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
|
- openstacksdk-functional-devstack-python3
|
||||||
- osc-functional-devstack-tips:
|
- osc-functional-devstack-tips:
|
||||||
voting: false
|
voting: false
|
||||||
|
- neutron-grenade
|
||||||
gate:
|
gate:
|
||||||
jobs:
|
jobs:
|
||||||
- build-openstack-sphinx-docs:
|
- build-openstack-sphinx-docs:
|
||||||
@ -226,3 +227,4 @@
|
|||||||
sphinx_python: python3
|
sphinx_python: python3
|
||||||
- openstacksdk-functional-devstack
|
- openstacksdk-functional-devstack
|
||||||
- openstacksdk-functional-devstack-python3
|
- openstacksdk-functional-devstack-python3
|
||||||
|
- neutron-grenade
|
||||||
|
@ -214,6 +214,10 @@ class Connection(object):
|
|||||||
self.config._keystone_session = session
|
self.config._keystone_session = session
|
||||||
|
|
||||||
self.session = self.config.get_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()
|
service_type_manager = os_service_types.ServiceTypes()
|
||||||
for service in service_type_manager.services:
|
for service in service_type_manager.services:
|
||||||
@ -253,7 +257,7 @@ class Connection(object):
|
|||||||
service_name=self.config.get_service_name(service_type),
|
service_name=self.config.get_service_name(service_type),
|
||||||
interface=self.config.get_interface(service_type),
|
interface=self.config.get_interface(service_type),
|
||||||
region_name=self.config.region_name,
|
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
|
# Register the proxy class with every known alias
|
||||||
|
@ -34,6 +34,7 @@ and then returned to the caller.
|
|||||||
import collections
|
import collections
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
|
from keystoneauth1 import adapter
|
||||||
from requests import structures
|
from requests import structures
|
||||||
|
|
||||||
from openstack import exceptions
|
from openstack import exceptions
|
||||||
@ -649,6 +650,29 @@ class Resource(object):
|
|||||||
self._header.attributes.update(headers)
|
self._header.attributes.update(headers)
|
||||||
self._header.clean()
|
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):
|
def create(self, session, prepend_key=True):
|
||||||
"""Create a remote resource based on this instance.
|
"""Create a remote resource based on this instance.
|
||||||
|
|
||||||
@ -665,6 +689,7 @@ class Resource(object):
|
|||||||
if not self.allow_create:
|
if not self.allow_create:
|
||||||
raise exceptions.MethodNotSupported(self, "create")
|
raise exceptions.MethodNotSupported(self, "create")
|
||||||
|
|
||||||
|
session = self._get_session(session)
|
||||||
if self.create_method == 'PUT':
|
if self.create_method == 'PUT':
|
||||||
request = self._prepare_request(requires_id=True,
|
request = self._prepare_request(requires_id=True,
|
||||||
prepend_key=prepend_key)
|
prepend_key=prepend_key)
|
||||||
@ -697,6 +722,7 @@ class Resource(object):
|
|||||||
raise exceptions.MethodNotSupported(self, "get")
|
raise exceptions.MethodNotSupported(self, "get")
|
||||||
|
|
||||||
request = self._prepare_request(requires_id=requires_id)
|
request = self._prepare_request(requires_id=requires_id)
|
||||||
|
session = self._get_session(session)
|
||||||
response = session.get(request.url)
|
response = session.get(request.url)
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
if error_message:
|
if error_message:
|
||||||
@ -720,6 +746,7 @@ class Resource(object):
|
|||||||
|
|
||||||
request = self._prepare_request()
|
request = self._prepare_request()
|
||||||
|
|
||||||
|
session = self._get_session(session)
|
||||||
response = session.head(request.url,
|
response = session.head(request.url,
|
||||||
headers={"Accept": ""})
|
headers={"Accept": ""})
|
||||||
|
|
||||||
@ -750,6 +777,7 @@ class Resource(object):
|
|||||||
raise exceptions.MethodNotSupported(self, "update")
|
raise exceptions.MethodNotSupported(self, "update")
|
||||||
|
|
||||||
request = self._prepare_request(prepend_key=prepend_key)
|
request = self._prepare_request(prepend_key=prepend_key)
|
||||||
|
session = self._get_session(session)
|
||||||
|
|
||||||
if self.update_method == 'PATCH':
|
if self.update_method == 'PATCH':
|
||||||
response = session.patch(
|
response = session.patch(
|
||||||
@ -781,6 +809,7 @@ class Resource(object):
|
|||||||
raise exceptions.MethodNotSupported(self, "delete")
|
raise exceptions.MethodNotSupported(self, "delete")
|
||||||
|
|
||||||
request = self._prepare_request()
|
request = self._prepare_request()
|
||||||
|
session = self._get_session(session)
|
||||||
|
|
||||||
response = session.delete(request.url,
|
response = session.delete(request.url,
|
||||||
headers={"Accept": ""})
|
headers={"Accept": ""})
|
||||||
@ -824,6 +853,7 @@ class Resource(object):
|
|||||||
"""
|
"""
|
||||||
if not cls.allow_list:
|
if not cls.allow_list:
|
||||||
raise exceptions.MethodNotSupported(cls, "list")
|
raise exceptions.MethodNotSupported(cls, "list")
|
||||||
|
session = cls._get_session(session)
|
||||||
|
|
||||||
expected_params = utils.get_string_format_keys(cls.base_path)
|
expected_params = utils.get_string_format_keys(cls.base_path)
|
||||||
expected_params += cls._query_mapping._mapping.keys()
|
expected_params += cls._query_mapping._mapping.keys()
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
|
from keystoneauth1 import adapter
|
||||||
import mock
|
import mock
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
@ -146,7 +147,7 @@ class TestLimits(testtools.TestCase):
|
|||||||
self.assertFalse(sot.allow_list)
|
self.assertFalse(sot.allow_list)
|
||||||
|
|
||||||
def test_get(self):
|
def test_get(self):
|
||||||
sess = mock.Mock()
|
sess = mock.Mock(spec=adapter.Adapter)
|
||||||
resp = mock.Mock()
|
resp = mock.Mock()
|
||||||
sess.get.return_value = resp
|
sess.get.return_value = resp
|
||||||
resp.json.return_value = copy.deepcopy(LIMITS_BODY)
|
resp.json.return_value = copy.deepcopy(LIMITS_BODY)
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
import json
|
import json
|
||||||
import operator
|
import operator
|
||||||
|
|
||||||
|
from keystoneauth1 import adapter
|
||||||
import mock
|
import mock
|
||||||
import requests
|
import requests
|
||||||
import testtools
|
import testtools
|
||||||
@ -100,7 +101,7 @@ class TestImage(testtools.TestCase):
|
|||||||
self.resp = mock.Mock()
|
self.resp = mock.Mock()
|
||||||
self.resp.body = None
|
self.resp.body = None
|
||||||
self.resp.json = mock.Mock(return_value=self.resp.body)
|
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)
|
self.sess.post = mock.Mock(return_value=self.resp)
|
||||||
|
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
# 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 keystoneauth1 import adapter
|
||||||
import mock
|
import mock
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ class TestFloatingIP(testtools.TestCase):
|
|||||||
self.assertEqual(EXAMPLE['subnet_id'], sot.subnet_id)
|
self.assertEqual(EXAMPLE['subnet_id'], sot.subnet_id)
|
||||||
|
|
||||||
def test_find_available(self):
|
def test_find_available(self):
|
||||||
mock_session = mock.Mock()
|
mock_session = mock.Mock(spec=adapter.Adapter)
|
||||||
mock_session.get_filter = mock.Mock(return_value={})
|
mock_session.get_filter = mock.Mock(return_value={})
|
||||||
data = {'id': 'one', 'floating_ip_address': '10.0.0.1'}
|
data = {'id': 'one', 'floating_ip_address': '10.0.0.1'}
|
||||||
fake_response = mock.Mock()
|
fake_response = mock.Mock()
|
||||||
@ -85,7 +86,7 @@ class TestFloatingIP(testtools.TestCase):
|
|||||||
params={'port_id': ''})
|
params={'port_id': ''})
|
||||||
|
|
||||||
def test_find_available_nada(self):
|
def test_find_available_nada(self):
|
||||||
mock_session = mock.Mock()
|
mock_session = mock.Mock(spec=adapter.Adapter)
|
||||||
fake_response = mock.Mock()
|
fake_response = mock.Mock()
|
||||||
body = {floating_ip.FloatingIP.resources_key: []}
|
body = {floating_ip.FloatingIP.resources_key: []}
|
||||||
fake_response.json = mock.Mock(return_value=body)
|
fake_response.json = mock.Mock(return_value=body)
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
from keystoneauth1 import session
|
from keystoneauth1 import adapter
|
||||||
import mock
|
import mock
|
||||||
import requests
|
import requests
|
||||||
import six
|
import six
|
||||||
@ -944,7 +944,7 @@ class TestResourceActions(base.TestCase):
|
|||||||
self.sot._prepare_request = mock.Mock(return_value=self.request)
|
self.sot._prepare_request = mock.Mock(return_value=self.request)
|
||||||
self.sot._translate_response = mock.Mock()
|
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.create = mock.Mock(return_value=self.response)
|
||||||
self.session.get = mock.Mock(return_value=self.response)
|
self.session.get = mock.Mock(return_value=self.response)
|
||||||
self.session.put = mock.Mock(return_value=self.response)
|
self.session.put = mock.Mock(return_value=self.response)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user