Add support for /v2/scope API endpoint to the client

This allows to retrieve the state of one or several scopes through the API via
the client library and cli tool.

Change-Id: I53995062fe76100f6dfcc672af482f653cc85bde
Story: 2005395
Task: 30795
Depends-On: https://review.opendev.org/#/c/658073/
This commit is contained in:
Luka Peschke 2019-05-10 12:07:14 +02:00
parent b29fefaf8d
commit 7e7d25dd78
17 changed files with 209 additions and 7 deletions

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
from cloudkittyclient.tests.functional.v1 import base
from cloudkittyclient.tests.functional import base
class CkCollectorTest(base.BaseFunctionalTest):

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
from cloudkittyclient.tests.functional.v1 import base
from cloudkittyclient.tests.functional import base
class CkHashmapTest(base.BaseFunctionalTest):

View File

@ -15,7 +15,7 @@
#
import jsonpath_rw_ext as jp
from cloudkittyclient.tests.functional.v1 import base
from cloudkittyclient.tests.functional import base
class CkInfoTest(base.BaseFunctionalTest):

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
from cloudkittyclient.tests.functional.v1 import base
from cloudkittyclient.tests.functional import base
class CkPyscriptTest(base.BaseFunctionalTest):

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
from cloudkittyclient.tests.functional.v1 import base
from cloudkittyclient.tests.functional import base
class CkRatingTest(base.BaseFunctionalTest):

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
from cloudkittyclient.tests.functional.v1 import base
from cloudkittyclient.tests.functional import base
class CkReportTest(base.BaseFunctionalTest):

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
#
from cloudkittyclient.tests.functional.v1 import base
from cloudkittyclient.tests.functional import base
class CkStorageTest(base.BaseFunctionalTest):

View File

@ -0,0 +1,35 @@
# Copyright 2019 Objectif Libre
#
# 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 cloudkittyclient.tests.functional import base
class CkScopeTest(base.BaseFunctionalTest):
def __init__(self, *args, **kwargs):
super(CkScopeTest, self).__init__(*args, **kwargs)
self.runner = self.cloudkitty
def test_scope_state_get(self):
return True
# FIXME(peschk_l): Uncomment and update this once there is a way to set
# the state of a scope through the client
# resp = self.runner('scope state get')
class OSCScopeTest(CkScopeTest):
def __init__(self, *args, **kwargs):
super(OSCScopeTest, self).__init__(*args, **kwargs)
self.runner = self.openstack

View File

@ -0,0 +1,24 @@
# Copyright 2019 objectif Libre
#
# 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 cloudkittyclient.tests import utils
from cloudkittyclient.v2 import scope
class BaseAPIEndpointTestCase(utils.BaseTestCase):
def setUp(self):
super(BaseAPIEndpointTestCase, self).setUp()
self.api_client = utils.FakeHTTPClient()
self.scope = scope.ScopeManager(self.api_client)

View File

@ -0,0 +1,31 @@
# Copyright 2019 Objectif Libre
#
# 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 cloudkittyclient.tests.unit.v2 import base
class TestScope(base.BaseAPIEndpointTestCase):
def test_get_scope(self):
self.scope.get_scope_state()
self.api_client.get.assert_called_once_with('/v2/scope')
def test_get_scope_with_args(self):
self.scope.get_scope_state(offset=10, limit=10)
try:
self.api_client.get.assert_called_once_with(
'/v2/scope?limit=10&offset=10')
except AssertionError:
self.api_client.get.assert_called_once_with(
'/v2/scope?offset=10&limit=10')

View File

@ -14,6 +14,7 @@
# under the License.
#
from cloudkittyclient.v1 import client
from cloudkittyclient.v2 import scope
# NOTE(peschk_l) v2 client needs to implement v1 until the v1 API has been
@ -33,3 +34,5 @@ class Client(client.Client):
insecure=insecure,
**kwargs
)
self.scope = scope.ScopeManager(self.api_client)

View File

@ -0,0 +1,50 @@
# Copyright 2019 Objectif Libre
#
# 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 cloudkittyclient.common import base
class ScopeManager(base.BaseManager):
"""Class used to handle /v2/scope endpoint"""
url = '/v2/scope'
def get_scope_state(self, **kwargs):
"""Returns a paginated list of scopes along with their state.
Some optional filters can be provided.
:param offset: Index of the first scope that should be returned.
:type offset: int
:param limit: Maximal number of scopes to return.
:type limit: int
:param collector: Optional collector to filter on.
:type collector: str or list of str
:param fetcher: Optional fetcher to filter on.
:type fetcher: str or list of str
:param scope_id: Optional scope_id to filter on.
:type scope_id: str or list of str
:param scope_key: Optional scope_key to filter on.
:type scope_key: str or list of str
"""
for key in ('collector', 'fetcher', 'scope_id', 'scope_key'):
if key in kwargs.keys():
if isinstance(kwargs[key], list):
kwargs[key] = ','.join(kwargs[key])
authorized_args = [
'offset', 'limit', 'collector', 'fetcher', 'scope_id', 'scope_key']
url = self.get_url(None, kwargs, authorized_args=authorized_args)
return self.api_client.get(url).json()

View File

@ -0,0 +1,55 @@
# Copyright 2019 Objectif Libre
#
# 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 cliff import lister
from cloudkittyclient import utils
class CliScopeStateGet(lister.Lister):
"""Get information about current state of several scopes."""
info_columns = [
('scope_id', 'Scope ID'),
('scope_key', 'Scope Key'),
('collector', 'Collector'),
('fetcher', 'Fetcher'),
('state', 'State')
]
def get_parser(self, prog_name):
parser = super(CliScopeStateGet, self).get_parser(prog_name)
for col in self.info_columns[:-1]:
parser.add_argument(
'--' + col[0].replace('_', '-'), type=str,
action='append', help='Optional filter on ' + col[1])
parser.add_argument('--offset', type=int, default=0,
help='Index of the first scope')
parser.add_argument('--limit', type=int, default=100,
help='Maximal number of scopes')
return parser
def take_action(self, parsed_args):
resp = utils.get_client_from_osc(self).scope.get_scope_state(
offset=parsed_args.offset,
limit=parsed_args.limit,
collector=parsed_args.collector,
fetcher=parsed_args.fetcher,
scope_id=parsed_args.scope_id,
scope_key=parsed_args.scope_key,
)
values = utils.list_to_cols(resp['results'], self.info_columns)
return [col[1] for col in self.info_columns], values

View File

@ -86,6 +86,8 @@ openstack.rating.v1 =
rating_pyscript_delete = cloudkittyclient.v1.rating.pyscripts_cli:CliDeleteScript
openstack.rating.v2 =
rating_scope_state_get = cloudkittyclient.v2.scope_cli:CliScopeStateGet
rating_total_get = cloudkittyclient.v1.report_cli:CliTotalGet
rating_summary_get = cloudkittyclient.v1.report_cli:CliSummaryGet
rating_report_tenant_list = cloudkittyclient.v1.report_cli:CliTenantList
@ -142,6 +144,8 @@ openstack.rating.v2 =
cloudkittyclient =
scope_state_get = cloudkittyclient.v2.scope_cli:CliScopeStateGet
total_get = cloudkittyclient.v1.report_cli:CliTotalGet
summary_get = cloudkittyclient.v1.report_cli:CliSummaryGet
report_tenant_list = cloudkittyclient.v1.report_cli:CliTenantList