Add plugins option to enable horizon plugins

`plugins` config option is a json list, containing plugin names.
Removing plugins from the list will disable them.

Change-Id: I0e25a8b2db2f12272ece343076a51bb8bf365653
This commit is contained in:
Guillaume Boutry 2023-08-28 14:46:04 +02:00
parent ab3aa4aa88
commit acb4a09799
2 changed files with 67 additions and 0 deletions

View File

@ -179,3 +179,9 @@ options:
description: |
This option can be used to set the instance sorting to either ascending or descending.
Set True to sort in ascending order or False for descending order.
plugins:
type: string
default: '[]'
description: |
This option can be used to enable plugins for Horizon. The value should be a
JSON formatted list of plugin names.

View File

@ -19,6 +19,7 @@ This charm provide Horizon services as part of an OpenStack
deployment
"""
import json
import logging
from typing import (
List,
@ -30,6 +31,7 @@ import ops.pebble
import ops_sunbeam.charm as sunbeam_charm
import ops_sunbeam.container_handlers as sunbeam_chandlers
import ops_sunbeam.core as sunbeam_core
import ops_sunbeam.guard as sunbeam_guard
from ops.main import (
main,
)
@ -53,6 +55,35 @@ def exec(container: ops.model.Container, cmd: str):
logger.exception(f"Command {cmd!r} failed")
def manage_plugins(
container: ops.model.Container, plugins: List[str], enable: bool
) -> bool:
"""Enable or disable plugins based on enable flag.
Return if any changes were made.
"""
command = "enable" if enable else "disable"
cmd = [
"/usr/bin/plugin_management.py",
command,
] + plugins
logger.debug("%s plugins: %r", command, plugins)
try:
process = container.exec(cmd, timeout=1 * 60)
out, err = process.wait_output()
except ops.pebble.ExecError as e:
logger.debug(
"Error using %r on plugins: %r", command, plugins, exc_info=True
)
raise sunbeam_guard.BlockedExceptionError(
f"Error using {command!r} on plugins: {plugins!r}"
) from e
if err:
logger.warning("Warning when using %r on plugins: %s", command, err)
tag = "Enabled" if enable else "Disabled"
return tag in out
class WSGIHorizonPebbleHandler(sunbeam_chandlers.WSGIPebbleHandler):
"""Horizon Pebble Handler."""
@ -94,6 +125,7 @@ class HorizonOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm):
def __init__(self, framework):
super().__init__(framework)
self._state.set_default(plugins=[])
self.framework.observe(
self.on.get_dashboard_url_action,
self._get_dashboard_url_action,
@ -161,6 +193,35 @@ class HorizonOperatorCharm(sunbeam_charm.OSBaseOperatorAPICharm):
self.ingress_public.url
)
def configure_unit(self, event: ops.framework.EventBase) -> None:
"""Run configuration on this unit."""
self.check_leader_ready()
self.check_relation_handlers_ready()
self.init_container_services()
self.check_pebble_handlers_ready()
self.run_db_sync()
self.configure_plugins(event)
self._state.unit_bootstrapped = True
def configure_plugins(self, event: ops.framework.EventBase) -> None:
"""Configure plugins for horizon."""
plugins = sorted(json.loads(self.config.get("plugins", "[]")))
container = self.model.unit.get_container(self.service_name)
if not container.can_connect():
logger.debug("Container not ready, skipping plugin configuration")
return
old_plugins: List[str] = self._state.plugins # type: ignore
disabled_plugins = list(set(old_plugins) - set(plugins))
any_changes = False
if disabled_plugins:
any_changes |= manage_plugins(container, disabled_plugins, False)
if plugins:
any_changes |= manage_plugins(container, plugins, True)
self._state.plugins = plugins
if any_changes:
container.restart("wsgi-" + self.service_name)
@property
def healthcheck_period(self) -> str:
"""Healthcheck period for horizon service."""