openstacksdk/openstack/tests/unit/config/test_from_conf.py

370 lines
13 KiB
Python

# 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 uuid
from keystoneauth1 import exceptions as ks_exc
import requests.exceptions
from openstack.config import cloud_region
from openstack import connection
from openstack import exceptions
from openstack.tests import fakes
from openstack.tests.unit import base
class TestFromConf(base.TestCase):
def _get_conn(self, **from_conf_kwargs):
oslocfg = self._load_ks_cfg_opts()
# Throw name in here to prove **kwargs is working
config = cloud_region.from_conf(
oslocfg,
session=self.cloud.session,
name='from_conf.example.com',
**from_conf_kwargs
)
self.assertEqual('from_conf.example.com', config.name)
return connection.Connection(config=config, strict_proxies=True)
def test_adapter_opts_set(self):
"""Adapter opts specified in the conf."""
conn = self._get_conn()
discovery = {
"versions": {
"values": [
{
"status": "stable",
"updated": "2019-06-01T00:00:00Z",
"media-types": [
{
"base": "application/json",
"type": "application/vnd.openstack.heat-v2+json", # noqa: E501
}
],
"id": "v2.0",
"links": [
{
"href": "https://example.org:8888/heat/v2",
"rel": "self",
}
],
}
]
}
}
self.register_uris(
[
dict(
method='GET',
uri='https://example.org:8888/heat/v2',
json=discovery,
),
dict(
method='GET',
uri='https://example.org:8888/heat/v2/foo',
json={'foo': {}},
),
]
)
adap = conn.orchestration
self.assertEqual('SpecialRegion', adap.region_name)
self.assertEqual('orchestration', adap.service_type)
self.assertEqual('internal', adap.interface)
self.assertEqual(
'https://example.org:8888/heat/v2', adap.endpoint_override
)
adap.get('/foo')
self.assert_calls()
def test_default_adapter_opts(self):
"""Adapter opts are registered, but all defaulting in conf."""
conn = self._get_conn()
server_id = str(uuid.uuid4())
server_name = self.getUniqueString('name')
fake_server = fakes.make_fake_server(server_id, server_name)
self.register_uris(
[
self.get_nova_discovery_mock_dict(),
dict(
method='GET',
uri=self.get_mock_url(
'compute', 'public', append=['servers', 'detail']
),
json={'servers': [fake_server]},
),
]
)
# Nova has empty adapter config, so these default
adap = conn.compute
self.assertIsNone(adap.region_name)
self.assertEqual('compute', adap.service_type)
self.assertEqual('public', adap.interface)
self.assertIsNone(adap.endpoint_override)
s = next(adap.servers())
self.assertEqual(s.id, server_id)
self.assertEqual(s.name, server_name)
self.assert_calls()
def test_service_not_ready_catalog(self):
"""Adapter opts are registered, but all defaulting in conf."""
conn = self._get_conn()
server_id = str(uuid.uuid4())
server_name = self.getUniqueString('name')
fake_server = fakes.make_fake_server(server_id, server_name)
self.register_uris(
[
dict(
method='GET',
uri='https://compute.example.com/v2.1/',
exc=requests.exceptions.ConnectionError,
),
self.get_nova_discovery_mock_dict(),
dict(
method='GET',
uri=self.get_mock_url(
'compute', 'public', append=['servers', 'detail']
),
json={'servers': [fake_server]},
),
]
)
self.assertRaises(
exceptions.ServiceDiscoveryException, getattr, conn, 'compute'
)
# Nova has empty adapter config, so these default
adap = conn.compute
self.assertIsNone(adap.region_name)
self.assertEqual('compute', adap.service_type)
self.assertEqual('public', adap.interface)
self.assertIsNone(adap.endpoint_override)
s = next(adap.servers())
self.assertEqual(s.id, server_id)
self.assertEqual(s.name, server_name)
self.assert_calls()
def test_name_with_dashes(self):
conn = self._get_conn()
discovery = {
"versions": {
"values": [
{
"status": "stable",
"id": "v1",
"links": [
{
"href": "https://example.org:5050/v1",
"rel": "self",
}
],
}
]
}
}
status = {'finished': True, 'error': None}
self.register_uris(
[
dict(
method='GET',
uri='https://example.org:5050',
json=discovery,
),
# strict-proxies means we're going to fetch the discovery
# doc from the versioned endpoint to verify it works.
dict(
method='GET',
uri='https://example.org:5050/v1',
json=discovery,
),
dict(
method='GET',
uri='https://example.org:5050/v1/introspection/abcd',
json=status,
),
]
)
adap = conn.baremetal_introspection
self.assertEqual('baremetal-introspection', adap.service_type)
self.assertEqual('public', adap.interface)
self.assertEqual('https://example.org:5050/v1', adap.endpoint_override)
self.assertTrue(adap.get_introspection('abcd').is_finished)
def test_service_not_ready_endpoint_override(self):
conn = self._get_conn()
discovery = {
"versions": {
"values": [
{
"status": "stable",
"id": "v1",
"links": [
{
"href": "https://example.org:5050/v1",
"rel": "self",
}
],
}
]
}
}
status = {'finished': True, 'error': None}
self.register_uris(
[
dict(
method='GET',
uri='https://example.org:5050',
exc=requests.exceptions.ConnectTimeout,
),
dict(
method='GET',
uri='https://example.org:5050',
json=discovery,
),
# strict-proxies means we're going to fetch the discovery
# doc from the versioned endpoint to verify it works.
dict(
method='GET',
uri='https://example.org:5050/v1',
json=discovery,
),
dict(
method='GET',
uri='https://example.org:5050/v1/introspection/abcd',
json=status,
),
]
)
self.assertRaises(
exceptions.ServiceDiscoveryException,
getattr,
conn,
'baremetal_introspection',
)
adap = conn.baremetal_introspection
self.assertEqual('baremetal-introspection', adap.service_type)
self.assertEqual('public', adap.interface)
self.assertEqual('https://example.org:5050/v1', adap.endpoint_override)
self.assertTrue(adap.get_introspection('abcd').is_finished)
def assert_service_disabled(
self, service_type, expected_reason, **from_conf_kwargs
):
conn = self._get_conn(**from_conf_kwargs)
# The _ServiceDisabledProxyShim loads up okay...
adap = getattr(conn, service_type)
# ...but freaks out if you try to use it.
ex = self.assertRaises(
exceptions.ServiceDisabledException, getattr, adap, 'get'
)
self.assertIn(
"Service '%s' is disabled because its configuration "
"could not be loaded." % service_type,
ex.message,
)
self.assertIn(expected_reason, ex.message)
def test_no_such_conf_section(self):
"""No conf section (therefore no adapter opts) for service type."""
del self.oslo_config_dict['heat']
self.assert_service_disabled(
'orchestration',
"No section for project 'heat' (service type 'orchestration') was "
"present in the config.",
)
def test_no_such_conf_section_ignore_service_type(self):
"""Ignore absent conf section if service type not requested."""
del self.oslo_config_dict['heat']
self.assert_service_disabled(
'orchestration',
"Not in the list of requested service_types.",
# 'orchestration' absent from this list
service_types=['compute'],
)
def test_no_adapter_opts(self):
"""Conf section present, but opts for service type not registered."""
self.oslo_config_dict['heat'] = None
self.assert_service_disabled(
'orchestration',
"Encountered an exception attempting to process config for "
"project 'heat' (service type 'orchestration'): no such option",
)
def test_no_adapter_opts_ignore_service_type(self):
"""Ignore unregistered conf section if service type not requested."""
self.oslo_config_dict['heat'] = None
self.assert_service_disabled(
'orchestration',
"Not in the list of requested service_types.",
# 'orchestration' absent from this list
service_types=['compute'],
)
def test_invalid_adapter_opts(self):
"""Adapter opts are bogus, in exception-raising ways."""
self.oslo_config_dict['heat'] = {
'interface': 'public',
'valid_interfaces': 'private',
}
self.assert_service_disabled(
'orchestration',
"Encountered an exception attempting to process config for "
"project 'heat' (service type 'orchestration'): interface and "
"valid_interfaces are mutually exclusive.",
)
def test_no_session(self):
# TODO(efried): Currently calling without a Session is not implemented.
self.assertRaises(
exceptions.ConfigException,
cloud_region.from_conf,
self._load_ks_cfg_opts(),
)
def test_no_endpoint(self):
"""Conf contains adapter opts, but service type not in catalog."""
self.os_fixture.v3_token.remove_service('monitoring')
conn = self._get_conn()
# Monasca is not in the service catalog
self.assertRaises(
ks_exc.catalog.EndpointNotFound, getattr, conn, 'monitoring'
)
def test_no_endpoint_ignore_service_type(self):
"""Bogus service type disabled if not in requested service_types."""
self.assert_service_disabled(
'monitoring',
"Not in the list of requested service_types.",
# 'monitoring' absent from this list
service_types={'compute', 'orchestration', 'bogus'},
)