Merge "Implement support for registered limits"
This commit is contained in:
commit
d177727a6e
140
doc/source/cli/command-objects/registered-limit.rst
Normal file
140
doc/source/cli/command-objects/registered-limit.rst
Normal file
@ -0,0 +1,140 @@
|
||||
================
|
||||
registered limit
|
||||
================
|
||||
|
||||
Identity v3
|
||||
|
||||
Registered limits are used to define default limits for resources within a
|
||||
deployment.
|
||||
|
||||
registered limit create
|
||||
-----------------------
|
||||
|
||||
Create a new registered limit
|
||||
|
||||
.. program:: registered limit create
|
||||
.. code:: bash
|
||||
|
||||
openstack registered limit create
|
||||
[--description <description>]
|
||||
[--region <region>]
|
||||
--service <service>
|
||||
--default-limit <default-limit>
|
||||
<resource-name>
|
||||
|
||||
.. option:: --description <description>
|
||||
|
||||
Useful description of the registered limit or its purpose
|
||||
|
||||
.. option:: --region <region>
|
||||
|
||||
Region that the limit should be applied to
|
||||
|
||||
.. describe:: --service <service>
|
||||
|
||||
The service that is responsible for the resource being limited (required)
|
||||
|
||||
.. describe:: --default-limit <default-limit>
|
||||
|
||||
The default limit for projects to assume unless explicitly overridden
|
||||
(required)
|
||||
|
||||
.. describe:: <resource-name>
|
||||
|
||||
The name of the resource to limit (e.g. cores or volumes)
|
||||
|
||||
registered limit delete
|
||||
-----------------------
|
||||
|
||||
Delete registered limit(s)
|
||||
|
||||
.. program:: registered limit delete
|
||||
.. code:: bash
|
||||
|
||||
openstack registered limit delete
|
||||
<registered-limit-id> [<registered-limit-id> ...]
|
||||
|
||||
|
||||
.. describe:: <registered-limit-id>
|
||||
|
||||
Registered limit(s) to delete (ID)
|
||||
|
||||
registered limit list
|
||||
---------------------
|
||||
|
||||
List registered limits
|
||||
|
||||
.. program:: registered limit list
|
||||
.. code:: bash
|
||||
|
||||
openstack registered limit list
|
||||
[--service <service>]
|
||||
[--resource-name <resource-name>]
|
||||
[--region <region>]
|
||||
|
||||
.. option:: --service <service>
|
||||
|
||||
The service to filter the response by (name or ID)
|
||||
|
||||
.. option:: --resource-name <resource-name>
|
||||
|
||||
The name of the resource to filter the response by
|
||||
|
||||
.. option:: --region <region>
|
||||
|
||||
The region name to filter the response by
|
||||
|
||||
registered limit show
|
||||
---------------------
|
||||
|
||||
Display details about a registered limit
|
||||
|
||||
.. program:: registered limit show
|
||||
.. code:: bash
|
||||
|
||||
openstack registered limit show
|
||||
<registered-limit-id>
|
||||
|
||||
.. describe:: <registered-limit-id>
|
||||
|
||||
Registered limit to display (ID)
|
||||
|
||||
registered limit set
|
||||
--------------------
|
||||
|
||||
Update a registered limit
|
||||
|
||||
.. program:: registered limit set
|
||||
.. code:: bash
|
||||
|
||||
openstack registered limit set
|
||||
[--service <service>]
|
||||
[--resource-name <resource-name>]
|
||||
[--default-limit <default-limit>]
|
||||
[--description <description>]
|
||||
[--region <region>]
|
||||
<registered-limit-id>
|
||||
|
||||
.. option:: --service <service>
|
||||
|
||||
The service of the registered limit to update (ID or name)
|
||||
|
||||
.. option:: --resource-name <resource-name>
|
||||
|
||||
The name of the resource for the limit
|
||||
|
||||
.. option:: --default-limit <default-limit>
|
||||
|
||||
The default limit for projects to assume for a given resource
|
||||
|
||||
.. option:: --description <description>
|
||||
|
||||
A useful description of the limit or its purpose
|
||||
|
||||
.. option:: --region <region>
|
||||
|
||||
The region the limit should apply to
|
||||
|
||||
.. describe:: <registered-limit-id>
|
||||
|
||||
Registered limit to display (ID)
|
@ -95,7 +95,7 @@ python-heatclient==1.10.0
|
||||
python-ironic-inspector-client==1.5.0
|
||||
python-ironicclient==2.3.0
|
||||
python-karborclient==0.6.0
|
||||
python-keystoneclient==3.15.0
|
||||
python-keystoneclient==3.17.0
|
||||
python-mimeparse==1.6.0
|
||||
python-mistralclient==3.1.0
|
||||
python-muranoclient==0.8.2
|
||||
|
260
openstackclient/identity/v3/registered_limit.py
Normal file
260
openstackclient/identity/v3/registered_limit.py
Normal file
@ -0,0 +1,260 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Registered limits action implementations."""
|
||||
|
||||
import logging
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import exceptions
|
||||
from osc_lib import utils
|
||||
import six
|
||||
|
||||
from openstackclient.i18n import _
|
||||
from openstackclient.identity import common as common_utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CreateRegisteredLimit(command.ShowOne):
|
||||
_description = _("Create a registered limit")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CreateRegisteredLimit, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
metavar='<description>',
|
||||
help=_('Description of the registered limit'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--region',
|
||||
metavar='<region>',
|
||||
help=_('Region for the registered limit to affect'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--service',
|
||||
metavar='<service>',
|
||||
required=True,
|
||||
help=_('Service responsible for the resource to limit (required)'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--default-limit',
|
||||
type=int,
|
||||
metavar='<default-limit>',
|
||||
required=True,
|
||||
help=_('The default limit for the resources to assume (required)'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'resource_name',
|
||||
metavar='<resource-name>',
|
||||
help=_('The name of the resource to limit'),
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
identity_client = self.app.client_manager.identity
|
||||
|
||||
service = utils.find_resource(
|
||||
identity_client.services, parsed_args.service
|
||||
)
|
||||
region = None
|
||||
if parsed_args.region:
|
||||
region = utils.find_resource(
|
||||
identity_client.regions, parsed_args.region
|
||||
)
|
||||
|
||||
registered_limit = identity_client.registered_limits.create(
|
||||
service,
|
||||
parsed_args.resource_name,
|
||||
parsed_args.default_limit,
|
||||
description=parsed_args.description,
|
||||
region=region
|
||||
)
|
||||
|
||||
registered_limit._info.pop('links', None)
|
||||
return zip(*sorted(six.iteritems(registered_limit._info)))
|
||||
|
||||
|
||||
class DeleteRegisteredLimit(command.Command):
|
||||
_description = _("Delete a registered limit")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DeleteRegisteredLimit, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'registered_limit_id',
|
||||
metavar='<registered-limit-id>',
|
||||
nargs="+",
|
||||
help=_('Registered limit to delete (ID)'),
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
identity_client = self.app.client_manager.identity
|
||||
|
||||
errors = 0
|
||||
for registered_limit_id in parsed_args.registered_limit_id:
|
||||
try:
|
||||
identity_client.registered_limits.delete(registered_limit_id)
|
||||
except Exception as e:
|
||||
errors += 1
|
||||
from pprint import pprint
|
||||
pprint(type(e))
|
||||
LOG.error(_("Failed to delete registered limit with ID "
|
||||
"'%(id)s': %(e)s"),
|
||||
{'id': registered_limit_id, 'e': e})
|
||||
|
||||
if errors > 0:
|
||||
total = len(parsed_args.registered_limit_id)
|
||||
msg = (_("%(errors)s of %(total)s registered limits failed to "
|
||||
"delete.") % {'errors': errors, 'total': total})
|
||||
raise exceptions.CommandError(msg)
|
||||
|
||||
|
||||
class ListRegisteredLimit(command.Lister):
|
||||
_description = _("List registered limits")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListRegisteredLimit, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'--service',
|
||||
metavar='<service>',
|
||||
help=_('Service responsible for the resource to limit'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--resource-name',
|
||||
metavar='<resource-name>',
|
||||
dest='resource_name',
|
||||
help=_('The name of the resource to limit'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--region',
|
||||
metavar='<region>',
|
||||
help=_('Region for the limit to affect.'),
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
identity_client = self.app.client_manager.identity
|
||||
|
||||
service = None
|
||||
if parsed_args.service:
|
||||
service = common_utils.find_service(
|
||||
identity_client, parsed_args.service
|
||||
)
|
||||
region = None
|
||||
if parsed_args.region:
|
||||
region = utils.find_resource(
|
||||
identity_client.regions, parsed_args.region
|
||||
)
|
||||
|
||||
registered_limits = identity_client.registered_limits.list(
|
||||
service=service,
|
||||
resource_name=parsed_args.resource_name,
|
||||
region=region
|
||||
)
|
||||
|
||||
columns = (
|
||||
'ID', 'Service ID', 'Resource Name', 'Default Limit',
|
||||
'Description', 'Region ID'
|
||||
)
|
||||
return (
|
||||
columns,
|
||||
(utils.get_item_properties(s, columns) for s in registered_limits),
|
||||
)
|
||||
|
||||
|
||||
class SetRegisteredLimit(command.ShowOne):
|
||||
_description = _("Update information about a registered limit")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(SetRegisteredLimit, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'registered_limit_id',
|
||||
metavar='<registered-limit-id>',
|
||||
help=_('Registered limit to update (ID)'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--service',
|
||||
metavar='<service>',
|
||||
help=_('Service responsible for the resource to limit'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--resource-name',
|
||||
metavar='<resource-name>',
|
||||
help=_('The name of the resource to limit'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--default-limit',
|
||||
metavar='<default-limit>',
|
||||
type=int,
|
||||
help=_('The default limit for the resources to assume'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--description',
|
||||
metavar='<description>',
|
||||
help=_('Description of the registered limit'),
|
||||
)
|
||||
parser.add_argument(
|
||||
'--region',
|
||||
metavar='<region>',
|
||||
help=_('Region for the registered limit to affect.'),
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
identity_client = self.app.client_manager.identity
|
||||
|
||||
service = None
|
||||
if parsed_args.service:
|
||||
service = common_utils.find_service(
|
||||
identity_client, parsed_args.service
|
||||
)
|
||||
|
||||
region = None
|
||||
if parsed_args.region:
|
||||
region = utils.find_resource(
|
||||
identity_client.regions, parsed_args.region
|
||||
)
|
||||
|
||||
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._info.pop('links', None)
|
||||
return zip(*sorted(six.iteritems(registered_limit._info)))
|
||||
|
||||
|
||||
class ShowRegisteredLimit(command.ShowOne):
|
||||
_description = _("Display registered limit details")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ShowRegisteredLimit, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'registered_limit_id',
|
||||
metavar='<registered-limit-id>',
|
||||
help=_('Registered limit to display (ID)'),
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
identity_client = self.app.client_manager.identity
|
||||
registered_limit = identity_client.registered_limits.get(
|
||||
parsed_args.registered_limit_id
|
||||
)
|
||||
registered_limit._info.pop('links', None)
|
||||
return zip(*sorted(six.iteritems(registered_limit._info)))
|
@ -54,6 +54,11 @@ class IdentityTests(base.TestCase):
|
||||
'Auth URL']
|
||||
IMPLIED_ROLE_LIST_HEADERS = ['Prior Role ID', 'Prior Role Name',
|
||||
'Implied Role ID', 'Implied Role Name']
|
||||
REGISTERED_LIMIT_FIELDS = ['id', 'service_id', 'resource_name',
|
||||
'default_limit', 'description', 'region_id']
|
||||
REGISTERED_LIMIT_LIST_HEADERS = ['ID', 'Service ID', 'Resource Name',
|
||||
'Default Limit', 'Description',
|
||||
'Region ID']
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
@ -319,3 +324,35 @@ class IdentityTests(base.TestCase):
|
||||
items = self.parse_show(raw_output)
|
||||
self.assert_show_fields(items, self.SERVICE_PROVIDER_FIELDS)
|
||||
return service_provider
|
||||
|
||||
def _create_dummy_registered_limit(self, add_clean_up=True):
|
||||
service_name = self._create_dummy_service()
|
||||
resource_name = data_utils.rand_name('resource_name')
|
||||
params = {
|
||||
'service_name': service_name,
|
||||
'default_limit': 10,
|
||||
'resource_name': resource_name
|
||||
}
|
||||
raw_output = self.openstack(
|
||||
'registered limit create'
|
||||
' --service %(service_name)s'
|
||||
' --default-limit %(default_limit)s'
|
||||
' %(resource_name)s' % params
|
||||
)
|
||||
items = self.parse_show(raw_output)
|
||||
registered_limit_id = self._extract_value_from_items('id', items)
|
||||
|
||||
if add_clean_up:
|
||||
self.addCleanup(
|
||||
self.openstack,
|
||||
'registered limit delete %s' % registered_limit_id
|
||||
)
|
||||
|
||||
self.assert_show_fields(items, self.REGISTERED_LIMIT_FIELDS)
|
||||
return registered_limit_id
|
||||
|
||||
def _extract_value_from_items(self, key, items):
|
||||
for d in items:
|
||||
for k, v in d.iteritems():
|
||||
if k == key:
|
||||
return v
|
||||
|
@ -0,0 +1,184 @@
|
||||
# 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 tempest.lib.common.utils import data_utils
|
||||
|
||||
from openstackclient.tests.functional.identity.v3 import common
|
||||
|
||||
|
||||
class RegisteredLimitTestCase(common.IdentityTests):
|
||||
|
||||
def test_registered_limit_create_with_service_name(self):
|
||||
self._create_dummy_registered_limit()
|
||||
|
||||
def test_registered_limit_create_with_service_id(self):
|
||||
service_name = self._create_dummy_service()
|
||||
raw_output = self.openstack(
|
||||
'service show'
|
||||
' %(service_name)s' % {'service_name': service_name}
|
||||
)
|
||||
service_items = self.parse_show(raw_output)
|
||||
service_id = self._extract_value_from_items('id', service_items)
|
||||
|
||||
raw_output = self.openstack(
|
||||
'registered limit create'
|
||||
' --service %(service_id)s'
|
||||
' --default-limit %(default_limit)s'
|
||||
' %(resource_name)s' % {
|
||||
'service_id': service_id,
|
||||
'default_limit': 10,
|
||||
'resource_name': 'cores'
|
||||
}
|
||||
)
|
||||
items = self.parse_show(raw_output)
|
||||
registered_limit_id = self._extract_value_from_items('id', items)
|
||||
self.addCleanup(
|
||||
self.openstack,
|
||||
'registered limit delete'
|
||||
' %(registered_limit_id)s' % {
|
||||
'registered_limit_id': registered_limit_id
|
||||
}
|
||||
)
|
||||
|
||||
self.assert_show_fields(items, self.REGISTERED_LIMIT_FIELDS)
|
||||
|
||||
def test_registered_limit_create_with_options(self):
|
||||
service_name = self._create_dummy_service()
|
||||
region_id = self._create_dummy_region()
|
||||
params = {
|
||||
'service_name': service_name,
|
||||
'resource_name': 'cores',
|
||||
'default_limit': 10,
|
||||
'description': 'default limit for cores',
|
||||
'region_id': region_id
|
||||
}
|
||||
|
||||
raw_output = self.openstack(
|
||||
'registered limit create'
|
||||
' --description \'%(description)s\''
|
||||
' --region %(region_id)s'
|
||||
' --service %(service_name)s'
|
||||
' --default-limit %(default_limit)s'
|
||||
' %(resource_name)s' % params
|
||||
)
|
||||
items = self.parse_show(raw_output)
|
||||
registered_limit_id = self._extract_value_from_items('id', items)
|
||||
self.addCleanup(
|
||||
self.openstack,
|
||||
'registered limit delete %(registered_limit_id)s' % {
|
||||
'registered_limit_id': registered_limit_id
|
||||
}
|
||||
)
|
||||
|
||||
self.assert_show_fields(items, self.REGISTERED_LIMIT_FIELDS)
|
||||
|
||||
def test_registered_limit_show(self):
|
||||
registered_limit_id = self._create_dummy_registered_limit()
|
||||
raw_output = self.openstack(
|
||||
'registered limit show %(registered_limit_id)s' % {
|
||||
'registered_limit_id': registered_limit_id
|
||||
}
|
||||
)
|
||||
items = self.parse_show(raw_output)
|
||||
self.assert_show_fields(items, self.REGISTERED_LIMIT_FIELDS)
|
||||
|
||||
def test_registered_limit_set_region_id(self):
|
||||
region_id = self._create_dummy_region()
|
||||
registered_limit_id = self._create_dummy_registered_limit()
|
||||
|
||||
params = {
|
||||
'registered_limit_id': registered_limit_id,
|
||||
'region_id': region_id
|
||||
}
|
||||
raw_output = self.openstack(
|
||||
'registered limit set'
|
||||
' %(registered_limit_id)s'
|
||||
' --region %(region_id)s' % params
|
||||
)
|
||||
items = self.parse_show(raw_output)
|
||||
self.assert_show_fields(items, self.REGISTERED_LIMIT_FIELDS)
|
||||
|
||||
def test_registered_limit_set_description(self):
|
||||
registered_limit_id = self._create_dummy_registered_limit()
|
||||
params = {
|
||||
'registered_limit_id': registered_limit_id,
|
||||
'description': 'updated description'
|
||||
}
|
||||
raw_output = self.openstack(
|
||||
'registered limit set'
|
||||
' %(registered_limit_id)s'
|
||||
' --description \'%(description)s\'' % params
|
||||
)
|
||||
items = self.parse_show(raw_output)
|
||||
self.assert_show_fields(items, self.REGISTERED_LIMIT_FIELDS)
|
||||
|
||||
def test_registered_limit_set_service(self):
|
||||
registered_limit_id = self._create_dummy_registered_limit()
|
||||
service_name = self._create_dummy_service()
|
||||
params = {
|
||||
'registered_limit_id': registered_limit_id,
|
||||
'service': service_name
|
||||
}
|
||||
raw_output = self.openstack(
|
||||
'registered limit set'
|
||||
' %(registered_limit_id)s'
|
||||
' --service %(service)s' % params
|
||||
)
|
||||
items = self.parse_show(raw_output)
|
||||
self.assert_show_fields(items, self.REGISTERED_LIMIT_FIELDS)
|
||||
|
||||
def test_registered_limit_set_default_limit(self):
|
||||
registered_limit_id = self._create_dummy_registered_limit()
|
||||
params = {
|
||||
'registered_limit_id': registered_limit_id,
|
||||
'default_limit': 20
|
||||
}
|
||||
raw_output = self.openstack(
|
||||
'registered limit set'
|
||||
' %(registered_limit_id)s'
|
||||
' --default-limit %(default_limit)s' % params
|
||||
)
|
||||
items = self.parse_show(raw_output)
|
||||
self.assert_show_fields(items, self.REGISTERED_LIMIT_FIELDS)
|
||||
|
||||
def test_registered_limit_set_resource_name(self):
|
||||
registered_limit_id = self._create_dummy_registered_limit()
|
||||
resource_name = data_utils.rand_name('resource_name')
|
||||
params = {
|
||||
'registered_limit_id': registered_limit_id,
|
||||
'resource_name': resource_name
|
||||
}
|
||||
raw_output = self.openstack(
|
||||
'registered limit set'
|
||||
' %(registered_limit_id)s'
|
||||
' --resource-name %(resource_name)s' % params
|
||||
)
|
||||
items = self.parse_show(raw_output)
|
||||
self.assert_show_fields(items, self.REGISTERED_LIMIT_FIELDS)
|
||||
|
||||
def test_registered_limit_list(self):
|
||||
self._create_dummy_registered_limit()
|
||||
raw_output = self.openstack('registered limit list')
|
||||
items = self.parse_listing(raw_output)
|
||||
self.assert_table_structure(items, self.REGISTERED_LIMIT_LIST_HEADERS)
|
||||
|
||||
def test_registered_limit_delete(self):
|
||||
registered_limit_id = self._create_dummy_registered_limit(
|
||||
add_clean_up=False
|
||||
)
|
||||
raw_output = self.openstack(
|
||||
'registered limit delete'
|
||||
' %(registered_limit_id)s' % {
|
||||
'registered_limit_id': registered_limit_id
|
||||
}
|
||||
)
|
||||
self.assertEqual(0, len(raw_output))
|
@ -486,6 +486,27 @@ APP_CRED_OPTIONS = {
|
||||
'secret': app_cred_secret
|
||||
}
|
||||
|
||||
registered_limit_id = 'registered-limit-id'
|
||||
registered_limit_default_limit = 10
|
||||
registered_limit_description = 'default limit of foobars'
|
||||
registered_limit_resource_name = 'foobars'
|
||||
REGISTERED_LIMIT = {
|
||||
'id': registered_limit_id,
|
||||
'default_limit': registered_limit_default_limit,
|
||||
'resource_name': registered_limit_resource_name,
|
||||
'service_id': service_id,
|
||||
'description': None,
|
||||
'region_id': None
|
||||
}
|
||||
REGISTERED_LIMIT_OPTIONS = {
|
||||
'id': registered_limit_id,
|
||||
'default_limit': registered_limit_default_limit,
|
||||
'resource_name': registered_limit_resource_name,
|
||||
'service_id': service_id,
|
||||
'description': registered_limit_description,
|
||||
'region_id': region_id
|
||||
}
|
||||
|
||||
|
||||
def fake_auth_ref(fake_token, fake_service=None):
|
||||
"""Create an auth_ref using keystoneauth's fixtures"""
|
||||
@ -578,6 +599,8 @@ class FakeIdentityv3Client(object):
|
||||
{})
|
||||
self.inference_rules = mock.Mock()
|
||||
self.inference_rules.resource_class = fakes.FakeResource(None, {})
|
||||
self.registered_limits = mock.Mock()
|
||||
self.registered_limits.resource_class = fakes.FakeResource(None, {})
|
||||
|
||||
|
||||
class FakeFederationManager(object):
|
||||
|
510
openstackclient/tests/unit/identity/v3/test_registered_limit.py
Normal file
510
openstackclient/tests/unit/identity/v3/test_registered_limit.py
Normal file
@ -0,0 +1,510 @@
|
||||
# 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
|
||||
|
||||
from keystoneauth1.exceptions import http as ksa_exceptions
|
||||
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):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRegisteredLimit, self).setUp()
|
||||
|
||||
identity_manager = self.app.client_manager.identity
|
||||
self.registered_limit_mock = identity_manager.registered_limits
|
||||
|
||||
self.services_mock = identity_manager.services
|
||||
self.services_mock.reset_mock()
|
||||
|
||||
self.regions_mock = identity_manager.regions
|
||||
self.regions_mock.reset_mock()
|
||||
|
||||
|
||||
class TestRegisteredLimitCreate(TestRegisteredLimit):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRegisteredLimitCreate, self).setUp()
|
||||
|
||||
self.service = fakes.FakeResource(
|
||||
None,
|
||||
copy.deepcopy(identity_fakes.SERVICE),
|
||||
loaded=True
|
||||
)
|
||||
self.services_mock.get.return_value = self.service
|
||||
|
||||
self.region = fakes.FakeResource(
|
||||
None,
|
||||
copy.deepcopy(identity_fakes.REGION),
|
||||
loaded=True
|
||||
)
|
||||
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
|
||||
)
|
||||
|
||||
resource_name = identity_fakes.registered_limit_resource_name
|
||||
default_limit = identity_fakes.registered_limit_default_limit
|
||||
arglist = [
|
||||
'--service', identity_fakes.service_id,
|
||||
'--default-limit', '10',
|
||||
resource_name,
|
||||
]
|
||||
|
||||
verifylist = [
|
||||
('service', identity_fakes.service_id),
|
||||
('default_limit', default_limit),
|
||||
('resource_name', 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
|
||||
)
|
||||
|
||||
collist = ('default_limit', 'description', 'id', 'region_id',
|
||||
'resource_name', 'service_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)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
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,
|
||||
'--description', description,
|
||||
'--service', identity_fakes.service_id,
|
||||
'--default-limit', '10',
|
||||
resource_name
|
||||
]
|
||||
|
||||
verifylist = [
|
||||
('region', identity_fakes.region_id),
|
||||
('description', description),
|
||||
('service', identity_fakes.service_id),
|
||||
('default_limit', default_limit),
|
||||
('resource_name', 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
|
||||
)
|
||||
|
||||
collist = ('default_limit', 'description', 'id', 'region_id',
|
||||
'resource_name', 'service_id')
|
||||
|
||||
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.assertEqual(datalist, data)
|
||||
|
||||
|
||||
class TestRegisteredLimitDelete(TestRegisteredLimit):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRegisteredLimitDelete, self).setUp()
|
||||
|
||||
self.cmd = registered_limit.DeleteRegisteredLimit(self.app, None)
|
||||
|
||||
def test_registered_limit_delete(self):
|
||||
self.registered_limit_mock.delete.return_value = None
|
||||
|
||||
arglist = [identity_fakes.registered_limit_id]
|
||||
verifylist = [
|
||||
('registered_limit_id', [identity_fakes.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.assertIsNone(result)
|
||||
|
||||
def test_registered_limit_delete_with_exception(self):
|
||||
return_value = ksa_exceptions.NotFound()
|
||||
self.registered_limit_mock.delete.side_effect = return_value
|
||||
|
||||
arglist = ['fake-registered-limit-id']
|
||||
verifylist = [
|
||||
('registered_limit_id', ['fake-registered-limit-id'])
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
try:
|
||||
self.cmd.take_action(parsed_args)
|
||||
self.fail('CommandError should be raised.')
|
||||
except exceptions.CommandError as e:
|
||||
self.assertEqual(
|
||||
'1 of 1 registered limits failed to delete.', str(e)
|
||||
)
|
||||
|
||||
|
||||
class TestRegisteredLimitShow(TestRegisteredLimit):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRegisteredLimitShow, self).setUp()
|
||||
|
||||
self.registered_limit_mock.get.return_value = fakes.FakeResource(
|
||||
None,
|
||||
copy.deepcopy(identity_fakes.REGISTERED_LIMIT),
|
||||
loaded=True
|
||||
)
|
||||
|
||||
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)
|
||||
]
|
||||
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
|
||||
)
|
||||
|
||||
collist = (
|
||||
'default_limit', 'description', 'id', 'region_id', 'resource_name',
|
||||
'service_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)
|
||||
|
||||
|
||||
class TestRegisteredLimitSet(TestRegisteredLimit):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRegisteredLimitSet, self).setUp()
|
||||
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
|
||||
)
|
||||
self.registered_limit_mock.update.return_value = fakes.FakeResource(
|
||||
None, registered_limit, loaded=True
|
||||
)
|
||||
|
||||
arglist = [
|
||||
'--description', identity_fakes.registered_limit_description,
|
||||
identity_fakes.registered_limit_id
|
||||
]
|
||||
verifylist = [
|
||||
('description', identity_fakes.registered_limit_description),
|
||||
('registered_limit_id', identity_fakes.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
|
||||
)
|
||||
|
||||
collist = (
|
||||
'default_limit', 'description', 'id', 'region_id', 'resource_name',
|
||||
'service_id'
|
||||
)
|
||||
self.assertEqual(collist, columns)
|
||||
datalist = (
|
||||
identity_fakes.registered_limit_default_limit,
|
||||
identity_fakes.registered_limit_description,
|
||||
identity_fakes.registered_limit_id,
|
||||
None,
|
||||
identity_fakes.registered_limit_resource_name,
|
||||
identity_fakes.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
|
||||
)
|
||||
|
||||
arglist = [
|
||||
'--default-limit', str(default_limit),
|
||||
identity_fakes.registered_limit_id
|
||||
]
|
||||
verifylist = [
|
||||
('default_limit', default_limit),
|
||||
('registered_limit_id', identity_fakes.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
|
||||
)
|
||||
|
||||
collist = (
|
||||
'default_limit', 'description', 'id', 'region_id', 'resource_name',
|
||||
'service_id'
|
||||
)
|
||||
self.assertEqual(collist, columns)
|
||||
datalist = (
|
||||
default_limit,
|
||||
None,
|
||||
identity_fakes.registered_limit_id,
|
||||
None,
|
||||
identity_fakes.registered_limit_resource_name,
|
||||
identity_fakes.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
|
||||
)
|
||||
|
||||
arglist = [
|
||||
'--resource-name', resource_name,
|
||||
identity_fakes.registered_limit_id
|
||||
]
|
||||
verifylist = [
|
||||
('resource_name', resource_name),
|
||||
('registered_limit_id', identity_fakes.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
|
||||
)
|
||||
|
||||
collist = (
|
||||
'default_limit', 'description', 'id', 'region_id', 'resource_name',
|
||||
'service_id'
|
||||
)
|
||||
self.assertEqual(collist, columns)
|
||||
datalist = (
|
||||
identity_fakes.registered_limit_default_limit,
|
||||
None,
|
||||
identity_fakes.registered_limit_id,
|
||||
None,
|
||||
resource_name,
|
||||
identity_fakes.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
|
||||
)
|
||||
self.services_mock.get.return_value = service
|
||||
|
||||
arglist = [
|
||||
'--service', service.id,
|
||||
identity_fakes.registered_limit_id
|
||||
]
|
||||
verifylist = [
|
||||
('service', service.id),
|
||||
('registered_limit_id', identity_fakes.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
|
||||
)
|
||||
|
||||
collist = (
|
||||
'default_limit', 'description', 'id', 'region_id', 'resource_name',
|
||||
'service_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,
|
||||
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
|
||||
)
|
||||
self.regions_mock.get.return_value = region
|
||||
|
||||
arglist = [
|
||||
'--region', region.id,
|
||||
identity_fakes.registered_limit_id
|
||||
]
|
||||
verifylist = [
|
||||
('region', region.id),
|
||||
('registered_limit_id', identity_fakes.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
|
||||
)
|
||||
|
||||
collist = (
|
||||
'default_limit', 'description', 'id', 'region_id', 'resource_name',
|
||||
'service_id'
|
||||
)
|
||||
self.assertEqual(collist, columns)
|
||||
datalist = (
|
||||
identity_fakes.registered_limit_default_limit,
|
||||
None,
|
||||
identity_fakes.registered_limit_id,
|
||||
region.id,
|
||||
identity_fakes.registered_limit_resource_name,
|
||||
identity_fakes.service_id
|
||||
)
|
||||
self.assertEqual(datalist, data)
|
||||
|
||||
|
||||
class TestRegisteredLimitList(TestRegisteredLimit):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRegisteredLimitList, self).setUp()
|
||||
|
||||
self.registered_limit_mock.get.return_value = fakes.FakeResource(
|
||||
None,
|
||||
copy.deepcopy(identity_fakes.REGISTERED_LIMIT),
|
||||
loaded=True
|
||||
)
|
||||
|
||||
self.cmd = registered_limit.ShowRegisteredLimit(self.app, None)
|
||||
|
||||
def test_limit_show(self):
|
||||
arglist = [identity_fakes.registered_limit_id]
|
||||
verifylist = [
|
||||
('registered_limit_id', identity_fakes.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
|
||||
)
|
||||
|
||||
collist = (
|
||||
'default_limit', 'description', 'id', 'region_id', 'resource_name',
|
||||
'service_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)
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
[`bp unified-limits <https://blueprints.launchpad.net/keystone/+spec/unified-limit>`_]
|
||||
Support has been added for managing registered limits in keystone via the
|
||||
``registered limit`` command. Registered limits define limits of resources
|
||||
for projects to assume by default.
|
@ -12,6 +12,6 @@ osc-lib>=1.10.0 # Apache-2.0
|
||||
oslo.i18n>=3.15.3 # Apache-2.0
|
||||
oslo.utils>=3.33.0 # Apache-2.0
|
||||
python-glanceclient>=2.8.0 # Apache-2.0
|
||||
python-keystoneclient>=3.15.0 # Apache-2.0
|
||||
python-keystoneclient>=3.17.0 # Apache-2.0
|
||||
python-novaclient>=9.1.0 # Apache-2.0
|
||||
python-cinderclient>=3.3.0 # Apache-2.0
|
||||
|
@ -301,6 +301,12 @@ openstack.identity.v3 =
|
||||
region_set = openstackclient.identity.v3.region:SetRegion
|
||||
region_show = openstackclient.identity.v3.region:ShowRegion
|
||||
|
||||
registered_limit_create = openstackclient.identity.v3.registered_limit:CreateRegisteredLimit
|
||||
registered_limit_delete = openstackclient.identity.v3.registered_limit:DeleteRegisteredLimit
|
||||
registered_limit_list = openstackclient.identity.v3.registered_limit:ListRegisteredLimit
|
||||
registered_limit_set = openstackclient.identity.v3.registered_limit:SetRegisteredLimit
|
||||
registered_limit_show = openstackclient.identity.v3.registered_limit:ShowRegisteredLimit
|
||||
|
||||
request_token_authorize = openstackclient.identity.v3.token:AuthorizeRequestToken
|
||||
request_token_create = openstackclient.identity.v3.token:CreateRequestToken
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user