Provide compatibility for people passing raw sessions
Code used to pass raw sessions to Resource methods. A common way to do that was to do thins like FloatingIP.get(conn.session, name_or_id). As conn.session is a session.Session that doesn't work anymore. To help ease upgrade path issues, attach a reference to the Connection into conn.session and so that we can pull the right adapter for a given resource back out. Add the neutron-grenade job to verify this works. Change-Id: Ief9a0215ea2399b91d1d03a8048e73e6d7bedd64
This commit is contained in:
parent
26e14550fe
commit
163f502345
@ -219,6 +219,7 @@
|
||||
- openstacksdk-functional-devstack-python3
|
||||
- osc-functional-devstack-tips:
|
||||
voting: false
|
||||
- neutron-grenade
|
||||
gate:
|
||||
jobs:
|
||||
- build-openstack-sphinx-docs:
|
||||
@ -226,3 +227,4 @@
|
||||
sphinx_python: python3
|
||||
- openstacksdk-functional-devstack
|
||||
- openstacksdk-functional-devstack-python3
|
||||
- neutron-grenade
|
||||
|
@ -214,6 +214,10 @@ class Connection(object):
|
||||
self.config._keystone_session = session
|
||||
|
||||
self.session = self.config.get_session()
|
||||
# Hide a reference to the connection on the session to help with
|
||||
# backwards compatibility for folks trying to just pass conn.session
|
||||
# to a Resource method's session argument.
|
||||
self.session._sdk_connection = self
|
||||
|
||||
service_type_manager = os_service_types.ServiceTypes()
|
||||
for service in service_type_manager.services:
|
||||
@ -253,7 +257,7 @@ class Connection(object):
|
||||
service_name=self.config.get_service_name(service_type),
|
||||
interface=self.config.get_interface(service_type),
|
||||
region_name=self.config.region_name,
|
||||
version=self.config.get_api_version(service_type)
|
||||
version=self.config.get_api_version(service_type),
|
||||
)
|
||||
|
||||
# Register the proxy class with every known alias
|
||||
|
@ -34,6 +34,7 @@ and then returned to the caller.
|
||||
import collections
|
||||
import itertools
|
||||
|
||||
from keystoneauth1 import adapter
|
||||
from requests import structures
|
||||
|
||||
from openstack import exceptions
|
||||
@ -649,6 +650,29 @@ class Resource(object):
|
||||
self._header.attributes.update(headers)
|
||||
self._header.clean()
|
||||
|
||||
@classmethod
|
||||
def _get_session(cls, session):
|
||||
"""Attempt to get an Adapter from a raw session.
|
||||
|
||||
Some older code used conn.session has the session argument to Resource
|
||||
methods. That does not work anymore, as Resource methods expect an
|
||||
Adapter not a session. We've hidden an _sdk_connection on the Session
|
||||
stored on the connection. If we get something that isn't an Adapter,
|
||||
pull the connection from the Session and look up the adapter by
|
||||
service_type.
|
||||
"""
|
||||
# TODO(mordred) We'll need to do this for every method in every
|
||||
# Resource class that is calling session.$something to be complete.
|
||||
if isinstance(session, adapter.Adapter):
|
||||
return session
|
||||
if hasattr(session, '_sdk_connection'):
|
||||
service_type = cls.service['service_type']
|
||||
return getattr(session._sdk_connection, service_type)
|
||||
raise ValueError(
|
||||
"The session argument to Resource methods requires either an"
|
||||
" instance of an openstack.proxy.Proxy object or at the very least"
|
||||
" a raw keystoneauth1.adapter.Adapter.")
|
||||
|
||||
def create(self, session, prepend_key=True):
|
||||
"""Create a remote resource based on this instance.
|
||||
|
||||
@ -665,6 +689,7 @@ class Resource(object):
|
||||
if not self.allow_create:
|
||||
raise exceptions.MethodNotSupported(self, "create")
|
||||
|
||||
session = self._get_session(session)
|
||||
if self.create_method == 'PUT':
|
||||
request = self._prepare_request(requires_id=True,
|
||||
prepend_key=prepend_key)
|
||||
@ -697,6 +722,7 @@ class Resource(object):
|
||||
raise exceptions.MethodNotSupported(self, "get")
|
||||
|
||||
request = self._prepare_request(requires_id=requires_id)
|
||||
session = self._get_session(session)
|
||||
response = session.get(request.url)
|
||||
kwargs = {}
|
||||
if error_message:
|
||||
@ -720,6 +746,7 @@ class Resource(object):
|
||||
|
||||
request = self._prepare_request()
|
||||
|
||||
session = self._get_session(session)
|
||||
response = session.head(request.url,
|
||||
headers={"Accept": ""})
|
||||
|
||||
@ -750,6 +777,7 @@ class Resource(object):
|
||||
raise exceptions.MethodNotSupported(self, "update")
|
||||
|
||||
request = self._prepare_request(prepend_key=prepend_key)
|
||||
session = self._get_session(session)
|
||||
|
||||
if self.update_method == 'PATCH':
|
||||
response = session.patch(
|
||||
@ -781,6 +809,7 @@ class Resource(object):
|
||||
raise exceptions.MethodNotSupported(self, "delete")
|
||||
|
||||
request = self._prepare_request()
|
||||
session = self._get_session(session)
|
||||
|
||||
response = session.delete(request.url,
|
||||
headers={"Accept": ""})
|
||||
@ -824,6 +853,7 @@ class Resource(object):
|
||||
"""
|
||||
if not cls.allow_list:
|
||||
raise exceptions.MethodNotSupported(cls, "list")
|
||||
session = cls._get_session(session)
|
||||
|
||||
expected_params = utils.get_string_format_keys(cls.base_path)
|
||||
expected_params += cls._query_mapping._mapping.keys()
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
import copy
|
||||
|
||||
from keystoneauth1 import adapter
|
||||
import mock
|
||||
import testtools
|
||||
|
||||
@ -146,7 +147,7 @@ class TestLimits(testtools.TestCase):
|
||||
self.assertFalse(sot.allow_list)
|
||||
|
||||
def test_get(self):
|
||||
sess = mock.Mock()
|
||||
sess = mock.Mock(spec=adapter.Adapter)
|
||||
resp = mock.Mock()
|
||||
sess.get.return_value = resp
|
||||
resp.json.return_value = copy.deepcopy(LIMITS_BODY)
|
||||
|
@ -13,6 +13,7 @@
|
||||
import json
|
||||
import operator
|
||||
|
||||
from keystoneauth1 import adapter
|
||||
import mock
|
||||
import requests
|
||||
import testtools
|
||||
@ -100,7 +101,7 @@ class TestImage(testtools.TestCase):
|
||||
self.resp = mock.Mock()
|
||||
self.resp.body = None
|
||||
self.resp.json = mock.Mock(return_value=self.resp.body)
|
||||
self.sess = mock.Mock()
|
||||
self.sess = mock.Mock(spec=adapter.Adapter)
|
||||
self.sess.post = mock.Mock(return_value=self.resp)
|
||||
|
||||
def test_basic(self):
|
||||
|
@ -10,6 +10,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from keystoneauth1 import adapter
|
||||
import mock
|
||||
import testtools
|
||||
|
||||
@ -67,7 +68,7 @@ class TestFloatingIP(testtools.TestCase):
|
||||
self.assertEqual(EXAMPLE['subnet_id'], sot.subnet_id)
|
||||
|
||||
def test_find_available(self):
|
||||
mock_session = mock.Mock()
|
||||
mock_session = mock.Mock(spec=adapter.Adapter)
|
||||
mock_session.get_filter = mock.Mock(return_value={})
|
||||
data = {'id': 'one', 'floating_ip_address': '10.0.0.1'}
|
||||
fake_response = mock.Mock()
|
||||
@ -85,7 +86,7 @@ class TestFloatingIP(testtools.TestCase):
|
||||
params={'port_id': ''})
|
||||
|
||||
def test_find_available_nada(self):
|
||||
mock_session = mock.Mock()
|
||||
mock_session = mock.Mock(spec=adapter.Adapter)
|
||||
fake_response = mock.Mock()
|
||||
body = {floating_ip.FloatingIP.resources_key: []}
|
||||
fake_response.json = mock.Mock(return_value=body)
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
import itertools
|
||||
|
||||
from keystoneauth1 import session
|
||||
from keystoneauth1 import adapter
|
||||
import mock
|
||||
import requests
|
||||
import six
|
||||
@ -944,7 +944,7 @@ class TestResourceActions(base.TestCase):
|
||||
self.sot._prepare_request = mock.Mock(return_value=self.request)
|
||||
self.sot._translate_response = mock.Mock()
|
||||
|
||||
self.session = mock.Mock(spec=session.Session)
|
||||
self.session = mock.Mock(spec=adapter.Adapter)
|
||||
self.session.create = mock.Mock(return_value=self.response)
|
||||
self.session.get = mock.Mock(return_value=self.response)
|
||||
self.session.put = mock.Mock(return_value=self.response)
|
||||
|
Loading…
x
Reference in New Issue
Block a user