Add a enabled by files healthcheck plugin
Implements: blueprint enable-by-files-healthcheck Change-Id: Ia8a54cbd38f2faf70bbe91032da36448f2fa2de7
This commit is contained in:
parent
e2ea8dc556
commit
01cd608104
@ -8,6 +8,9 @@
|
||||
.. automodule:: oslo_middleware.healthcheck.disable_by_file
|
||||
:members:
|
||||
|
||||
.. automodule:: oslo_middleware.healthcheck.enable_by_files
|
||||
:members:
|
||||
|
||||
|
||||
Available Plugins
|
||||
------------------
|
||||
|
@ -39,6 +39,7 @@ except ImportError:
|
||||
greenlet = None
|
||||
|
||||
from oslo_middleware import base
|
||||
from oslo_middleware.basic_auth import ConfigInvalid
|
||||
from oslo_middleware.healthcheck import opts
|
||||
|
||||
|
||||
@ -397,6 +398,11 @@ Reason
|
||||
for r in self._conf_get('allowed_source_ranges')]
|
||||
self._ignore_proxied_requests = self._conf_get(
|
||||
'ignore_proxied_requests')
|
||||
|
||||
# (abhishekk): Verify that if `enable_by_files` and
|
||||
# `disable_by_file` backends are not enabled at same time.
|
||||
self._verify_configured_plugins()
|
||||
|
||||
self._backends = stevedore.NamedExtensionManager(
|
||||
self.NAMESPACE, self._conf_get('backends'),
|
||||
name_order=True, invoke_on_load=True,
|
||||
@ -414,6 +420,16 @@ Reason
|
||||
self._default_accept = 'text/plain'
|
||||
self._ignore_path = False
|
||||
|
||||
def _verify_configured_plugins(self):
|
||||
backends = self._conf_get('backends')
|
||||
desired_plugins = ['disable_by_file', 'enable_by_files']
|
||||
|
||||
if set(desired_plugins).issubset(set(backends)):
|
||||
raise ConfigInvalid('`enable_by_files` and `disable_by_file`'
|
||||
' healthcheck middleware should not be '
|
||||
'configured at once.')
|
||||
|
||||
|
||||
def _conf_get(self, key, group='healthcheck'):
|
||||
return super(Healthcheck, self)._conf_get(key, group=group)
|
||||
|
||||
|
60
oslo_middleware/healthcheck/enable_by_files.py
Normal file
60
oslo_middleware/healthcheck/enable_by_files.py
Normal file
@ -0,0 +1,60 @@
|
||||
# Copyright 2024 Red Hat.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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 logging
|
||||
import os
|
||||
|
||||
from oslo_middleware.healthcheck import opts
|
||||
from oslo_middleware.healthcheck import pluginbase
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EnableByFilesHealthcheck(pluginbase.HealthcheckBaseExtension):
|
||||
"""EnableByFilesHealthcheck healthcheck middleware plugin
|
||||
|
||||
This plugin checks presence of a file at a specified location.
|
||||
|
||||
Example of middleware configuration:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[app:healthcheck]
|
||||
paste.app_factory = oslo_middleware:Healthcheck.app_factory
|
||||
path = /healthcheck
|
||||
backends = enable_by_files
|
||||
enable_by_file_paths = /var/lib/glance/images/.marker,
|
||||
/var/lib/glance/os_glance_staging_store/.marker
|
||||
# set to True to enable detailed output, False is the default
|
||||
detailed = False
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(EnableByFilesHealthcheck, self).__init__(*args, **kwargs)
|
||||
self.oslo_conf.register_opts(opts.ENABLE_BY_FILES_OPTS,
|
||||
group='healthcheck')
|
||||
self.file_paths = self._conf_get('enable_by_file_paths')
|
||||
|
||||
def healthcheck(self, server_port):
|
||||
for file_path in self.file_paths:
|
||||
if not os.path.exists(file_path):
|
||||
LOG.warning('EnableByFiles healthcheck middleware: Path %s '
|
||||
'is not present', file_path)
|
||||
return pluginbase.HealthcheckResult(
|
||||
available=False, reason="FILE PATH MISSING",
|
||||
details='File path %s is missing' % file_path)
|
||||
return pluginbase.HealthcheckResult(
|
||||
available=True, reason="OK",
|
||||
details='Specified file paths are available')
|
@ -57,3 +57,11 @@ DISABLE_BY_FILES_OPTS = [
|
||||
'Expects a "port:path" list of strings. Used by '
|
||||
'DisableByFilesPortsHealthcheck plugin.'),
|
||||
]
|
||||
|
||||
|
||||
ENABLE_BY_FILES_OPTS = [
|
||||
cfg.ListOpt('enable_by_file_paths',
|
||||
default=[],
|
||||
help='Check the presence of files. Used by '
|
||||
'EnableByFilesHealthcheck plugin.'),
|
||||
]
|
||||
|
@ -157,7 +157,8 @@ def list_opts_healthcheck():
|
||||
return [
|
||||
('healthcheck', copy.deepcopy(healthcheck_opts.HEALTHCHECK_OPTS +
|
||||
healthcheck_opts.DISABLE_BY_FILE_OPTS +
|
||||
healthcheck_opts.DISABLE_BY_FILES_OPTS))
|
||||
healthcheck_opts.DISABLE_BY_FILES_OPTS +
|
||||
healthcheck_opts.ENABLE_BY_FILES_OPTS))
|
||||
]
|
||||
|
||||
|
||||
|
@ -35,3 +35,17 @@ class TestPasteDeploymentEntryPoints(base.BaseTestCase):
|
||||
factory_names = [extension.name for extension in em]
|
||||
self.assertThat(factory_names,
|
||||
matchers.ContainsAll(factory_classes))
|
||||
|
||||
def test_healthcheck_entry_points(self):
|
||||
healthcheck_plugins = {
|
||||
'disable_by_file': 'DisableByFileHealthcheck',
|
||||
'disable_by_files_ports': 'DisableByFilesPortsHealthcheck',
|
||||
'enable_by_files': 'EnableByFilesHealthcheck'
|
||||
}
|
||||
|
||||
em = stevedore.ExtensionManager('oslo.middleware.healthcheck')
|
||||
|
||||
# Ensure all the healthcheck plugins are defined by their names
|
||||
plugin_names = [extension.name for extension in em]
|
||||
self.assertThat(plugin_names,
|
||||
matchers.ContainsAll(healthcheck_plugins))
|
||||
|
@ -24,6 +24,7 @@ import requests
|
||||
import webob.dec
|
||||
import webob.exc
|
||||
|
||||
from oslo_middleware.basic_auth import ConfigInvalid
|
||||
from oslo_middleware import healthcheck
|
||||
from oslo_middleware.healthcheck import __main__
|
||||
|
||||
@ -201,6 +202,63 @@ class HealthcheckTests(test_base.BaseTestCase):
|
||||
server_port=81)
|
||||
self.assertIn('disable_by_files_ports', self.app._backends.names())
|
||||
|
||||
def test_enablefile_disablefile_configured(self):
|
||||
conf = {'backends': 'disable_by_file,enable_by_files'}
|
||||
self.assertRaises(ConfigInvalid,
|
||||
healthcheck.Healthcheck, self.application, conf)
|
||||
|
||||
def test_enablefile_unconfigured(self):
|
||||
conf = {'backends': 'enable_by_files'}
|
||||
self._do_test(conf, expected_body=b'OK')
|
||||
self.assertIn('enable_by_files', self.app._backends.names())
|
||||
|
||||
def test_enablefile_enabled(self):
|
||||
filename = self.create_tempfiles([('.test', '.foobar')])[0]
|
||||
conf = {'backends': 'enable_by_files',
|
||||
'enable_by_file_paths': filename}
|
||||
self._do_test(conf, expected_body=b'OK')
|
||||
self.assertIn('enable_by_files', self.app._backends.names())
|
||||
|
||||
def test_enablefile_enabled_head(self):
|
||||
filename = self.create_tempfiles([('.test', '.foobar')])[0]
|
||||
conf = {'backends': 'enable_by_files',
|
||||
'enable_by_file_paths': filename}
|
||||
self._do_test(conf, expected_body=b'', method='HEAD',
|
||||
expected_code=webob.exc.HTTPNoContent.code)
|
||||
|
||||
def test_enablefile_enabled_html_detailed(self):
|
||||
filename = self.create_tempfiles([('.test', '.foobar')])[0]
|
||||
conf = {'backends': 'enable_by_files',
|
||||
'enable_by_file_paths': filename, 'detailed': True}
|
||||
res = self._do_test_request(conf, accept="text/html")
|
||||
self.assertIn(b'Result of 1 checks:', res.body)
|
||||
self.assertIn(b'<TD>OK</TD>', res.body)
|
||||
self.assertEqual(webob.exc.HTTPOk.code, res.status_int)
|
||||
|
||||
def test_enablefile_disabled(self):
|
||||
conf = {'backends': 'enable_by_files',
|
||||
'enable_by_file_paths': '.foobar'}
|
||||
self._do_test(conf,
|
||||
expected_code=webob.exc.HTTPServiceUnavailable.code,
|
||||
expected_body=b'FILE PATH MISSING')
|
||||
self.assertIn('enable_by_files', self.app._backends.names())
|
||||
|
||||
def test_enablefile_disabled_head(self):
|
||||
conf = {'backends': 'enable_by_files',
|
||||
'enable_by_file_paths': '.foobar'}
|
||||
self._do_test(conf,
|
||||
expected_code=webob.exc.HTTPServiceUnavailable.code,
|
||||
expected_body=b'', method='HEAD')
|
||||
self.assertIn('enable_by_files', self.app._backends.names())
|
||||
|
||||
def test_enablefile_disabled_html_detailed(self):
|
||||
conf = {'backends': 'enable_by_files',
|
||||
'enable_by_file_paths': '.foobar', 'detailed': True}
|
||||
res = self._do_test_request(conf, accept="text/html")
|
||||
self.assertIn(b'<TD>FILE PATH MISSING</TD>', res.body)
|
||||
self.assertEqual(webob.exc.HTTPServiceUnavailable.code,
|
||||
res.status_int)
|
||||
|
||||
def test_json_response(self):
|
||||
expected_body = jsonutils.dumps({'detailed': False, 'reasons': []},
|
||||
indent=4,
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
The new ``enable_by_files`` healthcheck plugin has been added.
|
||||
This plugin will help to check whether specified file paths in
|
||||
``[healthcheck] enable_by_file_paths`` are present or not.
|
@ -38,6 +38,7 @@ oslo.config.opts =
|
||||
oslo.middleware.healthcheck =
|
||||
disable_by_file = oslo_middleware.healthcheck.disable_by_file:DisableByFileHealthcheck
|
||||
disable_by_files_ports = oslo_middleware.healthcheck.disable_by_file:DisableByFilesPortsHealthcheck
|
||||
enable_by_files = oslo_middleware.healthcheck.enable_by_files:EnableByFilesHealthcheck
|
||||
|
||||
paste.app_factory =
|
||||
healthcheck = oslo_middleware:Healthcheck.app_factory
|
||||
|
Loading…
Reference in New Issue
Block a user