Add support for Middleware

This patch creates a new middleware context to retrieve data
from subordinate charm and update the kesytone configuration file.
It also allows integration with keystone-middleware interface:
https://github.com/openstack-charmers/interface-keystone-middleware
This patch uses the subordinate configuration approach
to retrieve data from the subordinate charm.

Every changes required for paste.ini file will be handled by
the subordinate charm. The latter should deal with keystone upgrades.

Closes-Bug: #1808597

Change-Id: I4897011fbc791abc97e34e75826579820e80a4f1
This commit is contained in:
Aymen Frikha 2018-12-17 13:46:13 +00:00
parent 97d0d4eff8
commit c272d2c707
11 changed files with 118 additions and 1 deletions

View File

@ -0,0 +1 @@
keystone_hooks.py

View File

@ -0,0 +1 @@
keystone_hooks.py

View File

@ -0,0 +1 @@
keystone_hooks.py

View File

@ -0,0 +1 @@
keystone_hooks.py

View File

@ -42,6 +42,26 @@ from charmhelpers.contrib.openstack.utils import (
)
class MiddlewareContext(context.OSContextGenerator):
interfaces = ['keystone-middleware']
def __call__(self):
middlewares = []
for rid in relation_ids('keystone-middleware'):
if related_units(rid):
for unit in related_units(rid):
middleware_name = relation_get('middleware_name',
rid=rid,
unit=unit)
if middleware_name:
middlewares.append(middleware_name)
return {
'middlewares': ",".join(middlewares)
}
class ApacheSSLContext(context.ApacheSSLContext):
interfaces = ['https']
external_ports = []

View File

@ -789,6 +789,15 @@ def certs_changed(relation_id=None, unit=None):
update_all_domain_backends()
@hooks.hook('keystone-middleware-relation-joined',
'keystone-middleware-relation-changed',
'keystone-middleware-relation-broken',
'keystone-middleware-relation-departed')
@restart_on_change(restart_map())
def keystone_middleware_changed():
CONFIGS.write(KEYSTONE_CONF)
@hooks.hook('pre-series-upgrade')
def pre_series_upgrade():
log("Running prepare series upgrade hook", "INFO")

View File

@ -233,7 +233,12 @@ BASE_RESOURCE_MAP = OrderedDict([
context.WorkerConfigContext(),
context.MemcacheContext(package='keystone'),
keystone_context.KeystoneFIDServiceProviderContext(),
keystone_context.WebSSOTrustedDashboardContext()],
keystone_context.WebSSOTrustedDashboardContext(),
keystone_context.context.SubordinateConfigContext(
interface=['keystone-middleware'],
service='keystone',
config_file=KEYSTONE_CONF),
keystone_context.MiddlewareContext()]
}),
(KEYSTONE_LOGGER_CONF, {
'contexts': [keystone_context.KeystoneLoggingContext()],

View File

@ -46,6 +46,9 @@ requires:
interface: websso-trusted-dashboard
certificates:
interface: tls-certificates
keystone-middleware:
interface: keystone-middleware
scope: container
peers:
cluster:
interface: keystone-ha

View File

@ -69,11 +69,15 @@ driver = {{ assignment_backend }}
[oauth1]
{% if middlewares -%}
{% include "parts/section-middleware" %}
{% else %}
[auth]
methods = external,password,token,oauth1,mapped,openid,totp
password = keystone.auth.plugins.password.Password
token = keystone.auth.plugins.token.Token
oauth1 = keystone.auth.plugins.oauth1.OAuth
{% endif %}
[paste_deploy]
config_file = {{ paste_config_file }}

View File

@ -0,0 +1,6 @@
{% for section in sections -%}
[{{section}}]
{% for key, value in sections[section].items() -%}
{{ key }} = {{ value }}
{% endfor %}
{%- endfor %}

View File

@ -439,3 +439,69 @@ class TestKeystoneContexts(CharmTestCase):
self.maxDiff = None
self.assertCountEqual(ctxt(), {})
@patch.object(context, 'relation_ids')
def test_middleware_no_related_units(self, mock_relation_ids):
os.environ['JUJU_UNIT_NAME'] = 'keystone'
def relation_ids_side_effect(rname):
return {
'keystone-middleware': {}
}[rname]
mock_relation_ids.side_effect = relation_ids_side_effect
ctxt = context.MiddlewareContext()
self.assertEqual(ctxt(), {'middlewares': ''})
@patch('charmhelpers.contrib.openstack.context.relation_ids')
@patch('charmhelpers.contrib.openstack.context.related_units')
@patch('charmhelpers.contrib.openstack.context.relation_get')
def test_middleware_related_units(
self, mock_relation_get, mock_related_units, mock_relation_ids):
mock_relation_ids.return_value = ['keystone-middleware:0']
mock_related_units.return_value = ['keystone-ico/0']
settings = \
{
'middleware_name': 'keystone-ico',
'subordinate_configuration':
'{"keystone":'
'{"/etc/keystone/keystone.conf":'
'{"sections":'
'{"authentication":'
'[["simple_token_header", "SimpleToken"],'
'["simple_token_secret", "foobar"]],'
'"auth":'
'[["methods", "external,password,token,oauth1"],'
'["external", "keystone.auth.plugins.external.Domain"],'
'["password", "keystone.auth.plugins.password.Password"],'
'["token", "keystone.auth.plugins.token.Token"],'
'["oauth1", "keystone.auth.plugins.oauth1.OAuth"]]'
'}}}}'
}
def fake_rel_get(attribute=None, unit=None, rid=None):
return settings[attribute]
mock_relation_get.side_effect = fake_rel_get
ctxt = context.context.SubordinateConfigContext(
interface=['keystone-middleware'],
service='keystone',
config_file='/etc/keystone/keystone.conf')
exp = {'sections': {
u'auth': [[u'methods',
u'external,password,token,oauth1'],
[u'external',
u'keystone.auth.plugins.external.Domain'],
[u'password',
u'keystone.auth.plugins.password.Password'],
[u'token',
u'keystone.auth.plugins.token.Token'],
[u'oauth1',
u'keystone.auth.plugins.oauth1.OAuth']],
u'authentication': [[u'simple_token_header', u'SimpleToken'],
[u'simple_token_secret', u'foobar']]}}
self.assertEqual(ctxt(), exp)