Merge "api: redirect to Panko if enabled"

This commit is contained in:
Jenkins 2016-08-29 14:46:36 +00:00 committed by Gerrit Code Review
commit a7eaead641
2 changed files with 97 additions and 17 deletions

View File

@ -45,6 +45,13 @@ API_OPTS = [
help=('The endpoint of Aodh to redirect alarms URLs '
'to Aodh API. Default autodetection by querying '
'keystone.')),
cfg.BoolOpt('panko_is_enabled',
help=('Set True to redirect events URLs to Panko. '
'Default autodetection by querying keystone.')),
cfg.StrOpt('panko_url',
help=('The endpoint of Panko to redirect events URLs '
'to Panko API. Default autodetection by querying '
'keystone.')),
]
cfg.CONF.register_opts(API_OPTS, group='api')
@ -64,7 +71,7 @@ def aodh_abort():
"disabled or unavailable."))
def aodh_redirect(url):
def _redirect(url):
# NOTE(sileht): we use 307 and not 301 or 302 to allow
# client to redirect POST/PUT/DELETE/...
# FIXME(sileht): it would be better to use 308, but webob
@ -75,14 +82,15 @@ def aodh_redirect(url):
class QueryController(object):
def __init__(self, gnocchi_is_enabled=False, aodh_url=None):
def __init__(self, gnocchi_is_enabled=False,
aodh_url=None):
self.gnocchi_is_enabled = gnocchi_is_enabled
self.aodh_url = aodh_url
@pecan.expose()
def _lookup(self, kind, *remainder):
if kind == 'alarms' and self.aodh_url:
aodh_redirect(self.aodh_url)
_redirect(self.aodh_url)
elif kind == 'alarms':
aodh_abort()
elif kind == 'samples' and self.gnocchi_is_enabled:
@ -96,14 +104,14 @@ class QueryController(object):
class V2Controller(object):
"""Version 2 API controller root."""
event_types = events.EventTypesController()
events = events.EventsController()
capabilities = capabilities.CapabilitiesController()
def __init__(self):
self._gnocchi_is_enabled = None
self._aodh_is_enabled = None
self._aodh_url = None
self._panko_is_enabled = None
self._panko_url = None
@property
def gnocchi_is_enabled(self):
@ -137,13 +145,13 @@ class V2Controller(object):
if cfg.CONF.api.aodh_is_enabled is False:
self._aodh_url = ""
elif cfg.CONF.api.aodh_url is not None:
self._aodh_url = self._normalize_aodh_url(
self._aodh_url = self._normalize_url(
cfg.CONF.api.aodh_url)
else:
try:
catalog = keystone_client.get_service_catalog(
keystone_client.get_client())
self._aodh_url = self._normalize_aodh_url(
self._aodh_url = self._normalize_url(
catalog.url_for(service_type='alarming'))
except exceptions.EndpointNotFound:
self._aodh_url = ""
@ -156,6 +164,32 @@ class V2Controller(object):
"to aodh endpoint."))
return self._aodh_url
@property
def panko_url(self):
if self._panko_url is None:
if cfg.CONF.api.panko_is_enabled is False:
self._panko_url = ""
elif cfg.CONF.api.panko_url is not None:
self._panko_url = self._normalize_url(
cfg.CONF.api.panko_url)
else:
try:
catalog = keystone_client.get_service_catalog(
keystone_client.get_client())
self._panko_url = self._normalize_url(
catalog.url_for(service_type='event'))
except exceptions.EndpointNotFound:
self._panko_url = ""
except exceptions.ClientException:
LOG.warning(
_LW("Can't connect to keystone, assuming Panko "
"is disabled and retry later."))
else:
LOG.warning(_LW("ceilometer-api started with Panko "
"enabled. Events URLs will be redirected "
"to Panko endpoint."))
return self._panko_url
@pecan.expose()
def _lookup(self, kind, *remainder):
if (kind in ['meters', 'resources', 'samples']
@ -181,12 +215,20 @@ class V2Controller(object):
elif kind == 'alarms' and (not self.aodh_url):
aodh_abort()
elif kind == 'alarms' and self.aodh_url:
aodh_redirect(self.aodh_url)
_redirect(self.aodh_url)
elif kind == 'events':
if self.panko_url:
return _redirect(self.panko_url)
return events.EventsController(), remainder
elif kind == 'event_types':
if self.panko_url:
return _redirect(self.panko_url)
return events.EventTypesController(), remainder
else:
pecan.abort(404)
@staticmethod
def _normalize_aodh_url(url):
def _normalize_url(url):
if url.endswith("/"):
return url[:-1]
return url

View File

@ -36,11 +36,16 @@ class TestAPIUpgradePath(v2.FunctionalTest):
self.CONF.set_override('aodh_is_enabled', True, group='api')
self.CONF.set_override('aodh_url', 'http://alarm-endpoint:8008/',
group='api')
self.CONF.set_override('panko_is_enabled', True, group='api')
self.CONF.set_override('panko_url', 'http://event-endpoint:8009/',
group='api')
def _setup_keystone_mock(self):
self.CONF.set_override('gnocchi_is_enabled', None, group='api')
self.CONF.set_override('aodh_is_enabled', None, group='api')
self.CONF.set_override('aodh_url', None, group='api')
self.CONF.set_override('panko_is_enabled', None, group='api')
self.CONF.set_override('panko_url', None, group='api')
self.CONF.set_override('meter_dispatchers', ['database'])
self.ks = mock.Mock()
self.catalog = (self.ks.session.auth.get_access.
@ -55,6 +60,8 @@ class TestAPIUpgradePath(v2.FunctionalTest):
return 'http://gnocchi/'
elif service_type == 'alarming':
return 'http://alarm-endpoint:8008/'
elif service_type == 'event':
return 'http://event-endpoint:8009/'
def _do_test_gnocchi_enabled_without_database_backend(self):
self.CONF.set_override('meter_dispatchers', 'gnocchi')
@ -63,14 +70,6 @@ class TestAPIUpgradePath(v2.FunctionalTest):
status=410)
self.assertIn(b'Gnocchi API', response.body)
headers_events = {"X-Roles": "admin",
"X-User-Id": "user1",
"X-Project-Id": "project1"}
for endpoint in ['events', 'event_types']:
self.app.get(self.PATH_PREFIX + '/' + endpoint,
headers=headers_events,
status=200)
response = self.post_json('/query/samples',
params={
"filter": '{"=": {"type": "creation"}}',
@ -125,6 +124,35 @@ class TestAPIUpgradePath(v2.FunctionalTest):
self.assertEqual("http://alarm-endpoint:8008/v2/query/alarms",
response.headers['Location'])
def _do_test_event_redirect(self):
response = self.app.get(self.PATH_PREFIX + '/events',
expect_errors=True)
self.assertEqual(307, response.status_code)
self.assertEqual("http://event-endpoint:8009/v2/events",
response.headers['Location'])
response = self.app.get(self.PATH_PREFIX + '/events/uuid',
expect_errors=True)
self.assertEqual(307, response.status_code)
self.assertEqual("http://event-endpoint:8009/v2/events/uuid",
response.headers['Location'])
response = self.app.delete(self.PATH_PREFIX + '/events/uuid',
expect_errors=True)
self.assertEqual(307, response.status_code)
self.assertEqual("http://event-endpoint:8009/v2/events/uuid",
response.headers['Location'])
response = self.app.get(self.PATH_PREFIX + '/event_types',
expect_errors=True)
self.assertEqual(307, response.status_code)
self.assertEqual("http://event-endpoint:8009/v2/event_types",
response.headers['Location'])
def test_gnocchi_enabled_without_database_backend_keystone(self):
self._setup_keystone_mock()
self._do_test_gnocchi_enabled_without_database_backend()
@ -143,6 +171,16 @@ class TestAPIUpgradePath(v2.FunctionalTest):
self.assertEqual([mock.call(service_type="alarming")],
self.catalog.url_for.mock_calls)
def test_event_redirect_keystone(self):
self._setup_keystone_mock()
self._do_test_event_redirect()
self.assertEqual([mock.call(service_type="event")],
self.catalog.url_for.mock_calls)
def test_alarm_redirect_configoptions(self):
self._setup_osloconfig_options()
self._do_test_alarm_redirect()
def test_event_redirect_configoptions(self):
self._setup_osloconfig_options()
self._do_test_event_redirect()