Implement quota defaults command for KB
kingbird quota defaults list the default global quotas for a tenant. Add test-case for the same. Added profile related things. Change-Id: I1a6b04fdf3ef7f7fa9aa61c8da9311c7e4c4a5f2
This commit is contained in:
parent
516b739613
commit
450695bd30
|
@ -0,0 +1,55 @@
|
|||
# Copyright (c) 2016 Ericsson AB
|
||||
#
|
||||
# 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 json
|
||||
|
||||
|
||||
class Resource(object):
|
||||
# This will be overridden by the actual resource
|
||||
resource_name = 'Something'
|
||||
|
||||
def __init__(self, manager, data, values):
|
||||
self.manager = manager
|
||||
self._data = data
|
||||
self._values = values
|
||||
|
||||
|
||||
class ResourceManager(object):
|
||||
resource_class = None
|
||||
|
||||
def __init__(self, http_client):
|
||||
self.http_client = http_client
|
||||
|
||||
def _list(self, url, response_key=None):
|
||||
resp = self.http_client.get(url)
|
||||
if resp.status_code != 200:
|
||||
self._raise_api_exception(resp)
|
||||
json_response_key = get_json(resp)
|
||||
json_objects = [json_response_key[item] for item in json_response_key]
|
||||
|
||||
resource = []
|
||||
for json_object in json_objects:
|
||||
for resource_data in json_object:
|
||||
resource.append(self.resource_class(self, resource_data,
|
||||
json_object[resource_data]))
|
||||
return resource
|
||||
|
||||
|
||||
def get_json(response):
|
||||
"""Get JSON representation of response."""
|
||||
json_field_or_function = getattr(response, 'json', None)
|
||||
if callable(json_field_or_function):
|
||||
return response.json()
|
||||
else:
|
||||
return json.loads(response.content)
|
|
@ -19,6 +19,7 @@ import six
|
|||
import osprofiler.profiler
|
||||
|
||||
from kingbirdclient.api import httpclient
|
||||
from kingbirdclient.api.v1 import quota_manager as qm
|
||||
|
||||
_DEFAULT_KINGBIRD_URL = "http://localhost:8118/v1.0"
|
||||
|
||||
|
@ -73,6 +74,9 @@ class Client(object):
|
|||
insecure=insecure
|
||||
)
|
||||
|
||||
# Create all resource managers
|
||||
self.quota_manager = qm.quota_manager(self.http_client)
|
||||
|
||||
|
||||
def authenticate(kingbird_url=None, username=None,
|
||||
api_key=None, project_name=None, auth_url=None,
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright (c) 2016 Ericsson AB.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 kingbirdclient.api import base
|
||||
|
||||
|
||||
class Quota(base.Resource):
|
||||
resource_name = 'os-quota-sets'
|
||||
|
||||
|
||||
class quota_manager(base.ResourceManager):
|
||||
resource_class = Quota
|
||||
|
||||
def list_defaults(self):
|
||||
tenant = self.http_client.project_id
|
||||
url = '/%s/os-quota-sets/defaults' % tenant
|
||||
return self._list(url)
|
|
@ -0,0 +1,51 @@
|
|||
# Copyright (c) 2016 Ericsson AB
|
||||
# All Rights Reserved
|
||||
#
|
||||
# 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 abc
|
||||
|
||||
from osc_lib.command import command
|
||||
import six
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class KingbirdLister(command.Lister):
|
||||
@abc.abstractmethod
|
||||
def _get_format_function(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@abc.abstractmethod
|
||||
def _get_resources(self, parsed_args):
|
||||
"""Get a list of API resources (e.g. using client)."""
|
||||
raise NotImplementedError
|
||||
|
||||
def _validate_parsed_args(self, parsed_args):
|
||||
# No-op by default.
|
||||
pass
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self._validate_parsed_args(parsed_args)
|
||||
f = self._get_format_function()
|
||||
|
||||
ret = self._get_resources(parsed_args)
|
||||
if not isinstance(ret, list):
|
||||
ret = [ret]
|
||||
|
||||
data = [f(r)[1] for r in ret]
|
||||
|
||||
if data:
|
||||
return f()[0], data
|
||||
else:
|
||||
return f()
|
|
@ -0,0 +1,44 @@
|
|||
# Copyright (c) 2016 Ericsson AB.
|
||||
#
|
||||
# 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 kingbirdclient.commands.v1 import base
|
||||
|
||||
|
||||
def format(quotas=None):
|
||||
columns = (
|
||||
'Quota',
|
||||
'Limit'
|
||||
)
|
||||
|
||||
if quotas:
|
||||
data = (
|
||||
quotas._data,
|
||||
quotas._values,
|
||||
)
|
||||
|
||||
else:
|
||||
data = (tuple('<none>' for _ in range(len(columns))),)
|
||||
|
||||
return columns, data
|
||||
|
||||
|
||||
class ListDefaults(base.KingbirdLister):
|
||||
"""List all default quotas."""
|
||||
|
||||
def _get_format_function(self):
|
||||
return format
|
||||
|
||||
def _get_resources(self, parsed_args):
|
||||
kingbird_client = self.app.client_manager.sync_engine
|
||||
return kingbird_client.quota_manager.list_defaults()
|
|
@ -29,7 +29,7 @@ from cliff import commandmanager
|
|||
from osc_lib.command import command
|
||||
|
||||
import argparse
|
||||
|
||||
from kingbirdclient.commands.v1 import quota_manager as qm
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -290,6 +290,19 @@ class KingbirdShell(app.App):
|
|||
'(Env: KINGBIRDCLIENT_INSECURE)'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--profile',
|
||||
dest='profile',
|
||||
metavar='HMAC_KEY',
|
||||
help='HMAC key to use for encrypting context data for performance '
|
||||
'profiling of operation. This key should be one of the '
|
||||
'values configured for the osprofiler middleware in kingbird,'
|
||||
'it is specified in the profiler section of the kingbird '
|
||||
'configuration (i.e. /etc/kingbird/kingbird.conf). '
|
||||
'Without the key, profiling will not be triggered even if '
|
||||
'osprofiler is enabled on the server side.'
|
||||
)
|
||||
|
||||
return parser
|
||||
|
||||
def initialize_app(self, argv):
|
||||
|
@ -337,7 +350,8 @@ class KingbirdShell(app.App):
|
|||
service_type=self.options.service_type,
|
||||
auth_token=self.options.token,
|
||||
cacert=self.options.cacert,
|
||||
insecure=self.options.insecure
|
||||
insecure=self.options.insecure,
|
||||
profile=self.options.profile
|
||||
)
|
||||
|
||||
if not self.options.auth_url and not skip_auth:
|
||||
|
@ -348,6 +362,15 @@ class KingbirdShell(app.App):
|
|||
" default url with --os-auth-system or env[OS_AUTH_SYSTEM]")
|
||||
)
|
||||
|
||||
# Adding client_manager variable to make kingbird client work with
|
||||
# unified OpenStack client.
|
||||
ClientManager = type(
|
||||
'ClientManager',
|
||||
(object,),
|
||||
dict(sync_engine=self.client)
|
||||
)
|
||||
self.client_manager = ClientManager()
|
||||
|
||||
def _set_shell_commands(self, cmds_dict):
|
||||
for k, v in cmds_dict.items():
|
||||
self.command_manager.add_command(k, v)
|
||||
|
@ -370,6 +393,7 @@ class KingbirdShell(app.App):
|
|||
def _get_commands_v1():
|
||||
return {
|
||||
'bash-completion': BashCompletionCommand,
|
||||
'quota defaults': qm.ListDefaults,
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ class BaseClientTest(unittest2.TestCase):
|
|||
class BaseCommandTest(unittest2.TestCase):
|
||||
def setUp(self):
|
||||
self.app = mock.Mock()
|
||||
self.client = self.app.client_manager.workflow_engine
|
||||
self.client = self.app.client_manager.sync_engine
|
||||
|
||||
def call(self, command, app_args=[], prog_name=''):
|
||||
cmd = command(self.app, app_args)
|
||||
|
|
|
@ -31,7 +31,7 @@ class TestShell(base.BaseShellTests):
|
|||
@mock.patch('kingbirdclient.api.client.determine_client_version')
|
||||
def test_default_kingbird_version(self, mock):
|
||||
default_version = 'v1.0'
|
||||
self.shell('quota-defaults')
|
||||
self.shell('quota defaults')
|
||||
self.assertTrue(mock.called)
|
||||
kingbird_version = mock.call_args
|
||||
self.assertEqual(default_version, kingbird_version[0][0])
|
||||
|
@ -43,7 +43,7 @@ class TestShell(base.BaseShellTests):
|
|||
'--os-username=admin '
|
||||
'--os-password=1234 '
|
||||
'--os-tenant-name=admin '
|
||||
'quota-defaults'
|
||||
'quota defaults'
|
||||
)
|
||||
self.assertTrue(mock.called)
|
||||
params = mock.call_args
|
||||
|
@ -57,7 +57,7 @@ class TestShell(base.BaseShellTests):
|
|||
'--os-username=admin '
|
||||
'--os-password=1234 '
|
||||
'--os-tenant-name=admin '
|
||||
'quota-defaults'
|
||||
'quota defaults'
|
||||
)
|
||||
self.assertTrue(mock.called)
|
||||
params = mock.call_args
|
||||
|
@ -74,7 +74,7 @@ class TestShell(base.BaseShellTests):
|
|||
|
||||
@mock.patch('kingbirdclient.api.client.client')
|
||||
def test_kb_default_service_type(self, mock):
|
||||
self.shell('quota-defaults')
|
||||
self.shell('quota defaults')
|
||||
self.assertTrue(mock.called)
|
||||
params = mock.call_args
|
||||
# Default service type is synchronization
|
||||
|
@ -89,7 +89,7 @@ class TestShell(base.BaseShellTests):
|
|||
|
||||
@mock.patch('kingbirdclient.api.client.client')
|
||||
def test_kb_default_endpoint_type(self, mock):
|
||||
self.shell('quota-defaults')
|
||||
self.shell('quota defaults')
|
||||
self.assertTrue(mock.called)
|
||||
params = mock.call_args
|
||||
self.assertEqual('publicURL', params[1]['endpoint_type'])
|
||||
|
@ -98,7 +98,7 @@ class TestShell(base.BaseShellTests):
|
|||
def test_os_auth_token(self, mock):
|
||||
self.shell(
|
||||
'--os-auth-token=abcd1234 '
|
||||
'quota-defaults'
|
||||
'quota defaults'
|
||||
)
|
||||
self.assertTrue(mock.called)
|
||||
params = mock.call_args
|
||||
|
@ -107,7 +107,7 @@ class TestShell(base.BaseShellTests):
|
|||
@mock.patch('kingbirdclient.api.client.client')
|
||||
def test_command_without_kingbird_url(self, mock):
|
||||
self.shell(
|
||||
'quota-defaults'
|
||||
'quota defaults'
|
||||
)
|
||||
self.assertTrue(mock.called)
|
||||
params = mock.call_args
|
||||
|
@ -126,8 +126,22 @@ class TestShell(base.BaseShellTests):
|
|||
@mock.patch('kingbirdclient.api.client.client')
|
||||
def test_command_without_project_name(self, mock):
|
||||
self.shell(
|
||||
'quota-defaults'
|
||||
'quota defaults'
|
||||
)
|
||||
self.assertTrue(mock.called)
|
||||
params = mock.call_args
|
||||
self.assertEqual('', params[1]['project_name'])
|
||||
|
||||
@mock.patch('kingbirdclient.api.client.client')
|
||||
def test_kingbird_profile(self, mock):
|
||||
self.shell('--profile=SECRET_HMAC_KEY quota defaults')
|
||||
self.assertTrue(mock.called)
|
||||
params = mock.call_args
|
||||
self.assertEqual('SECRET_HMAC_KEY', params[1]['profile'])
|
||||
|
||||
@mock.patch('kingbirdclient.api.client.client')
|
||||
def test_kingbird_without_profile(self, mock):
|
||||
self.shell('quota defaults')
|
||||
self.assertTrue(mock.called)
|
||||
params = mock.call_args
|
||||
self.assertEqual(None, params[1]['profile'])
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# Copyright (c) 2016 Ericsson AB.
|
||||
#
|
||||
# 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 mock
|
||||
|
||||
from kingbirdclient.api.v1 import quota_manager as qm
|
||||
from kingbirdclient.commands.v1 import quota_manager as quota_cmd
|
||||
from kingbirdclient.tests import base
|
||||
|
||||
QUOTAS_DICT = {
|
||||
'Quota': 'fake_item',
|
||||
'Limit': '123'
|
||||
}
|
||||
|
||||
QUOTAMANAGER = qm.Quota(mock, QUOTAS_DICT['Quota'],
|
||||
QUOTAS_DICT['Limit'])
|
||||
|
||||
|
||||
class TestCLIQuotaManagerV1(base.BaseCommandTest):
|
||||
|
||||
def test_list_defaults(self):
|
||||
self.client.quota_manager.list_defaults.return_value = [QUOTAMANAGER]
|
||||
actual_quota = self.call(quota_cmd.ListDefaults)
|
||||
self.assertEqual([('fake_item', '123')], actual_quota[1])
|
||||
|
||||
def test_negative_list_defaults(self):
|
||||
self.client.quota_manager.list_defaults.return_value = []
|
||||
actual_quota = self.call(quota_cmd.ListDefaults)
|
||||
self.assertEqual((('<none>', '<none>'),), actual_quota[1])
|
Loading…
Reference in New Issue