diff --git a/README.rst b/README.rst
index 8d32e3c..55e04b4 100644
--- a/README.rst
+++ b/README.rst
@@ -163,7 +163,8 @@ The following environment variables are supported:
Template to make Nodes clickable, e.g. can point to `kube-web-view `_. ``{cluster}`` (cluster ID) and ``{name}`` (Node name) will be replaced in the URL template.
``POD_LINK_URL_TEMPLATE``
Template to make Pods clickable, e.g. can point to `kube-web-view `_. ``{cluster}`` (cluster ID), ``{namespace}`` (Pod's namespace), and ``{name}`` (Pod name) will be replaced in the URL template.
-
+``ROUTE_PREFIX``
+ The URL prefix under which kube-ops-view is externally reachable (for example, if kube-ops-view is served via a reverse proxy). Used for generating relative and absolute links back to kube-ops-view itself. If the URL has a path portion, it will be used to prefix all HTTP endpoints served by kube-ops-view. If omitted, relevant URL components will be derived automatically.
Supported Browsers
==================
diff --git a/app/src/app.js b/app/src/app.js
index 48495ed..05318cb 100644
--- a/app/src/app.js
+++ b/app/src/app.js
@@ -20,6 +20,7 @@ export default class App {
this.config = Config.fromParams(params)
this.config.nodeLinkUrlTemplate = config['node_link_url_template']
this.config.podLinkUrlTemplate = config['pod_link_url_template']
+ this.config.route_prefix = config['route_prefix']
this.filterString = (params.get('q') && decodeURIComponent(params.get('q'))) || ''
this.selectedClusters = new Set((params.get('clusters') || '').split(',').filter(x => x))
@@ -658,7 +659,7 @@ export default class App {
this.disconnect()
const that = this
// NOTE: path must be relative to work with kubectl proxy out of the box
- let url = 'events'
+ let url = this.config.route_prefix + (this.config.route_prefix === '/' ? 'events' : '/events')
const clusterIds = Array.from(this.selectedClusters).join(',')
if (clusterIds) {
url += '?cluster_ids=' + clusterIds
diff --git a/kube_ops_view/main.py b/kube_ops_view/main.py
index 7bc9408..1d9f654 100644
--- a/kube_ops_view/main.py
+++ b/kube_ops_view/main.py
@@ -19,7 +19,6 @@ from pathlib import Path
from flask import Flask, redirect, url_for
from .oauth import OAuth2ConsumerBlueprintWithClientRefresh
-from urllib.parse import urljoin
from .mock import query_mock_cluster
from .kubernetes import query_kubernetes_cluster
@@ -39,7 +38,6 @@ logger = logging.getLogger(__name__)
SERVER_STATUS = {"shutdown": False}
AUTHORIZE_URL = os.getenv("AUTHORIZE_URL")
ACCESS_TOKEN_URL = os.getenv("ACCESS_TOKEN_URL")
-APP_URL = os.getenv("APP_URL") or ""
SCOPE = os.getenv("SCOPE")
app = Flask(__name__)
@@ -97,6 +95,7 @@ def index():
"index.html",
app_js=app_js,
version=kube_ops_view.__version__,
+ route_prefix=app.app_config["route_prefix"],
app_config_json=json.dumps(app.app_config),
)
@@ -168,13 +167,13 @@ def redeem_screen_token(token: str):
except Exception:
flask.abort(401)
flask.session["auth_token"] = (token, "")
- return redirect(urljoin(APP_URL, "/"))
+ return redirect(app.config["APPLICATION_ROOT"])
@app.route("/logout")
def logout():
flask.session.pop("auth_token", None)
- return redirect(urljoin(APP_URL, "/"))
+ return redirect(app.config["APPLICATION_ROOT"])
def shutdown():
@@ -228,6 +227,17 @@ class CommaSeparatedValues(click.ParamType):
envvar="SERVER_PORT",
default=8080,
)
+@click.option(
+ "--route-prefix",
+ help="""The URL prefix under which kube-ops-view is externally reachable
+ (for example, if kube-ops-view is served via a reverse proxy). Used for
+ generating relative and absolute links back to kube-ops-view itself. If the
+ URL has a path portion, it will be used to prefix all HTTP endpoints served
+ by kube-ops-view. If omitted, relevant URL components will be derived
+ automatically.""",
+ envvar="ROUTE_PREFIX",
+ default="/",
+)
@click.option(
"-d", "--debug", is_flag=True, help="Run in debugging mode", envvar="DEBUG"
)
@@ -300,6 +310,7 @@ def main(
query_interval,
node_link_url_template: str,
pod_link_url_template: str,
+ route_prefix: str,
):
logging.basicConfig(level=logging.DEBUG if debug else logging.INFO)
@@ -308,9 +319,11 @@ def main(
app.debug = debug
app.secret_key = secret_key
app.store = store
+ app.config["APPLICATION_ROOT"] = route_prefix
app.app_config = {
"node_link_url_template": node_link_url_template,
"pod_link_url_template": pod_link_url_template,
+ "route_prefix": route_prefix,
}
discoverer: Union[
diff --git a/kube_ops_view/templates/index.html b/kube_ops_view/templates/index.html
index bf1d503..d4c42ed 100644
--- a/kube_ops_view/templates/index.html
+++ b/kube_ops_view/templates/index.html
@@ -4,7 +4,7 @@