Calculate name in CloudRegion

We calculate a name from the auth_url in the from_session factory
function, but it should really be a fundamental piece of logic for
CloudRegion about what to do with name not being present since we've
added in several paths for people to make a Connection that have nothing
to do with named clouds in clouds.yaml.

Change-Id: Ib4cdcde6be50295e214e7cd4ca8c65b7da431529
This commit is contained in:
Monty Taylor 2018-02-04 12:00:00 -06:00
parent a61b5d25de
commit ebe5fde830
No known key found for this signature in database
GPG Key ID: 7BAE94BC7141A594
6 changed files with 57 additions and 35 deletions

View File

@ -318,7 +318,9 @@ class OpenStackCloud(_normalize.Normalizer):
def session_constructor(*args, **kwargs): def session_constructor(*args, **kwargs):
# We need to pass our current keystone session to the Session # We need to pass our current keystone session to the Session
# Constructor, otherwise the new auth plugin doesn't get used. # Constructor, otherwise the new auth plugin doesn't get used.
return keystoneauth1.session.Session(session=self.session) return keystoneauth1.session.Session(
session=self.session,
discovery_cache=self.config._discovery_cache)
# Use cloud='defaults' so that we overlay settings properly # Use cloud='defaults' so that we overlay settings properly
cloud_config = config.get_one( cloud_config = config.get_one(
@ -326,7 +328,7 @@ class OpenStackCloud(_normalize.Normalizer):
session_constructor=session_constructor, session_constructor=session_constructor,
**params) **params)
# Override the cloud name so that logging/location work right # Override the cloud name so that logging/location work right
cloud_config.name = self.name cloud_config._name = self.name
cloud_config.config['profile'] = self.name cloud_config.config['profile'] = self.name
# Use self.__class__ so that we return whatever this if, like if it's # Use self.__class__ so that we return whatever this if, like if it's
# a subclass in the case of shade wrapping sdk. # a subclass in the case of shade wrapping sdk.

View File

