[wolsen,r=] Add support for overriding public endpoint addresses.
Adds in the config option for overriding public endpoint addresses and introduces a unit tests to ensure that the override for the public address is functioning correctly. Additionally fixed unit test to not attempt an actual restart of the cinder services.
This commit is contained in:
parent
15f52309b9
commit
5bd17722b3
13
config.yaml
13
config.yaml
@ -207,6 +207,19 @@ options:
|
||||
192.168.0.0/24)
|
||||
.
|
||||
This network will be used for public endpoints.
|
||||
endpoint-public-name:
|
||||
type: string
|
||||
default:
|
||||
description: |
|
||||
The hostname or address of the public endpoints created for cinder
|
||||
in the keystone identity provider.
|
||||
.
|
||||
This value will be used for public endpoints. For example, an
|
||||
endpoint-public-name set to 'cinder.example.com' with ssl enabled will
|
||||
create two public endpoints for cinder.
|
||||
.
|
||||
https://cinder.example.com:443/v1/$(tenant_id)s and
|
||||
https://cinder.example.com:443/v2/$(tenant_id)s
|
||||
prefer-ipv6:
|
||||
type: boolean
|
||||
default: False
|
||||
|
@ -26,8 +26,6 @@ from charmhelpers.contrib.network.ip import (
|
||||
)
|
||||
from charmhelpers.contrib.hahelpers.cluster import is_clustered
|
||||
|
||||
from functools import partial
|
||||
|
||||
PUBLIC = 'public'
|
||||
INTERNAL = 'int'
|
||||
ADMIN = 'admin'
|
||||
@ -35,15 +33,18 @@ ADMIN = 'admin'
|
||||
ADDRESS_MAP = {
|
||||
PUBLIC: {
|
||||
'config': 'os-public-network',
|
||||
'fallback': 'public-address'
|
||||
'fallback': 'public-address',
|
||||
'override': 'endpoint-public-name',
|
||||
},
|
||||
INTERNAL: {
|
||||
'config': 'os-internal-network',
|
||||
'fallback': 'private-address'
|
||||
'fallback': 'private-address',
|
||||
'override': 'endpoint-internal-name',
|
||||
},
|
||||
ADMIN: {
|
||||
'config': 'os-admin-network',
|
||||
'fallback': 'private-address'
|
||||
'fallback': 'private-address',
|
||||
'override': 'endpoint-admin-name',
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,13 +58,35 @@ def canonical_url(configs, endpoint_type=PUBLIC):
|
||||
:param endpoint_type: str endpoint type to resolve.
|
||||
:param returns: str base URL for services on the current service unit.
|
||||
"""
|
||||
scheme = _get_scheme(configs)
|
||||
|
||||
# Allow the user to override the address which is used. This is
|
||||
# useful for proxy services or exposing a public endpoint url, etc.
|
||||
override_key = ADDRESS_MAP[endpoint_type]['override']
|
||||
addr_override = config(override_key)
|
||||
if addr_override:
|
||||
address = addr_override
|
||||
else:
|
||||
address = resolve_address(endpoint_type)
|
||||
if is_ipv6(address):
|
||||
address = "[{}]".format(address)
|
||||
|
||||
return '%s://%s' % (scheme, address)
|
||||
|
||||
|
||||
def _get_scheme(configs):
|
||||
"""Returns the scheme to use for the url (either http or https)
|
||||
depending upon whether https is in the configs value.
|
||||
|
||||
:param configs: OSTemplateRenderer config templating object to inspect
|
||||
for a complete https context.
|
||||
:returns: either 'http' or 'https' depending on whether https is
|
||||
configured within the configs context.
|
||||
"""
|
||||
scheme = 'http'
|
||||
if 'https' in configs.complete_contexts():
|
||||
scheme = 'https'
|
||||
address = resolve_address(endpoint_type)
|
||||
if is_ipv6(address):
|
||||
address = "[{}]".format(address)
|
||||
return '%s://%s' % (scheme, address)
|
||||
return scheme
|
||||
|
||||
|
||||
def resolve_address(endpoint_type=PUBLIC):
|
||||
@ -109,38 +132,3 @@ def resolve_address(endpoint_type=PUBLIC):
|
||||
"clustered=%s)" % (net_type, clustered))
|
||||
|
||||
return resolved_address
|
||||
|
||||
|
||||
def endpoint_url(configs, url_template, port, endpoint_type=PUBLIC,
|
||||
override=None):
|
||||
"""Returns the correct endpoint URL to advertise to Keystone.
|
||||
|
||||
This method provides the correct endpoint URL which should be advertised to
|
||||
the keystone charm for endpoint creation. This method allows for the url to
|
||||
be overridden to force a keystone endpoint to have specific URL for any of
|
||||
the defined scopes (admin, internal, public).
|
||||
|
||||
:param configs: OSTemplateRenderer config templating object to inspect
|
||||
for a complete https context.
|
||||
:param url_template: str format string for creating the url template. Only
|
||||
two values will be passed - the scheme+hostname
|
||||
returned by the canonical_url and the port.
|
||||
:param endpoint_type: str endpoint type to resolve.
|
||||
:param override: str the name of the config option which overrides the
|
||||
endpoint URL defined by the charm itself. None will
|
||||
disable any overrides (default).
|
||||
"""
|
||||
if override:
|
||||
# Return any user-defined overrides for the keystone endpoint URL.
|
||||
user_value = config(override)
|
||||
if user_value:
|
||||
return user_value.strip()
|
||||
|
||||
return url_template % (canonical_url(configs, endpoint_type), port)
|
||||
|
||||
|
||||
public_endpoint = partial(endpoint_url, endpoint_type=PUBLIC)
|
||||
|
||||
internal_endpoint = partial(endpoint_url, endpoint_type=INTERNAL)
|
||||
|
||||
admin_endpoint = partial(endpoint_url, endpoint_type=ADMIN)
|
||||
|
@ -67,7 +67,6 @@ TO_PATCH = [
|
||||
'openstack_upgrade_available',
|
||||
'os_release',
|
||||
# charmhelpers.contrib.hahelpers.cluster_utils
|
||||
'canonical_url',
|
||||
'eligible_leader',
|
||||
'get_hacluster_config',
|
||||
'execd_preinstall',
|
||||
@ -412,12 +411,13 @@ class TestJoinedHooks(CharmTestCase):
|
||||
vhost='openstack',
|
||||
relation_id='amqp:1')
|
||||
|
||||
def test_identity_service_joined(self):
|
||||
@patch.object(hooks, 'canonical_url')
|
||||
def test_identity_service_joined(self, _canonical_url):
|
||||
'It properly requests unclustered endpoint via identity-service'
|
||||
self.os_release.return_value = 'havana'
|
||||
self.unit_get.return_value = 'cindernode1'
|
||||
self.config.side_effect = self.test_config.get
|
||||
self.canonical_url.return_value = 'http://cindernode1'
|
||||
_canonical_url.return_value = 'http://cindernode1'
|
||||
hooks.hooks.execute(['hooks/identity-service-relation-joined'])
|
||||
expected = {
|
||||
'region': None,
|
||||
@ -434,12 +434,13 @@ class TestJoinedHooks(CharmTestCase):
|
||||
}
|
||||
self.relation_set.assert_called_with(**expected)
|
||||
|
||||
def test_identity_service_joined_icehouse(self):
|
||||
@patch.object(hooks, 'canonical_url')
|
||||
def test_identity_service_joined_icehouse(self, _canonical_url):
|
||||
'It properly requests unclustered endpoint via identity-service'
|
||||
self.os_release.return_value = 'icehouse'
|
||||
self.unit_get.return_value = 'cindernode1'
|
||||
self.config.side_effect = self.test_config.get
|
||||
self.canonical_url.return_value = 'http://cindernode1'
|
||||
_canonical_url.return_value = 'http://cindernode1'
|
||||
hooks.hooks.execute(['hooks/identity-service-relation-joined'])
|
||||
expected = {
|
||||
'region': None,
|
||||
@ -462,6 +463,37 @@ class TestJoinedHooks(CharmTestCase):
|
||||
}
|
||||
self.relation_set.assert_called_with(**expected)
|
||||
|
||||
@patch('charmhelpers.contrib.openstack.ip.config')
|
||||
@patch('charmhelpers.contrib.openstack.ip.resolve_address')
|
||||
def test_identity_service_joined_public_name(self, _resolve_address, _config):
|
||||
self.os_release.return_value = 'icehouse'
|
||||
self.unit_get.return_value = 'cindernode1'
|
||||
self.config.side_effect = self.test_config.get
|
||||
_config.side_effect = self.test_config.get
|
||||
self.test_config.set('endpoint-public-name', 'public.example.com')
|
||||
_resolve_address.return_value = 'cindernode1'
|
||||
hooks.hooks.execute(['hooks/identity-service-relation-joined'])
|
||||
expected = {
|
||||
'region': None,
|
||||
'service': None,
|
||||
'public_url': None,
|
||||
'internal_url': None,
|
||||
'admin_url': None,
|
||||
'cinder_service': 'cinder',
|
||||
'cinder_region': 'RegionOne',
|
||||
'cinder_public_url': 'http://public.example.com:8776/v1/$(tenant_id)s',
|
||||
'cinder_admin_url': 'http://cindernode1:8776/v1/$(tenant_id)s',
|
||||
'cinder_internal_url': 'http://cindernode1:8776/v1/$(tenant_id)s',
|
||||
'cinderv2_service': 'cinderv2',
|
||||
'cinderv2_region': 'RegionOne',
|
||||
'cinderv2_public_url': 'http://public.example.com:8776/v2/$(tenant_id)s',
|
||||
'cinderv2_admin_url': 'http://cindernode1:8776/v2/$(tenant_id)s',
|
||||
'cinderv2_internal_url': 'http://cindernode1:8776/'
|
||||
'v2/$(tenant_id)s',
|
||||
'relation_id': None,
|
||||
}
|
||||
self.relation_set.assert_called_with(**expected)
|
||||
|
||||
@patch('os.mkdir')
|
||||
def test_ceph_joined(self, mkdir):
|
||||
'It correctly prepares for a ceph changed hook'
|
||||
@ -501,8 +533,10 @@ class TestJoinedHooks(CharmTestCase):
|
||||
self.assertNotIn(c, self.CONFIGS.write.call_args_list)
|
||||
self.assertFalse(self.set_ceph_env_variables.called)
|
||||
|
||||
@patch('charmhelpers.core.host.service')
|
||||
@patch("cinder_hooks.relation_get", autospec=True)
|
||||
def test_ceph_changed_broker_success(self, mock_relation_get):
|
||||
def test_ceph_changed_broker_success(self, mock_relation_get,
|
||||
_service):
|
||||
'It ensures ceph assets created on ceph changed'
|
||||
self.CONFIGS.complete_contexts.return_value = ['ceph']
|
||||
self.service_name.return_value = 'cinder'
|
||||
|
Loading…
Reference in New Issue
Block a user