Neutron Limits API Infrastructure
- Adding JSON response model - Adding response model meta test - Adding API client and behavior GET method - Adding config and constants file - Adding composite Change-Id: Ic0adefc67c1ceac1bb03bc4ec784e111ea4cdfc2
This commit is contained in:
@@ -0,0 +1,15 @@
|
|||||||
|
"""
|
||||||
|
Copyright 2015 Rackspace
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
"""
|
||||||
|
Copyright 2015 Rackspace
|
||||||
|
|
||||||
|
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 time
|
||||||
|
|
||||||
|
from cloudcafe.networking.networks.common.behaviors \
|
||||||
|
import NetworkingBaseBehaviors, NetworkingResponse
|
||||||
|
from cloudcafe.networking.networks.common.exceptions \
|
||||||
|
import ResourceGetException
|
||||||
|
from cloudcafe.networking.networks.extensions.limits_api.constants \
|
||||||
|
import LimitsResponseCodes
|
||||||
|
|
||||||
|
|
||||||
|
class LimitsBehaviors(NetworkingBaseBehaviors):
|
||||||
|
|
||||||
|
def __init__(self, limits_client, limits_config):
|
||||||
|
super(LimitsBehaviors, self).__init__()
|
||||||
|
self.config = limits_config
|
||||||
|
self.client = limits_client
|
||||||
|
|
||||||
|
def get_limits(self, page_reverse=None,
|
||||||
|
resource_get_attempts=None,
|
||||||
|
raise_exception=False, poll_interval=None):
|
||||||
|
"""
|
||||||
|
@summary: get rate limits
|
||||||
|
@param page_reverse: direction of the page
|
||||||
|
@type page_reverse: bool
|
||||||
|
@param resource_get_attempts: number of API retries
|
||||||
|
@type resource_get_attempts: int
|
||||||
|
@param raise_exception: flag to raise an exception if the get
|
||||||
|
limits call was not as expected or to return None
|
||||||
|
@type raise_exception: bool
|
||||||
|
@param poll_interval: sleep time interval between API retries
|
||||||
|
@type poll_interval: int
|
||||||
|
@return: NetworkingResponse object with api response and failure list
|
||||||
|
@rtype: common.behaviors.NetworkingResponse
|
||||||
|
"""
|
||||||
|
poll_interval = poll_interval or self.config.api_poll_interval
|
||||||
|
resource_get_attempts = (resource_get_attempts or
|
||||||
|
self.config.api_retries)
|
||||||
|
|
||||||
|
result = NetworkingResponse()
|
||||||
|
err_msg = 'Limits GET failure'
|
||||||
|
for attempt in range(resource_get_attempts):
|
||||||
|
self._log.debug('Attempt {0} of {1} with limits GET'.
|
||||||
|
format(attempt + 1, resource_get_attempts))
|
||||||
|
|
||||||
|
resp = self.client.get_limits(page_reverse=page_reverse)
|
||||||
|
resp_check = self.check_response(resp=resp,
|
||||||
|
status_code=LimitsResponseCodes.GET_LIMITS,
|
||||||
|
label='', message=err_msg)
|
||||||
|
result.response = resp
|
||||||
|
|
||||||
|
# resp_check will have the response failure or None if no failure
|
||||||
|
if resp_check is None:
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Failures will be an empty list if the list was successful the
|
||||||
|
# first time
|
||||||
|
result.failures.append(resp_check)
|
||||||
|
time.sleep(poll_interval)
|
||||||
|
|
||||||
|
else:
|
||||||
|
err_msg = (
|
||||||
|
'Unable to GET limits after {0} attempts: '
|
||||||
|
'{1}').format(resource_get_attempts, result.failures)
|
||||||
|
self._log.error(err_msg)
|
||||||
|
if raise_exception:
|
||||||
|
raise ResourceGetException(err_msg)
|
||||||
|
return result
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
"""
|
||||||
|
Copyright 2015 Rackspace
|
||||||
|
|
||||||
|
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 cafe.engine.http.client import AutoMarshallingHTTPClient
|
||||||
|
from cloudcafe.networking.networks.extensions.limits_api.models.response \
|
||||||
|
import Limits
|
||||||
|
|
||||||
|
|
||||||
|
class LimitsClient(AutoMarshallingHTTPClient):
|
||||||
|
|
||||||
|
def __init__(self, url, auth_token, serialize_format=None,
|
||||||
|
deserialize_format=None, tenant_id=None):
|
||||||
|
"""
|
||||||
|
@param url: Base URL for the networks service
|
||||||
|
@type url: string
|
||||||
|
@param auth_token: Auth token to be used for all requests
|
||||||
|
@type auth_token: string
|
||||||
|
@param serialize_format: Format for serializing requests
|
||||||
|
@type serialize_format: string
|
||||||
|
@param deserialize_format: Format for de-serializing responses
|
||||||
|
@type deserialize_format: string
|
||||||
|
@param tenant_id: optional tenant id to be included in the
|
||||||
|
header if given
|
||||||
|
@type tenant_id: string
|
||||||
|
"""
|
||||||
|
super(LimitsClient, self).__init__(serialize_format,
|
||||||
|
deserialize_format)
|
||||||
|
self.auth_token = auth_token
|
||||||
|
self.default_headers['X-Auth-Token'] = auth_token
|
||||||
|
ct = '{content_type}/{content_subtype}'.format(
|
||||||
|
content_type='application',
|
||||||
|
content_subtype=self.serialize_format)
|
||||||
|
accept = '{content_type}/{content_subtype}'.format(
|
||||||
|
content_type='application',
|
||||||
|
content_subtype=self.deserialize_format)
|
||||||
|
self.default_headers['Content-Type'] = ct
|
||||||
|
self.default_headers['Accept'] = accept
|
||||||
|
if tenant_id:
|
||||||
|
self.default_headers['X-Auth-Project-Id'] = tenant_id
|
||||||
|
self.url = url
|
||||||
|
self.limits_url = '{url}/limits'.format(url=self.url)
|
||||||
|
|
||||||
|
def get_limits(self, page_reverse=None, requestslib_kwargs=None):
|
||||||
|
"""
|
||||||
|
@summary: Shows rate limit user information
|
||||||
|
@return: get limits response
|
||||||
|
@rtype: Requests.response
|
||||||
|
"""
|
||||||
|
params = {'page_reverse': page_reverse}
|
||||||
|
url = self.limits_url
|
||||||
|
resp = self.request('GET', url, params=params,
|
||||||
|
response_entity_type=Limits,
|
||||||
|
requestslib_kwargs=requestslib_kwargs)
|
||||||
|
return resp
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
"""
|
||||||
|
Copyright 2015 Rackspace
|
||||||
|
|
||||||
|
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 cloudcafe.networking.networks.composites import _NetworkingAuthComposite
|
||||||
|
from cloudcafe.networking.networks.extensions.limits_api.behaviors \
|
||||||
|
import LimitsBehaviors
|
||||||
|
from cloudcafe.networking.networks.extensions.limits_api.client \
|
||||||
|
import LimitsClient
|
||||||
|
from cloudcafe.networking.networks.extensions.limits_api.config \
|
||||||
|
import LimitsConfig
|
||||||
|
|
||||||
|
|
||||||
|
class LimitsComposite(object):
|
||||||
|
networking_auth_composite = _NetworkingAuthComposite
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
auth_composite = self.networking_auth_composite()
|
||||||
|
self.url = auth_composite.networking_url
|
||||||
|
self.user = auth_composite._auth_user_config
|
||||||
|
self.config = LimitsConfig()
|
||||||
|
self.client = LimitsClient(**auth_composite.client_args)
|
||||||
|
|
||||||
|
self.behaviors = LimitsBehaviors(
|
||||||
|
limits_client=self.client, limits_config=self.config)
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
"""
|
||||||
|
Copyright 2015 Rackspace
|
||||||
|
|
||||||
|
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 cloudcafe.networking.networks.common.config import NetworkingBaseConfig
|
||||||
|
|
||||||
|
|
||||||
|
class LimitsConfig(NetworkingBaseConfig):
|
||||||
|
"""Network limits config params"""
|
||||||
|
|
||||||
|
# Adding networks_ in case the limits section for the config files is
|
||||||
|
# already in use by another product
|
||||||
|
SECTION_NAME = 'networks_limits'
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
"""
|
||||||
|
Copyright 2015 Rackspace
|
||||||
|
|
||||||
|
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 cloudcafe.networking.networks.common.constants \
|
||||||
|
import NeutronResponseCodes
|
||||||
|
|
||||||
|
|
||||||
|
class LimitsResponseCodes(NeutronResponseCodes):
|
||||||
|
"""HTTP Limits API Response codes"""
|
||||||
|
|
||||||
|
GET_LIMITS = 200
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
"""
|
||||||
|
Copyright 2015 Rackspace
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
"""
|
||||||
|
Copyright 2015 Rackspace
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
from cafe.engine.models.base import AutoMarshallingListModel, \
|
||||||
|
AutoMarshallingModel
|
||||||
|
|
||||||
|
|
||||||
|
class Limits(AutoMarshallingModel):
|
||||||
|
"""
|
||||||
|
@summary: Limits model response object
|
||||||
|
@param rate: User HTTP rate limits for Neutron API calls
|
||||||
|
For ex. Neutron API PUT calls per minute
|
||||||
|
@type rate: list
|
||||||
|
"""
|
||||||
|
|
||||||
|
LIMITS = 'limits'
|
||||||
|
|
||||||
|
def __init__(self, rate=None, **kwargs):
|
||||||
|
super(Limits, self).__init__()
|
||||||
|
self.rate = rate
|
||||||
|
self.kwargs = kwargs
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _json_to_obj(cls, serialized_str):
|
||||||
|
"""Return limits object from a JSON serialized string"""
|
||||||
|
|
||||||
|
limits = None
|
||||||
|
json_dict = json.loads(serialized_str)
|
||||||
|
|
||||||
|
json_dict = cls._replace_dict_key(
|
||||||
|
json_dict, 'next-available', 'next_available', recursion=True)
|
||||||
|
|
||||||
|
if cls.LIMITS in json_dict:
|
||||||
|
limits_dict = json_dict.get(cls.LIMITS)
|
||||||
|
limits = Limits(**limits_dict)
|
||||||
|
rate = []
|
||||||
|
for rate_limit in limits.rate:
|
||||||
|
rate_obj = Rate(**rate_limit)
|
||||||
|
limit = [Limit(**limit_type) for limit_type in rate_obj.limit]
|
||||||
|
rate_obj.limit = limit
|
||||||
|
rate.append(rate_obj)
|
||||||
|
limits.rate = rate
|
||||||
|
|
||||||
|
return limits
|
||||||
|
|
||||||
|
|
||||||
|
class Rate(AutoMarshallingModel):
|
||||||
|
"""
|
||||||
|
@summary: Rate model response object
|
||||||
|
@param limit: rate limit
|
||||||
|
@type limit: list
|
||||||
|
@param uri: rate limit uniform resource identifier
|
||||||
|
@type uri: str
|
||||||
|
@param regex: regular expression for the API URL the rate limit applies
|
||||||
|
@type regex: str
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, limit=None, uri=None, regex=None, **kwargs):
|
||||||
|
super(Rate, self).__init__()
|
||||||
|
self.limit = limit
|
||||||
|
self.uri = uri
|
||||||
|
self.regex = regex
|
||||||
|
self.kwargs = kwargs
|
||||||
|
|
||||||
|
|
||||||
|
class Limit(AutoMarshallingModel):
|
||||||
|
"""
|
||||||
|
@summary: Limit model response object
|
||||||
|
@param unit: rate limit time units
|
||||||
|
@type unit: str
|
||||||
|
@param next_available: datetime when the available rate limits will reset
|
||||||
|
@type next_available: str
|
||||||
|
@param value: rate limit value
|
||||||
|
@type value: int
|
||||||
|
@param remaining: remaining rate limits
|
||||||
|
@type remaining: int
|
||||||
|
@param verb: HTTP request method
|
||||||
|
@type verb: str
|
||||||
|
"""
|
||||||
|
def __init__(self, unit=None, next_available=None, value=None,
|
||||||
|
remaining=None, verb=None, **kwargs):
|
||||||
|
super(Limit, self).__init__()
|
||||||
|
self.unit = unit
|
||||||
|
self.next_available = next_available
|
||||||
|
self.value = value
|
||||||
|
self.remaining = remaining
|
||||||
|
self.verb = verb
|
||||||
|
self.kwargs = kwargs
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
"""
|
||||||
|
Copyright 2015 Rackspace
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
"""
|
||||||
|
Copyright 2015 Rackspace
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
"""
|
||||||
|
Copyright 2015 Rackspace
|
||||||
|
|
||||||
|
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 unittest
|
||||||
|
|
||||||
|
from cloudcafe.networking.networks.extensions.limits_api.models.response \
|
||||||
|
import Limits, Rate, Limit
|
||||||
|
|
||||||
|
|
||||||
|
LIMITS_DATA = (
|
||||||
|
"""{"limits" : {
|
||||||
|
"rate" : [
|
||||||
|
{
|
||||||
|
"limit" : [
|
||||||
|
{
|
||||||
|
"unit" : "MINUTE",
|
||||||
|
"next-available" : "2015-05-12T21:43:00.182Z",
|
||||||
|
"value" : 1000,
|
||||||
|
"remaining" : 1000,
|
||||||
|
"verb" : "PUT"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"uri" : "LoadTestingPUTs",
|
||||||
|
"regex" : ".*"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"limit" : [
|
||||||
|
{
|
||||||
|
"unit" : "HOUR",
|
||||||
|
"next-available" : "2015-05-12T21:43:00.181Z",
|
||||||
|
"value" : 1000,
|
||||||
|
"remaining" : 1000,
|
||||||
|
"verb" : "DELETE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"unit" : "HOUR",
|
||||||
|
"next-available" : "2015-05-12T21:43:00.181Z",
|
||||||
|
"value" : 1000,
|
||||||
|
"remaining" : 1000,
|
||||||
|
"verb" : "POST"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"unit" : "HOUR",
|
||||||
|
"next-available" : "2015-05-12T21:43:00.181Z",
|
||||||
|
"value" : 1000,
|
||||||
|
"remaining" : 1000,
|
||||||
|
"verb" : "PUT"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"uri" : "LoadTestingPorts",
|
||||||
|
"regex" : "regex_data"
|
||||||
|
}
|
||||||
|
]}}
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
class GetLimitsTest(unittest.TestCase):
|
||||||
|
"""Test for the limits (GET) model object response"""
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
"""Creating the expected models"""
|
||||||
|
|
||||||
|
limit_obj_a1 = Limit(unit='MINUTE',
|
||||||
|
next_available='2015-05-12T21:43:00.182Z',
|
||||||
|
value=1000, remaining=1000, verb='PUT')
|
||||||
|
rate_limits_a = [limit_obj_a1]
|
||||||
|
rate_obj_a = Rate(limit=rate_limits_a,
|
||||||
|
uri='LoadTestingPUTs', regex='.*')
|
||||||
|
|
||||||
|
limit_obj_b1 = Limit(unit='HOUR',
|
||||||
|
next_available='2015-05-12T21:43:00.181Z',
|
||||||
|
value=1000, remaining=1000, verb='DELETE')
|
||||||
|
limit_obj_b2 = Limit(unit='HOUR',
|
||||||
|
next_available='2015-05-12T21:43:00.181Z', value=1000,
|
||||||
|
remaining=1000, verb='POST')
|
||||||
|
limit_obj_b3 = Limit(unit='HOUR',
|
||||||
|
next_available='2015-05-12T21:43:00.181Z',
|
||||||
|
value=1000, remaining=1000, verb='PUT')
|
||||||
|
rate_limits_b = [limit_obj_b1, limit_obj_b2, limit_obj_b3]
|
||||||
|
rate_obj_b = Rate(limit=rate_limits_b,
|
||||||
|
uri='LoadTestingPorts', regex='regex_data')
|
||||||
|
rate = [rate_obj_a, rate_obj_b]
|
||||||
|
cls.expected_response = Limits(rate=rate)
|
||||||
|
|
||||||
|
def test_json_response(self):
|
||||||
|
api_json_resp = LIMITS_DATA
|
||||||
|
response = Limits()._json_to_obj(api_json_resp)
|
||||||
|
msg = ('Unexpected JSON response, expected:\n{0}\n\n'
|
||||||
|
'instead of:\n{1}\n').format(self.expected_response,
|
||||||
|
response)
|
||||||
|
self.assertEqual(response, self.expected_response, msg)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Reference in New Issue
Block a user