From 6e9f1f72523afbfa04b09f85f95f77bf962c763f Mon Sep 17 00:00:00 2001 From: Artyom Zavrin Date: Thu, 21 Oct 2021 19:52:59 +0300 Subject: [PATCH] New action button with custom URL --- docs/configuration.rst | 30 ++++++++++++++++++++++++++++++ supervisor/options.py | 14 ++++++++++++-- supervisor/skel/sample.conf | 2 ++ supervisor/web.py | 16 +++++++++++++--- 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/docs/configuration.rst b/docs/configuration.rst index 84f8c8c3e..a6394e487 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -1138,6 +1138,36 @@ where specified. *Introduced*: 3.0 +``custom_action_name`` + + Custom action name to be displayed along the usual Start/Stop/Tail log + actions in the Web UI. When this custom action button is clicked a new + browser window will open with URL provided by custom_action_href parameter. + This is useful for example to open an application dashboard or control panel. + Both custom_action_name and custom_action_href parameters have to be + defined for custom button to be displayed. + + *Default*: None + + *Required*: No. + + *Introduced*: 4.3.0 + +``custom_action_href`` + + Custom action link to be displayed along the usual Start/Stop/Tail log + actions in the Web UI. Title for the custom action link is defined by the + custom_action_name parameter. When this custom action button is clicked a new + browser window will open with URL provided by custom_action_href parameter. + Both custom_action_name and custom_action_href parameters have to be + defined for custom button to be displayed. + + *Default*: None + + *Required*: No. + + *Introduced*: 4.3.0 + ``[program:x]`` Section Example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/supervisor/options.py b/supervisor/options.py index 7b53cc760..d1016fe49 100644 --- a/supervisor/options.py +++ b/supervisor/options.py @@ -1026,6 +1026,13 @@ def get(section, opt, *args, **kwargs): raise ValueError( 'program section %s does not specify a command' % section) + custom_action_name = get(section, 'custom_action_name', None, expansions=expansions) + custom_action_href = get(section, 'custom_action_href', None, expansions=expansions) + if custom_action_name is None: + custom_action_href = None + if custom_action_href is None: + custom_action_name = None + pconfig = klass( self, name=expand(process_name, expansions, 'process_name'), @@ -1057,7 +1064,9 @@ def get(section, opt, *args, **kwargs): exitcodes=exitcodes, redirect_stderr=redirect_stderr, environment=environment, - serverurl=serverurl) + serverurl=serverurl, + custom_action_name=custom_action_name, + custom_action_href=custom_action_href) programs.append(pconfig) @@ -1874,7 +1883,8 @@ class ProcessConfig(Config): 'stderr_logfile_backups', 'stderr_logfile_maxbytes', 'stderr_events_enabled', 'stderr_syslog', 'stopsignal', 'stopwaitsecs', 'stopasgroup', 'killasgroup', - 'exitcodes', 'redirect_stderr' ] + 'exitcodes', 'redirect_stderr', + 'custom_action_name', 'custom_action_href' ] optional_param_names = [ 'environment', 'serverurl' ] def __init__(self, options, **params): diff --git a/supervisor/skel/sample.conf b/supervisor/skel/sample.conf index 289c9cb38..65bcc256d 100644 --- a/supervisor/skel/sample.conf +++ b/supervisor/skel/sample.conf @@ -115,6 +115,8 @@ serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket ;stderr_syslog=false ; send stderr to syslog with process name (default false) ;environment=A="1",B="2" ; process environment additions (def no adds) ;serverurl=AUTO ; override serverurl computation (childutils) +;custom_action_name=Link Title ; Title for custom action in the web UI +;custom_action_href=http://url ; URL for custom action button in the web UI ; The sample eventlistener section below shows all possible eventlistener ; subsection values. Create one or more 'real' eventlistener: sections to be diff --git a/supervisor/web.py b/supervisor/web.py index ee1568165..37f3535db 100644 --- a/supervisor/web.py +++ b/supervisor/web.py @@ -269,13 +269,23 @@ def actions_for_process(self, process): 'href': 'logtail/%s/stderr' % processname, 'target': '_blank' } + if (process.config.custom_action_name is not None + and process.config.custom_action_href is not None): + custom_action = { + 'name': process.config.custom_action_name, + 'href': process.config.custom_action_href, + 'target': '_blank' + } + else: + custom_action = None if state == ProcessStates.RUNNING: - actions = [restart, stop, clearlog, tailf_stdout, tailf_stderr] + actions = [restart, stop, clearlog, tailf_stdout, tailf_stderr, + custom_action] elif state in (ProcessStates.STOPPED, ProcessStates.EXITED, ProcessStates.FATAL): - actions = [start, None, clearlog, tailf_stdout, tailf_stderr] + actions = [start, None, clearlog, tailf_stdout, tailf_stderr, None] else: - actions = [None, None, clearlog, tailf_stdout, tailf_stderr] + actions = [None, None, clearlog, tailf_stdout, tailf_stderr, None] return actions def css_class_for_state(self, state):