@ -60,9 +60,6 @@ def from_session(session, name=None, region_name=None,
:param kwargs: :param kwargs:
Config settings for this cloud region. Config settings for this cloud region.
""" """
# If someone is constructing one of these from a Session, then they are
# not using a named config. Use the hostname of their auth_url instead.
name = name or urllib.parse.urlparse(session.auth.auth_url).hostname
config_dict = config_defaults.get_defaults() config_dict = config_defaults.get_defaults()
config_dict.update(**kwargs) config_dict.update(**kwargs)
return CloudRegion( return CloudRegion(
@ -77,11 +74,13 @@ class CloudRegion(object):
A CloudRegion encapsulates the config information needed for connections A CloudRegion encapsulates the config information needed for connections
to all of the services in a Region of a Cloud. to all of the services in a Region of a Cloud.
""" """
def __init__(self, name, region_name=None, config=None, def __init__(self, name=None, region_name=None, config=None,
force_ipv4=False, auth_plugin=None, force_ipv4=False, auth_plugin=None,
openstack_config=None, session_constructor=None, openstack_config=None, session_constructor=None,
app_name=None, app_version=None, session=None): app_name=None, app_version=None, session=None,
self.name = name discovery_cache=None):
self._name = name
self.region_name = region_name self.region_name = region_name
self.config = config self.config = config
self.log = _log.setup_logging('openstack.config') self.log = _log.setup_logging('openstack.config')
@ -92,6 +91,7 @@ class CloudRegion(object):
self._session_constructor = session_constructor or ks_session.Session self._session_constructor = session_constructor or ks_session.Session
self._app_name = app_name self._app_name = app_name
self._app_version = app_version self._app_version = app_version
self._discovery_cache = discovery_cache or None
def __getattr__(self, key): def __getattr__(self, key):
"""Return arbitrary attributes.""" """Return arbitrary attributes."""
@ -116,6 +116,32 @@ class CloudRegion(object):
def __ne__(self, other): def __ne__(self, other):
return not self == other return not self == other
@property
def name(self):
if self._name is None:
try:
self._name = urllib.parse.urlparse(
self.get_session().auth.auth_url).hostname
except Exception:
self._name = self._app_name or ''
return self._name
@property
def full_name(self):
"""Return a string that can be used as an identifier.
Always returns a valid string. It will have name and region_name
or just one of the two if only one is set, or else 'unknown'.
"""
if self.name and self.region_name:
return ":".join([self.name, self.region_name])
elif self.name and not self.region_name:
return self.name
elif not self.name and self.region_name:
return self.region_name
else:
return 'unknown'
def set_session_constructor(self, session_constructor): def set_session_constructor(self, session_constructor):
"""Sets the Session constructor.""" """Sets the Session constructor."""
self._session_constructor = session_constructor self._session_constructor = session_constructor
@ -128,9 +154,10 @@ class CloudRegion(object):
verify = self.config['verify'] verify = self.config['verify']
if self.config['cacert']: if self.config['cacert']:
warnings.warn( warnings.warn(
"You are specifying a cacert for the cloud {0} but " "You are specifying a cacert for the cloud {full_name}"
"also to ignore the host verification. The host SSL cert " " but also to ignore the host verification. The host SSL"
"will not be verified.".format(self.name)) " cert will not be verified.".format(
full_name=self.full_name))
cert = self.config.get('cert', None) cert = self.config.get('cert', None)
if cert: if cert:
@ -216,15 +243,15 @@ class CloudRegion(object):
# cert verification # cert verification
if not verify: if not verify:
self.log.debug( self.log.debug(
"Turning off SSL warnings for {cloud}:{region}" "Turning off SSL warnings for {full_name}"
" since verify=False".format( " since verify=False".format(full_name=self.full_name))
cloud=self.name, region=self.region_name))
requestsexceptions.squelch_warnings(insecure_requests=not verify) requestsexceptions.squelch_warnings(insecure_requests=not verify)
self._keystone_session = self._session_constructor( self._keystone_session = self._session_constructor(
auth=self._auth, auth=self._auth,
verify=verify, verify=verify,
cert=cert, cert=cert,
timeout=self.config['api_timeout']) timeout=self.config['api_timeout'],
discovery_cache=self._discovery_cache)
if hasattr(self._keystone_session, 'additional_user_agent'): if hasattr(self._keystone_session, 'additional_user_agent'):
self._keystone_session.additional_user_agent.append( self._keystone_session.additional_user_agent.append(
('openstacksdk', openstack_version.__version__)) ('openstacksdk', openstack_version.__version__))

View File

@ -295,18 +295,7 @@ class Connection(six.with_metaclass(_meta.ConnectionMeta,
load_envvars=cloud is not None, load_envvars=cloud is not None,
**kwargs) **kwargs)
if self.config.name: self.task_manager = task_manager.TaskManager(self.config.full_name)
tm_name = ':'.join([
self.config.name,
self.config.region_name or 'unknown'])
else:
tm_name = self.config.region_name or 'unknown'
self.task_manager = task_manager.TaskManager(name=tm_name)
if session:
# TODO(mordred) Expose constructor option for this in OCC
self.config._keystone_session = session
self._session = None self._session = None
self._proxies = {} self._proxies = {}

View File

@ -16,7 +16,6 @@
""" """
import copy import copy
from six.moves import urllib
from openstack import _log from openstack import _log
from openstack.config import cloud_region from openstack.config import cloud_region
@ -45,9 +44,6 @@ def _get_config_from_profile(profile, authenticator, **kwargs):
# TODO(shade) Remove this once we've shifted python-openstackclient # TODO(shade) Remove this once we've shifted python-openstackclient
# to not use the profile interface. # to not use the profile interface.
# We don't have a cloud name. Make one up from the auth_url hostname
# so that log messages work.
name = urllib.parse.urlparse(authenticator.auth_url).hostname
region_name = None region_name = None
for service in profile.get_services(): for service in profile.get_services():
if service.region: if service.region:
@ -66,7 +62,7 @@ def _get_config_from_profile(profile, authenticator, **kwargs):
config_kwargs = config_defaults.get_defaults() config_kwargs = config_defaults.get_defaults()
config_kwargs.update(kwargs) config_kwargs.update(kwargs)
config = cloud_region.CloudRegion( config = cloud_region.CloudRegion(
name=name, region_name=region_name, config=config_kwargs) region_name=region_name, config=config_kwargs)
config._auth = authenticator config._auth = authenticator
return config return config

View File

@ -54,6 +54,14 @@ class TestShade(base.RequestsMockTestCase):
def test_openstack_cloud(self): def test_openstack_cloud(self):
self.assertIsInstance(self.cloud, openstack.cloud.OpenStackCloud) self.assertIsInstance(self.cloud, openstack.cloud.OpenStackCloud)
def test_connect_as(self):
# Do initial auth/catalog steps
# TODO(mordred) This only tests the constructor steps. Discovery
# cache sharing is broken. We need to get discovery_cache option
# plumbed through
# keystoneauth1.loading.base.BaseLoader.load_from_options
self.cloud.connect_as(project_name='test_project')
@mock.patch.object(openstack.cloud.OpenStackCloud, 'search_images') @mock.patch.object(openstack.cloud.OpenStackCloud, 'search_images')
def test_get_images(self, mock_search): def test_get_images(self, mock_search):
image1 = dict(id='123', name='mickey') image1 = dict(id='123', name='mickey')

View File

@ -192,7 +192,7 @@ class TestCloudRegion(base.TestCase):
cc.get_session() cc.get_session()
mock_session.assert_called_with( mock_session.assert_called_with(
auth=mock.ANY, auth=mock.ANY,
verify=True, cert=None, timeout=None) verify=True, cert=None, timeout=None, discovery_cache=None)
self.assertEqual( self.assertEqual(
fake_session.additional_user_agent, fake_session.additional_user_agent,
[('openstacksdk', openstack_version.__version__)]) [('openstacksdk', openstack_version.__version__)])
@ -212,7 +212,7 @@ class TestCloudRegion(base.TestCase):
cc.get_session() cc.get_session()
mock_session.assert_called_with( mock_session.assert_called_with(
auth=mock.ANY, auth=mock.ANY,
verify=True, cert=None, timeout=None) verify=True, cert=None, timeout=None, discovery_cache=None)
self.assertEqual(fake_session.app_name, "test_app") self.assertEqual(fake_session.app_name, "test_app")
self.assertEqual(fake_session.app_version, "test_version") self.assertEqual(fake_session.app_version, "test_version")
self.assertEqual( self.assertEqual(
@ -232,7 +232,7 @@ class TestCloudRegion(base.TestCase):
cc.get_session() cc.get_session()
mock_session.assert_called_with( mock_session.assert_called_with(
auth=mock.ANY, auth=mock.ANY,
verify=True, cert=None, timeout=9) verify=True, cert=None, timeout=9, discovery_cache=None)
self.assertEqual( self.assertEqual(
fake_session.additional_user_agent, fake_session.additional_user_agent,
[('openstacksdk', openstack_version.__version__)]) [('openstacksdk', openstack_version.__version__)])