Merge "Implement socket timeout in v1"
This commit is contained in:
commit
9803b87a31
@ -18,7 +18,6 @@ import json as json_
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
import fixtures
|
import fixtures
|
||||||
from keystoneclient import adapter
|
|
||||||
from keystoneclient import session as keystone_session
|
from keystoneclient import session as keystone_session
|
||||||
from oslotest import base as test
|
from oslotest import base as test
|
||||||
from requests_mock.contrib import fixture as req_fixture
|
from requests_mock.contrib import fixture as req_fixture
|
||||||
@ -26,6 +25,7 @@ import six
|
|||||||
from six.moves.urllib import parse as urlparse
|
from six.moves.urllib import parse as urlparse
|
||||||
|
|
||||||
from designateclient import client
|
from designateclient import client
|
||||||
|
from designateclient.utils import AdapterWithTimeout
|
||||||
|
|
||||||
_TRUE_VALUES = ('True', 'true', '1', 'yes')
|
_TRUE_VALUES = ('True', 'true', '1', 'yes')
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ class APITestCase(TestCase):
|
|||||||
def get_client(self, version=None, session=None):
|
def get_client(self, version=None, session=None):
|
||||||
version = version or self.VERSION
|
version = version or self.VERSION
|
||||||
session = session or keystone_session.Session()
|
session = session or keystone_session.Session()
|
||||||
adapted = adapter.Adapter(
|
adapted = AdapterWithTimeout(
|
||||||
session=session, endpoint_override=self.get_base())
|
session=session, endpoint_override=self.get_base())
|
||||||
return client.Client(version, session=adapted)
|
return client.Client(version, session=adapted)
|
||||||
|
|
||||||
|
@ -13,10 +13,13 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from designateclient.tests import test_v1
|
from designateclient.tests import test_v1
|
||||||
from designateclient import utils
|
from designateclient import utils
|
||||||
from designateclient import v1
|
from designateclient import v1
|
||||||
|
|
||||||
|
from keystoneclient import session as keystone_session
|
||||||
|
|
||||||
|
|
||||||
class TestClient(test_v1.APIV1TestCase):
|
class TestClient(test_v1.APIV1TestCase):
|
||||||
def test_all_tenants(self):
|
def test_all_tenants(self):
|
||||||
@ -26,7 +29,7 @@ class TestClient(test_v1.APIV1TestCase):
|
|||||||
# Verify this has been picked up
|
# Verify this has been picked up
|
||||||
self.assertTrue(client.all_tenants)
|
self.assertTrue(client.all_tenants)
|
||||||
|
|
||||||
def test_all_tenants_not_suplied(self):
|
def test_all_tenants_not_supplied(self):
|
||||||
# Create a client without supplying any all_tenants flag
|
# Create a client without supplying any all_tenants flag
|
||||||
client = v1.Client()
|
client = v1.Client()
|
||||||
|
|
||||||
@ -68,7 +71,7 @@ class TestClient(test_v1.APIV1TestCase):
|
|||||||
# Verify this has been picked up
|
# Verify this has been picked up
|
||||||
self.assertTrue(client.edit_managed)
|
self.assertTrue(client.edit_managed)
|
||||||
|
|
||||||
def test_edit_managed_not_suplied(self):
|
def test_edit_managed_not_supplied(self):
|
||||||
# Create a client without supplying any edit_managed flag
|
# Create a client without supplying any edit_managed flag
|
||||||
client = v1.Client()
|
client = v1.Client()
|
||||||
|
|
||||||
@ -102,3 +105,20 @@ class TestClient(test_v1.APIV1TestCase):
|
|||||||
|
|
||||||
# Verify the edit_managed flag has been picked up
|
# Verify the edit_managed flag has been picked up
|
||||||
self.assertTrue(client.edit_managed)
|
self.assertTrue(client.edit_managed)
|
||||||
|
|
||||||
|
def test_timeout_new_session(self):
|
||||||
|
client = v1.Client(
|
||||||
|
auth_url="http://127.0.0.1:22/",
|
||||||
|
timeout=1,
|
||||||
|
)
|
||||||
|
assert client.session.timeout == 1
|
||||||
|
|
||||||
|
def test_timeout_override_session_timeout(self):
|
||||||
|
# The adapter timeout should override the session timeout
|
||||||
|
session = keystone_session.Session(timeout=10)
|
||||||
|
client = v1.Client(
|
||||||
|
auth_url="http://127.0.0.1:22/",
|
||||||
|
session=session,
|
||||||
|
timeout=2,
|
||||||
|
)
|
||||||
|
self.assertEqual(client.session.timeout, 2)
|
||||||
|
32
designateclient/tests/v2/test_client.py
Normal file
32
designateclient/tests/v2/test_client.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||||
|
#
|
||||||
|
# Author: Federico Ceratto <federico.ceratto@hp.com>
|
||||||
|
#
|
||||||
|
# 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 keystoneclient import adapter
|
||||||
|
from keystoneclient import session as keystone_session
|
||||||
|
|
||||||
|
from designateclient.tests.base import TestCase
|
||||||
|
from designateclient.v2.client import Client
|
||||||
|
|
||||||
|
|
||||||
|
class TestClient(TestCase):
|
||||||
|
def test_init(self):
|
||||||
|
self.assertRaises(ValueError, Client)
|
||||||
|
|
||||||
|
def test_init_with_session(self):
|
||||||
|
session = keystone_session.Session()
|
||||||
|
adapted = adapter.Adapter(session=session)
|
||||||
|
client = Client(session=adapted)
|
||||||
|
assert client.session
|
109
designateclient/tests/v2/test_timeout.py
Normal file
109
designateclient/tests/v2/test_timeout.py
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
# Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||||
|
#
|
||||||
|
# Author: Federico Ceratto <federico.ceratto@hp.com>
|
||||||
|
#
|
||||||
|
# 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 keystoneclient.auth.identity import generic
|
||||||
|
from keystoneclient import session as keystone_session
|
||||||
|
from mock import Mock
|
||||||
|
|
||||||
|
from designateclient.tests import v2
|
||||||
|
from designateclient.v2.client import Client
|
||||||
|
|
||||||
|
|
||||||
|
def create_session(timeout=None):
|
||||||
|
auth = generic.Password(auth_url='', username='', password='',
|
||||||
|
tenant_name='')
|
||||||
|
return keystone_session.Session(auth=auth, timeout=timeout)
|
||||||
|
|
||||||
|
|
||||||
|
class TestTimeout(v2.APIV2TestCase, v2.CrudMixin):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestTimeout, self).setUp()
|
||||||
|
|
||||||
|
# Mock methods in KeyStone's Session
|
||||||
|
self._saved_methods = (
|
||||||
|
keystone_session.Session.get_auth_headers,
|
||||||
|
keystone_session.Session.get_endpoint,
|
||||||
|
keystone_session.Session._send_request,
|
||||||
|
)
|
||||||
|
|
||||||
|
resp = Mock()
|
||||||
|
resp.text = ''
|
||||||
|
resp.status_code = 200
|
||||||
|
|
||||||
|
keystone_session.Session.get_auth_headers = Mock(
|
||||||
|
return_value=[]
|
||||||
|
)
|
||||||
|
keystone_session.Session.get_endpoint = Mock(
|
||||||
|
return_value='foo'
|
||||||
|
)
|
||||||
|
keystone_session.Session._send_request = Mock(
|
||||||
|
return_value=resp,
|
||||||
|
)
|
||||||
|
self.mock_send_request = keystone_session.Session._send_request
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super(TestTimeout, self).tearDown()
|
||||||
|
(
|
||||||
|
keystone_session.Session.get_auth_headers,
|
||||||
|
keystone_session.Session.get_endpoint,
|
||||||
|
keystone_session.Session._send_request,
|
||||||
|
) = self._saved_methods
|
||||||
|
|
||||||
|
def _call_request_and_check_timeout(self, client, timeout):
|
||||||
|
"""call the mocked _send_request() and check if the timeout was set
|
||||||
|
"""
|
||||||
|
client.limits.get()
|
||||||
|
self.assertTrue(self.mock_send_request.called)
|
||||||
|
kw = self.mock_send_request.call_args[1]
|
||||||
|
if timeout is None:
|
||||||
|
self.assertFalse('timeout' in kw)
|
||||||
|
else:
|
||||||
|
self.assertEqual(kw['timeout'], timeout)
|
||||||
|
|
||||||
|
def test_no_timeout(self):
|
||||||
|
session = create_session(timeout=None)
|
||||||
|
client = Client(session=session)
|
||||||
|
self.assertEqual(session.timeout, None)
|
||||||
|
self.assertEqual(client.session.timeout, None)
|
||||||
|
self._call_request_and_check_timeout(client, None)
|
||||||
|
|
||||||
|
def test_timeout_in_session(self):
|
||||||
|
session = create_session(timeout=1)
|
||||||
|
client = Client(session=session)
|
||||||
|
self.assertEqual(session.timeout, 1)
|
||||||
|
self.assertEqual(client.session.timeout, None)
|
||||||
|
self._call_request_and_check_timeout(client, 1)
|
||||||
|
|
||||||
|
def test_timeout_override_session_timeout(self):
|
||||||
|
# The adapter timeout should override the session timeout
|
||||||
|
session = create_session(timeout=10)
|
||||||
|
self.assertEqual(session.timeout, 10)
|
||||||
|
client = Client(session=session, timeout=2)
|
||||||
|
self.assertEqual(client.session.timeout, 2)
|
||||||
|
self._call_request_and_check_timeout(client, 2)
|
||||||
|
|
||||||
|
def test_timeout_update(self):
|
||||||
|
session = create_session(timeout=1)
|
||||||
|
client = Client(session=session)
|
||||||
|
self.assertEqual(session.timeout, 1)
|
||||||
|
self.assertEqual(client.session.timeout, None)
|
||||||
|
self._call_request_and_check_timeout(client, 1)
|
||||||
|
|
||||||
|
session.timeout = 2
|
||||||
|
self.assertEqual(session.timeout, 2)
|
||||||
|
|
||||||
|
self._call_request_and_check_timeout(client, 2)
|
@ -19,6 +19,7 @@ import os
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from debtcollector import removals
|
from debtcollector import removals
|
||||||
|
from keystoneclient import adapter
|
||||||
from keystoneclient.auth.identity import generic
|
from keystoneclient.auth.identity import generic
|
||||||
from keystoneclient.auth import token_endpoint
|
from keystoneclient.auth import token_endpoint
|
||||||
from keystoneclient import session as ks_session
|
from keystoneclient import session as ks_session
|
||||||
@ -174,3 +175,22 @@ def find_resourceid_by_name_or_id(resource_client, name_or_id):
|
|||||||
raise exceptions.NoUniqueMatch(
|
raise exceptions.NoUniqueMatch(
|
||||||
'Multiple resources with name "%s": %s' % (name_or_id, str_ids))
|
'Multiple resources with name "%s": %s' % (name_or_id, str_ids))
|
||||||
return candidate_ids[0]
|
return candidate_ids[0]
|
||||||
|
|
||||||
|
|
||||||
|
class AdapterWithTimeout(adapter.Adapter):
|
||||||
|
"""adapter.Adapter wraps around a Session.
|
||||||
|
The user can pass a timeout keyword that will apply only to
|
||||||
|
the Designate Client, in order:
|
||||||
|
- timeout keyword passed to request()
|
||||||
|
- timeout keyword passed to AdapterWithTimeout()
|
||||||
|
- timeout attribute on keystone session
|
||||||
|
"""
|
||||||
|
def __init__(self, *args, **kw):
|
||||||
|
self.timeout = kw.pop('timeout', None)
|
||||||
|
super(self.__class__, self).__init__(*args, **kw)
|
||||||
|
|
||||||
|
def request(self, *args, **kwargs):
|
||||||
|
if self.timeout is not None:
|
||||||
|
kwargs.setdefault('timeout', self.timeout)
|
||||||
|
|
||||||
|
return super(AdapterWithTimeout, self).request(*args, **kwargs)
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
from keystoneclient import adapter
|
|
||||||
from stevedore import extension
|
from stevedore import extension
|
||||||
|
|
||||||
from designateclient import exceptions
|
from designateclient import exceptions
|
||||||
@ -32,7 +31,8 @@ class Client(object):
|
|||||||
project_domain_id=None, auth_url=None, token=None,
|
project_domain_id=None, auth_url=None, token=None,
|
||||||
endpoint_type='publicURL', region_name=None,
|
endpoint_type='publicURL', region_name=None,
|
||||||
service_type='dns', insecure=False, session=None,
|
service_type='dns', insecure=False, session=None,
|
||||||
cacert=None, all_tenants=None, edit_managed=None):
|
cacert=None, all_tenants=None, edit_managed=None,
|
||||||
|
timeout=None):
|
||||||
"""
|
"""
|
||||||
:param endpoint: Endpoint URL
|
:param endpoint: Endpoint URL
|
||||||
:param token: A token instead of username / password
|
:param token: A token instead of username / password
|
||||||
@ -62,7 +62,7 @@ class Client(object):
|
|||||||
user_domain_name=user_domain_name,
|
user_domain_name=user_domain_name,
|
||||||
token=token,
|
token=token,
|
||||||
insecure=insecure,
|
insecure=insecure,
|
||||||
cacert=cacert
|
cacert=cacert,
|
||||||
)
|
)
|
||||||
|
|
||||||
# NOTE: all_tenants and edit_managed are pulled from the session for
|
# NOTE: all_tenants and edit_managed are pulled from the session for
|
||||||
@ -82,7 +82,7 @@ class Client(object):
|
|||||||
# an adapter around the session to not modify it's state.
|
# an adapter around the session to not modify it's state.
|
||||||
interface = endpoint_type.rstrip('URL')
|
interface = endpoint_type.rstrip('URL')
|
||||||
|
|
||||||
self.session = adapter.Adapter(
|
self.session = utils.AdapterWithTimeout(
|
||||||
session,
|
session,
|
||||||
auth=session.auth,
|
auth=session.auth,
|
||||||
endpoint_override=endpoint,
|
endpoint_override=endpoint,
|
||||||
@ -90,7 +90,8 @@ class Client(object):
|
|||||||
service_type=service_type,
|
service_type=service_type,
|
||||||
interface=interface,
|
interface=interface,
|
||||||
user_agent='python-designateclient-%s' % version.version_info,
|
user_agent='python-designateclient-%s' % version.version_info,
|
||||||
version='1'
|
version='1',
|
||||||
|
timeout=timeout,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _load_controller(ext):
|
def _load_controller(ext):
|
||||||
|
@ -30,13 +30,25 @@ from designateclient import version
|
|||||||
class DesignateAdapter(adapter.LegacyJsonAdapter):
|
class DesignateAdapter(adapter.LegacyJsonAdapter):
|
||||||
"""
|
"""
|
||||||
Adapter around LegacyJsonAdapter.
|
Adapter around LegacyJsonAdapter.
|
||||||
|
The user can pass a timeout keyword that will apply only to
|
||||||
|
the Designate Client, in order:
|
||||||
|
- timeout keyword passed to request()
|
||||||
|
- timeout attribute on keystone session
|
||||||
"""
|
"""
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.timeout = kwargs.pop('timeout', None)
|
||||||
|
super(self.__class__, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def request(self, *args, **kwargs):
|
def request(self, *args, **kwargs):
|
||||||
kwargs.setdefault('raise_exc', False)
|
kwargs.setdefault('raise_exc', False)
|
||||||
|
|
||||||
|
if self.timeout is not None:
|
||||||
|
kwargs.setdefault('timeout', self.timeout)
|
||||||
|
|
||||||
kwargs.setdefault('headers', {}).setdefault(
|
kwargs.setdefault('headers', {}).setdefault(
|
||||||
'Content-Type', 'application/json')
|
'Content-Type', 'application/json')
|
||||||
response, body = super(DesignateAdapter, self).request(*args, **kwargs)
|
|
||||||
|
response, body = super(self.__class__, self).request(*args, **kwargs)
|
||||||
|
|
||||||
# Decode is response, if possible
|
# Decode is response, if possible
|
||||||
try:
|
try:
|
||||||
@ -60,7 +72,11 @@ class DesignateAdapter(adapter.LegacyJsonAdapter):
|
|||||||
class Client(object):
|
class Client(object):
|
||||||
def __init__(self, region_name=None, endpoint_type='publicURL',
|
def __init__(self, region_name=None, endpoint_type='publicURL',
|
||||||
extensions=None, service_type='dns', service_name=None,
|
extensions=None, service_type='dns', service_name=None,
|
||||||
http_log_debug=False, session=None, auth=None):
|
http_log_debug=False, session=None, auth=None, timeout=None,
|
||||||
|
endpoint_override=None):
|
||||||
|
if session is None:
|
||||||
|
raise ValueError("A session instance is required")
|
||||||
|
|
||||||
self.session = DesignateAdapter(
|
self.session = DesignateAdapter(
|
||||||
session,
|
session,
|
||||||
auth=auth,
|
auth=auth,
|
||||||
@ -68,7 +84,10 @@ class Client(object):
|
|||||||
service_type=service_type,
|
service_type=service_type,
|
||||||
interface=endpoint_type.rstrip('URL'),
|
interface=endpoint_type.rstrip('URL'),
|
||||||
user_agent='python-designateclient-%s' % version.version_info,
|
user_agent='python-designateclient-%s' % version.version_info,
|
||||||
version=('2'))
|
version=('2'),
|
||||||
|
endpoint_override=endpoint_override,
|
||||||
|
timeout=timeout
|
||||||
|
)
|
||||||
|
|
||||||
self.blacklists = BlacklistController(self)
|
self.blacklists = BlacklistController(self)
|
||||||
self.floatingips = FloatingIPController(self)
|
self.floatingips = FloatingIPController(self)
|
||||||
|
@ -15,7 +15,7 @@ auth = generic.Password(
|
|||||||
password=shell.env('OS_PASSWORD'),
|
password=shell.env('OS_PASSWORD'),
|
||||||
tenant_name=shell.env('OS_TENANT_NAME'))
|
tenant_name=shell.env('OS_TENANT_NAME'))
|
||||||
|
|
||||||
session = keystone_session.Session(auth=auth)
|
session = keystone_session.Session(auth=auth, timeout=10)
|
||||||
|
|
||||||
client = client.Client(session=session)
|
client = client.Client(session=session)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user