After merged the patch I08c8b753972c27b4e6bbe07a8aa51e0e72fbc56d, blazarclient can't be used with blazar_url and auth_token since this patch only allows sessions for the initiation of client. For backward compatibility, blazarclient should be initiated with blazar_url and auth_token as before. This patch enables using blazarclient with a set of blazar_url and auth_token or session by reviving BaseClientManager class with adding a logic to chose an auth method based on given params. Change-Id: I25a665145b0503cc04e49bc85c39e2f6dca36925 Closes-Bug: #1724757changes/49/517849/6
parent
8d897c5220
commit
2afa290302
@ -0,0 +1,135 @@
|
||||
# Copyright (c) 2013 Mirantis Inc.
|
||||
#
|
||||
# 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 keystoneauth1 import adapter
|
||||
import requests
|
||||
|
||||
from blazarclient import exception
|
||||
from blazarclient.i18n import _
|
||||
|
||||
|
||||
class RequestManager(object):
|
||||
"""Manager to create request from given Blazar URL and auth token."""
|
||||
|
||||
def __init__(self, blazar_url, auth_token, user_agent):
|
||||
self.blazar_url = blazar_url
|
||||
self.auth_token = auth_token
|
||||
self.user_agent = user_agent
|
||||
|
||||
def get(self, url):
|
||||
"""Sends get request to Blazar.
|
||||
|
||||
:param url: URL to the wanted Blazar resource.
|
||||
:type url: str
|
||||
"""
|
||||
return self.request(url, 'GET')
|
||||
|
||||
def post(self, url, body):
|
||||
"""Sends post request to Blazar.
|
||||
|
||||
:param url: URL to the wanted Blazar resource.
|
||||
:type url: str
|
||||
|
||||
:param body: Values resource to be created from.
|
||||
:type body: dict
|
||||
"""
|
||||
return self.request(url, 'POST', body=body)
|
||||
|
||||
def delete(self, url):
|
||||
"""Sends delete request to Blazar.
|
||||
|
||||
:param url: URL to the wanted Blazar resource.
|
||||
:type url: str
|
||||
"""
|
||||
return self.request(url, 'DELETE')
|
||||
|
||||
def put(self, url, body):
|
||||
"""Sends update request to Blazar.
|
||||
|
||||
:param url: URL to the wanted Blazar resource.
|
||||
:type url: str
|
||||
|
||||
:param body: Values resource to be updated from.
|
||||
:type body: dict
|
||||
"""
|
||||
return self.request(url, 'PUT', body=body)
|
||||
|
||||
def request(self, url, method, **kwargs):
|
||||
"""Base request method.
|
||||
|
||||
Adds specific headers and URL prefix to the request.
|
||||
|
||||
:param url: Resource URL.
|
||||
:type url: str
|
||||
|
||||
:param method: Method to be called (GET, POST, PUT, DELETE).
|
||||
:type method: str
|
||||
|
||||
:returns: Response and body.
|
||||
:rtype: tuple
|
||||
"""
|
||||
kwargs.setdefault('headers', kwargs.get('headers', {}))
|
||||
kwargs['headers']['User-Agent'] = self.user_agent
|
||||
kwargs['headers']['Accept'] = 'application/json'
|
||||
kwargs['headers']['x-auth-token'] = self.auth_token
|
||||
|
||||
if 'body' in kwargs:
|
||||
kwargs['headers']['Content-Type'] = 'application/json'
|
||||
kwargs['data'] = json.dumps(kwargs['body'])
|
||||
del kwargs['body']
|
||||
|
||||
resp = requests.request(method, self.blazar_url + url, **kwargs)
|
||||
|
||||
try:
|
||||
body = json.loads(resp.text)
|
||||
except ValueError:
|
||||
body = None
|
||||
|
||||
if resp.status_code >= 400:
|
||||
if body is not None:
|
||||
error_message = body.get('error_message', body)
|
||||
else:
|
||||
error_message = resp.text
|
||||
|
||||
body = _("ERROR: {0}").format(error_message)
|
||||
raise exception.BlazarClientException(body, code=resp.status_code)
|
||||
|
||||
return resp, body
|
||||
|
||||
|
||||
class BaseClientManager(object):
|
||||
"""Base class for managing resources of Blazar."""
|
||||
|
||||
user_agent = 'python-blazarclient'
|
||||
|
||||
def __init__(self, blazar_url, auth_token, session, **kwargs):
|
||||
self.blazar_url = blazar_url
|
||||
self.auth_token = auth_token
|
||||
self.session = session
|
||||
|
||||
if self.session:
|
||||
self.request_manager = adapter.LegacyJsonAdapter(
|
||||
session=self.session,
|
||||
user_agent=self.user_agent,
|
||||
**kwargs
|
||||
)
|
||||
elif self.blazar_url and self.auth_token:
|
||||
self.request_manager = RequestManager(blazar_url=self.blazar_url,
|
||||
auth_token=self.auth_token,
|
||||
user_agent=self.user_agent)
|
||||
else:
|
||||
raise exception.InsufficientAuthInfomation
|
@ -0,0 +1,162 @@
|
||||
# Copyright (c) 2014 Mirantis Inc.
|
||||
#
|
||||
# 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 keystoneauth1 import adapter
|
||||
|
||||
from blazarclient import base
|
||||
from blazarclient import exception
|
||||
from blazarclient import tests
|
||||
|
||||
|
||||
class RequestManagerTestCase(tests.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(RequestManagerTestCase, self).setUp()
|
||||
|
||||
self.blazar_url = "www.fake.com/reservation"
|
||||
self.auth_token = "aaa-bbb-ccc"
|
||||
self.user_agent = "python-blazarclient"
|
||||
self.manager = base.RequestManager(blazar_url=self.blazar_url,
|
||||
auth_token=self.auth_token,
|
||||
user_agent=self.user_agent)
|
||||
|
||||
@mock.patch('blazarclient.base.RequestManager.request',
|
||||
return_value=(200, {"fake": "FAKE"}))
|
||||
def test_get(self, m):
|
||||
url = '/leases'
|
||||
resp, body = self.manager.get(url)
|
||||
self.assertEqual(resp, 200)
|
||||
self.assertDictEqual(body, {"fake": "FAKE"})
|
||||
m.assert_called_once_with(url, "GET")
|
||||
|
||||
@mock.patch('blazarclient.base.RequestManager.request',
|
||||
return_value=(200, {"fake": "FAKE"}))
|
||||
def test_post(self, m):
|
||||
url = '/leases'
|
||||
req_body = {
|
||||
'start': '2020-07-24 20:00',
|
||||
'end': '2020-08-09 22:30',
|
||||
'before_end': '2020-08-09 21:30',
|
||||
'events': [],
|
||||
'name': 'lease-test',
|
||||
'reservations': [
|
||||
{
|
||||
'min': '1',
|
||||
'max': '2',
|
||||
'hypervisor_properties':
|
||||
'[">=", "$vcpus", "2"]',
|
||||
'resource_properties':
|
||||
'["==", "$extra_key", "extra_value"]',
|
||||
'resource_type': 'physical:host',
|
||||
'before_end': 'default'
|
||||
}
|
||||
]
|
||||
}
|
||||
resp, body = self.manager.post(url, req_body)
|
||||
self.assertEqual(resp, 200)
|
||||
self.assertDictEqual(body, {"fake": "FAKE"})
|
||||
m.assert_called_once_with(url, "POST", body=req_body)
|
||||
|
||||
@mock.patch('blazarclient.base.RequestManager.request',
|
||||
return_value=(200, {"fake": "FAKE"}))
|
||||
def test_delete(self, m):
|
||||
url = '/leases/aaa-bbb-ccc'
|
||||
resp, body = self.manager.delete(url)
|
||||
self.assertEqual(resp, 200)
|
||||
self.assertDictEqual(body, {"fake": "FAKE"})
|
||||
m.assert_called_once_with(url, "DELETE")
|
||||
|
||||
@mock.patch('blazarclient.base.RequestManager.request',
|
||||
return_value=(200, {"fake": "FAKE"}))
|
||||
def test_put(self, m):
|
||||
url = '/leases/aaa-bbb-ccc'
|
||||
req_body = {
|
||||
'name': 'lease-test',
|
||||
}
|
||||
resp, body = self.manager.put(url, req_body)
|
||||
self.assertEqual(resp, 200)
|
||||
self.assertDictEqual(body, {"fake": "FAKE"})
|
||||
m.assert_called_once_with(url, "PUT", body=req_body)
|
||||
|
||||
@mock.patch('requests.request')
|
||||
def test_request_ok_with_body(self, m):
|
||||
m.return_value.status_code = 200
|
||||
m.return_value.text = '{"resp_key": "resp_value"}'
|
||||
url = '/leases'
|
||||
kwargs = {"body": {"req_key": "req_value"}}
|
||||
self.assertEqual(self.manager.request(url, "POST", **kwargs),
|
||||
(m(), {"resp_key": "resp_value"}))
|
||||
|
||||
@mock.patch('requests.request')
|
||||
def test_request_ok_without_body(self, m):
|
||||
m.return_value.status_code = 200
|
||||
m.return_value.text = "resp"
|
||||
url = '/leases'
|
||||
kwargs = {"body": {"req_key": "req_value"}}
|
||||
self.assertEqual(self.manager.request(url, "POST", **kwargs),
|
||||
(m(), None))
|
||||
|
||||
@mock.patch('requests.request')
|
||||
def test_request_fail_with_body(self, m):
|
||||
m.return_value.status_code = 400
|
||||
m.return_value.text = '{"resp_key": "resp_value"}'
|
||||
url = '/leases'
|
||||
kwargs = {"body": {"req_key": "req_value"}}
|
||||
self.assertRaises(exception.BlazarClientException,
|
||||
self.manager.request, url, "POST", **kwargs)
|
||||
|
||||
@mock.patch('requests.request')
|
||||
def test_request_fail_without_body(self, m):
|
||||
m.return_value.status_code = 400
|
||||
m.return_value.text = "resp"
|
||||
url = '/leases'
|
||||
kwargs = {"body": {"req_key": "req_value"}}
|
||||
self.assertRaises(exception.BlazarClientException,
|
||||
self.manager.request, url, "POST", **kwargs)
|
||||
|
||||
|
||||
class BaseClientManagerTestCase(tests.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(BaseClientManagerTestCase, self).setUp()
|
||||
|
||||
self.blazar_url = "www.fake.com/reservation"
|
||||
self.auth_token = "aaa-bbb-ccc"
|
||||
self.session = mock.MagicMock()
|
||||
self.user_agent = "python-blazarclient"
|
||||
|
||||
def test_init_with_session(self):
|
||||
manager = base.BaseClientManager(blazar_url=None,
|
||||
auth_token=None,
|
||||
session=self.session)
|
||||
self.assertIsInstance(manager.request_manager,
|
||||
adapter.LegacyJsonAdapter)
|
||||
|
||||
def test_init_with_url_and_token(self):
|
||||
manager = base.BaseClientManager(blazar_url=self.blazar_url,
|
||||
auth_token=self.auth_token,
|
||||
session=None)
|
||||
self.assertIsInstance(manager.request_manager,
|
||||
base.RequestManager)
|
||||
|
||||
def test_init_with_insufficient_info(self):
|
||||
self.assertRaises(exception.InsufficientAuthInfomation,
|
||||
base.BaseClientManager,
|
||||
blazar_url=None,
|
||||
auth_token=self.auth_token,
|
||||
session=None)
|
Loading…
Reference in new issue