Add ROUTE_PREFIX parameter for working with reverse proxies. (#256)
* Add ROUTE_PREFIX parameter for working with reverse proxies. * [flake8/E304] remove blank line after function decoder * Add APPLICATION_ROOT and use route_prefix in requests. * [black/code-styling] use double quotes instead of single. * handle right events url depending route path * properly handle redirects * [flake8] remove unused module, fix styling issues Co-authored-by: Henning Jacobs <henning@jacobs1.de>
This commit is contained in:
committed by
GitHub
parent
3c6056dac3
commit
89c143d3aa
@@ -163,7 +163,8 @@ The following environment variables are supported:
|
|||||||
Template to make Nodes clickable, e.g. can point to `kube-web-view <https://codeberg.org/hjacobs/kube-web-view/>`_. ``{cluster}`` (cluster ID) and ``{name}`` (Node name) will be replaced in the URL template.
|
Template to make Nodes clickable, e.g. can point to `kube-web-view <https://codeberg.org/hjacobs/kube-web-view/>`_. ``{cluster}`` (cluster ID) and ``{name}`` (Node name) will be replaced in the URL template.
|
||||||
``POD_LINK_URL_TEMPLATE``
|
``POD_LINK_URL_TEMPLATE``
|
||||||
Template to make Pods clickable, e.g. can point to `kube-web-view <https://codeberg.org/hjacobs/kube-web-view/>`_. ``{cluster}`` (cluster ID), ``{namespace}`` (Pod's namespace), and ``{name}`` (Pod name) will be replaced in the URL template.
|
Template to make Pods clickable, e.g. can point to `kube-web-view <https://codeberg.org/hjacobs/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
|
Supported Browsers
|
||||||
==================
|
==================
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export default class App {
|
|||||||
this.config = Config.fromParams(params)
|
this.config = Config.fromParams(params)
|
||||||
this.config.nodeLinkUrlTemplate = config['node_link_url_template']
|
this.config.nodeLinkUrlTemplate = config['node_link_url_template']
|
||||||
this.config.podLinkUrlTemplate = config['pod_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.filterString = (params.get('q') && decodeURIComponent(params.get('q'))) || ''
|
||||||
this.selectedClusters = new Set((params.get('clusters') || '').split(',').filter(x => x))
|
this.selectedClusters = new Set((params.get('clusters') || '').split(',').filter(x => x))
|
||||||
@@ -658,7 +659,7 @@ export default class App {
|
|||||||
this.disconnect()
|
this.disconnect()
|
||||||
const that = this
|
const that = this
|
||||||
// NOTE: path must be relative to work with kubectl proxy out of the box
|
// 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(',')
|
const clusterIds = Array.from(this.selectedClusters).join(',')
|
||||||
if (clusterIds) {
|
if (clusterIds) {
|
||||||
url += '?cluster_ids=' + clusterIds
|
url += '?cluster_ids=' + clusterIds
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ from pathlib import Path
|
|||||||
|
|
||||||
from flask import Flask, redirect, url_for
|
from flask import Flask, redirect, url_for
|
||||||
from .oauth import OAuth2ConsumerBlueprintWithClientRefresh
|
from .oauth import OAuth2ConsumerBlueprintWithClientRefresh
|
||||||
from urllib.parse import urljoin
|
|
||||||
|
|
||||||
from .mock import query_mock_cluster
|
from .mock import query_mock_cluster
|
||||||
from .kubernetes import query_kubernetes_cluster
|
from .kubernetes import query_kubernetes_cluster
|
||||||
@@ -39,7 +38,6 @@ logger = logging.getLogger(__name__)
|
|||||||
SERVER_STATUS = {"shutdown": False}
|
SERVER_STATUS = {"shutdown": False}
|
||||||
AUTHORIZE_URL = os.getenv("AUTHORIZE_URL")
|
AUTHORIZE_URL = os.getenv("AUTHORIZE_URL")
|
||||||
ACCESS_TOKEN_URL = os.getenv("ACCESS_TOKEN_URL")
|
ACCESS_TOKEN_URL = os.getenv("ACCESS_TOKEN_URL")
|
||||||
APP_URL = os.getenv("APP_URL") or ""
|
|
||||||
SCOPE = os.getenv("SCOPE")
|
SCOPE = os.getenv("SCOPE")
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
@@ -97,6 +95,7 @@ def index():
|
|||||||
"index.html",
|
"index.html",
|
||||||
app_js=app_js,
|
app_js=app_js,
|
||||||
version=kube_ops_view.__version__,
|
version=kube_ops_view.__version__,
|
||||||
|
route_prefix=app.app_config["route_prefix"],
|
||||||
app_config_json=json.dumps(app.app_config),
|
app_config_json=json.dumps(app.app_config),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -168,13 +167,13 @@ def redeem_screen_token(token: str):
|
|||||||
except Exception:
|
except Exception:
|
||||||
flask.abort(401)
|
flask.abort(401)
|
||||||
flask.session["auth_token"] = (token, "")
|
flask.session["auth_token"] = (token, "")
|
||||||
return redirect(urljoin(APP_URL, "/"))
|
return redirect(app.config["APPLICATION_ROOT"])
|
||||||
|
|
||||||
|
|
||||||
@app.route("/logout")
|
@app.route("/logout")
|
||||||
def logout():
|
def logout():
|
||||||
flask.session.pop("auth_token", None)
|
flask.session.pop("auth_token", None)
|
||||||
return redirect(urljoin(APP_URL, "/"))
|
return redirect(app.config["APPLICATION_ROOT"])
|
||||||
|
|
||||||
|
|
||||||
def shutdown():
|
def shutdown():
|
||||||
@@ -228,6 +227,17 @@ class CommaSeparatedValues(click.ParamType):
|
|||||||
envvar="SERVER_PORT",
|
envvar="SERVER_PORT",
|
||||||
default=8080,
|
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(
|
@click.option(
|
||||||
"-d", "--debug", is_flag=True, help="Run in debugging mode", envvar="DEBUG"
|
"-d", "--debug", is_flag=True, help="Run in debugging mode", envvar="DEBUG"
|
||||||
)
|
)
|
||||||
@@ -300,6 +310,7 @@ def main(
|
|||||||
query_interval,
|
query_interval,
|
||||||
node_link_url_template: str,
|
node_link_url_template: str,
|
||||||
pod_link_url_template: str,
|
pod_link_url_template: str,
|
||||||
|
route_prefix: str,
|
||||||
):
|
):
|
||||||
logging.basicConfig(level=logging.DEBUG if debug else logging.INFO)
|
logging.basicConfig(level=logging.DEBUG if debug else logging.INFO)
|
||||||
|
|
||||||
@@ -308,9 +319,11 @@ def main(
|
|||||||
app.debug = debug
|
app.debug = debug
|
||||||
app.secret_key = secret_key
|
app.secret_key = secret_key
|
||||||
app.store = store
|
app.store = store
|
||||||
|
app.config["APPLICATION_ROOT"] = route_prefix
|
||||||
app.app_config = {
|
app.app_config = {
|
||||||
"node_link_url_template": node_link_url_template,
|
"node_link_url_template": node_link_url_template,
|
||||||
"pod_link_url_template": pod_link_url_template,
|
"pod_link_url_template": pod_link_url_template,
|
||||||
|
"route_prefix": route_prefix,
|
||||||
}
|
}
|
||||||
|
|
||||||
discoverer: Union[
|
discoverer: Union[
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Kubernetes Operational View {{ version }}</title>
|
<title>Kubernetes Operational View {{ version }}</title>
|
||||||
<link rel="shortcut icon" href="static/favicon.ico">
|
<link rel="shortcut icon" href="{{ route_prefix }}static/favicon.ico">
|
||||||
<style>* {padding: 0; margin: 0} body { color: #aaaaff; background: #000; }</style>
|
<style>* {padding: 0; margin: 0} body { color: #aaaaff; background: #000; }</style>
|
||||||
<style>
|
<style>
|
||||||
/* latin */
|
/* latin */
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
/* ShareTechMono-Regular.ttf: Copyright (c) 2012, Carrois Type Design, Ralph du Carrois (www.carrois.com post@carrois.com), with Reserved Font Name 'Share'
|
/* ShareTechMono-Regular.ttf: Copyright (c) 2012, Carrois Type Design, Ralph du Carrois (www.carrois.com post@carrois.com), with Reserved Font Name 'Share'
|
||||||
License: SIL Open Font License, 1.1 */
|
License: SIL Open Font License, 1.1 */
|
||||||
src: local('Share Tech Mono'), local('ShareTechMono-Regular'), url(static/sharetechmono.woff2) format('woff2');
|
src: local('Share Tech Mono'), local('ShareTechMono-Regular'), url({{ route_prefix }}static/sharetechmono.woff2) format('woff2');
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<!-- make sure the font is loaded -->
|
<!-- make sure the font is loaded -->
|
||||||
<div id="loading" style="font-family: ShareTechMono">Loading..</div>
|
<div id="loading" style="font-family: ShareTechMono">Loading..</div>
|
||||||
<script src="static/build/{{ app_js }}"></script>
|
<script src="{{ route_prefix }}static/build/{{ app_js }}"></script>
|
||||||
<script>document.getElementById('loading').style.display = 'none'; const app = new App({{ app_config_json|safe }}); app.run()</script>
|
<script>document.getElementById('loading').style.display = 'none'; const app = new App({{ app_config_json|safe }}); app.run()</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Screen Tokens</title>
|
<title>Screen Tokens</title>
|
||||||
<link rel="shortcut icon" href="static/favicon.ico">
|
<link rel="shortcut icon" href="{{ route_prefix }}static/favicon.ico">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Screen Tokens</h1>
|
<h1>Screen Tokens</h1>
|
||||||
|
|||||||
Reference in New Issue
Block a user