Skip to content

Commit 8eb60d1

Browse files
authored
Allow disabling the dashboard (#639)
1 parent fe23cc5 commit 8eb60d1

File tree

11 files changed

+88
-62
lines changed

11 files changed

+88
-62
lines changed

cmd/dashboard.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ var (
3131
showAllVPAs bool
3232
basePath string
3333
insightsHost string
34+
enableCost bool
3435
)
3536

3637
func init() {
@@ -40,6 +41,7 @@ func init() {
4041
dashboardCmd.PersistentFlags().BoolVar(&onByDefault, "on-by-default", false, "Display every namespace that isn't explicitly excluded.")
4142
dashboardCmd.PersistentFlags().BoolVar(&showAllVPAs, "show-all", false, "Display every VPA, even if it isn't managed by Goldilocks")
4243
dashboardCmd.PersistentFlags().StringVar(&basePath, "base-path", "/", "Path on which the dashboard is served.")
44+
dashboardCmd.PersistentFlags().BoolVar(&enableCost, "enable-cost", true, "If set to false, the cost integration will be disabled on the dashboard.")
4345
dashboardCmd.PersistentFlags().StringVar(&insightsHost, "insights-host", "https://insights.fairwinds.com", "Insights host for retrieving optional cost data.")
4446
}
4547

@@ -56,6 +58,7 @@ var dashboardCmd = &cobra.Command{
5658
dashboard.OnByDefault(onByDefault),
5759
dashboard.ShowAllVPAs(showAllVPAs),
5860
dashboard.InsightsHost(insightsHost),
61+
dashboard.EnableCost(enableCost),
5962
)
6063
http.Handle("/", router)
6164
klog.Infof("Starting goldilocks dashboard server on port %d and basePath %v", serverPort, validBasePath)

pkg/dashboard/dashboard.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,11 @@ func Dashboard(opts Options) http.Handler {
7171
}
7272

7373
data := struct {
74-
VpaData summary.Summary
75-
InsightsHost string
74+
VpaData summary.Summary
75+
Opts Options
7676
}{
77-
VpaData: vpaData,
78-
InsightsHost: opts.insightsHost,
77+
VpaData: vpaData,
78+
Opts: opts,
7979
}
8080

8181
writeTemplate(tmpl, opts, &data, w)
@@ -114,14 +114,14 @@ func API(opts Options) http.Handler {
114114
func getVPAData(opts Options, namespace, costPerCPU, costPerGB string) (summary.Summary, error) {
115115

116116
filterLabels := make(map[string]string)
117-
if !opts.showAllVPAs {
118-
filterLabels = opts.vpaLabels
117+
if !opts.ShowAllVPAs {
118+
filterLabels = opts.VpaLabels
119119
}
120120

121121
summarizer := summary.NewSummarizer(
122122
summary.ForNamespace(namespace),
123123
summary.ForVPAsWithLabels(filterLabels),
124-
summary.ExcludeContainers(opts.excludedContainers),
124+
summary.ExcludeContainers(opts.ExcludedContainers),
125125
)
126126

127127
vpaData, err := summarizer.GetSummary()

pkg/dashboard/namespace-list.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
func NamespaceList(opts Options) http.Handler {
1717
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1818
var listOptions v1.ListOptions
19-
if opts.onByDefault || opts.showAllVPAs {
19+
if opts.OnByDefault || opts.ShowAllVPAs {
2020
listOptions = v1.ListOptions{
2121
LabelSelector: fmt.Sprintf("%s!=false", utils.VpaEnabledLabel),
2222
}
@@ -48,17 +48,23 @@ func NamespaceList(opts Options) http.Handler {
4848
// this helps to not leak additional information like
4949
// annotations, labels, metadata about the Namespace to the
5050
// client UI source code or javascript console
51-
data := []struct {
52-
Name string
53-
}{}
51+
52+
data := struct {
53+
Namespaces []struct {
54+
Name string
55+
}
56+
Opts Options
57+
}{
58+
Opts: opts,
59+
}
5460

5561
for _, ns := range namespacesList.Items {
5662
item := struct {
5763
Name string
5864
}{
5965
Name: ns.Name,
6066
}
61-
data = append(data, item)
67+
data.Namespaces = append(data.Namespaces, item)
6268
}
6369

6470
writeTemplate(tmpl, opts, &data, w)

pkg/dashboard/options.go

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,69 +10,77 @@ type Option func(*Options)
1010

1111
// Options are options for getting and caching the Summarizer's VPAs
1212
type Options struct {
13-
port int
14-
basePath string
15-
vpaLabels map[string]string
16-
excludedContainers sets.Set[string]
17-
onByDefault bool
18-
showAllVPAs bool
19-
insightsHost string
13+
Port int
14+
BasePath string
15+
VpaLabels map[string]string
16+
ExcludedContainers sets.Set[string]
17+
OnByDefault bool
18+
ShowAllVPAs bool
19+
InsightsHost string
20+
EnableCost bool
2021
}
2122

2223
// default options for the dashboard
2324
func defaultOptions() *Options {
2425
return &Options{
25-
port: 8080,
26-
basePath: "/",
27-
vpaLabels: utils.VPALabels,
28-
excludedContainers: sets.Set[string]{},
29-
onByDefault: false,
30-
showAllVPAs: false,
26+
Port: 8080,
27+
BasePath: "/",
28+
VpaLabels: utils.VPALabels,
29+
ExcludedContainers: sets.Set[string]{},
30+
OnByDefault: false,
31+
ShowAllVPAs: false,
32+
EnableCost: true,
3133
}
3234
}
3335

3436
// OnPort is an Option for running the dashboard on a different port
3537
func OnPort(port int) Option {
3638
return func(opts *Options) {
37-
opts.port = port
39+
opts.Port = port
3840
}
3941
}
4042

4143
// ExcludeContainers is an Option for excluding containers in the dashboard summary
4244
func ExcludeContainers(excludedContainers sets.Set[string]) Option {
4345
return func(opts *Options) {
44-
opts.excludedContainers = excludedContainers
46+
opts.ExcludedContainers = excludedContainers
4547
}
4648
}
4749

4850
// ForVPAsWithLabels Option for limiting the dashboard to certain VPAs matching the labels
4951
func ForVPAsWithLabels(vpaLabels map[string]string) Option {
5052
return func(opts *Options) {
51-
opts.vpaLabels = vpaLabels
53+
opts.VpaLabels = vpaLabels
5254
}
5355
}
5456

5557
// OnByDefault is an option for listing all namespaces in the dashboard unless explicitly excluded
5658
func OnByDefault(onByDefault bool) Option {
5759
return func(opts *Options) {
58-
opts.onByDefault = onByDefault
60+
opts.OnByDefault = onByDefault
5961
}
6062
}
6163

6264
func ShowAllVPAs(showAllVPAs bool) Option {
6365
return func(opts *Options) {
64-
opts.showAllVPAs = showAllVPAs
66+
opts.ShowAllVPAs = showAllVPAs
6567
}
6668
}
6769

6870
func BasePath(basePath string) Option {
6971
return func(opts *Options) {
70-
opts.basePath = basePath
72+
opts.BasePath = basePath
7173
}
7274
}
7375

7476
func InsightsHost(insightsHost string) Option {
7577
return func(opts *Options) {
76-
opts.insightsHost = insightsHost
78+
opts.InsightsHost = insightsHost
79+
}
80+
}
81+
82+
func EnableCost(enableCost bool) Option {
83+
return func(opts *Options) {
84+
opts.EnableCost = enableCost
7785
}
7886
}

pkg/dashboard/router.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func GetRouter(setters ...Option) *mux.Router {
5050
setter(opts)
5151
}
5252

53-
router := mux.NewRouter().PathPrefix(opts.basePath).Subrouter()
53+
router := mux.NewRouter().PathPrefix(opts.BasePath).Subrouter()
5454

5555
// health
5656
router.Handle("/health", Health("OK"))
@@ -59,7 +59,7 @@ func GetRouter(setters ...Option) *mux.Router {
5959
// assets
6060
router.Handle("/favicon.ico", Asset("/images/favicon-32x32.png"))
6161
fileServer := http.FileServer(GetAssetBox())
62-
router.PathPrefix("/static/").Handler(http.StripPrefix(path.Join(opts.basePath, "/static/"), fileServer))
62+
router.PathPrefix("/static/").Handler(http.StripPrefix(path.Join(opts.BasePath, "/static/"), fileServer))
6363

6464
// dashboard
6565
router.Handle("/dashboard", Dashboard(*opts))
@@ -71,15 +71,15 @@ func GetRouter(setters ...Option) *mux.Router {
7171
// root
7272
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
7373
// catch all other paths that weren't matched
74-
if r.URL.Path != "/" && r.URL.Path != opts.basePath && r.URL.Path != opts.basePath+"/" {
74+
if r.URL.Path != "/" && r.URL.Path != opts.BasePath && r.URL.Path != opts.BasePath+"/" {
7575
klog.Infof("404: %s", r.URL.Path)
7676
http.NotFound(w, r)
7777
return
7878
}
7979

80-
klog.Infof("redirecting to %v", path.Join(opts.basePath, "/namespaces"))
80+
klog.Infof("redirecting to %v", path.Join(opts.BasePath, "/namespaces"))
8181
// default redirect on root path
82-
http.Redirect(w, r, path.Join(opts.basePath, "/namespaces"), http.StatusMovedPermanently)
82+
http.Redirect(w, r, path.Join(opts.BasePath, "/namespaces"), http.StatusMovedPermanently)
8383
})
8484

8585
// api

pkg/dashboard/templates.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func writeTemplate(tmpl *template.Template, opts Options, data interface{}, w ht
104104
return
105105
}
106106
err = tmpl.Execute(buf, baseTemplateData{
107-
BasePath: validateBasePath(opts.basePath),
107+
BasePath: validateBasePath(opts.BasePath),
108108
Data: data,
109109
JSON: template.JS(jsonData),
110110
})

pkg/dashboard/templates/dashboard.gohtml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<!DOCTYPE html>
22
<html lang="en-US">
33
<head>
4-
{{ template "head" . }}
4+
{{ template "head" .Data }}
55

66
{{ if gt (len .Data.VpaData.Namespaces) 1 }}
77
<script src="static/js/filter.js" type="module"></script>
8-
{{ end }}
8+
99

1010
<noscript>
1111
<style>
@@ -16,12 +16,15 @@
1616
</noscript>
1717

1818
<script>
19-
window.INSIGHTS_HOST = "{{ .Data.InsightsHost }}"
19+
window.INSIGHTS_HOST = "{{ .Data.Opts.InsightsHost }}"
2020
</script>
21+
{{ end }}
2122

23+
{{- if .Data.Opts.EnableCost }}
2224
<script defer src="static/js/email.js"></script>
2325
<script defer src="static/js/api-token.js"></script>
2426
<script defer src="static/js/cost_settings.js"></script>
27+
{{- end }}
2528
</head>
2629

2730
<body class="layoutSidebar">
@@ -31,9 +34,12 @@
3134

3235
<div class="layoutSidebar__main">
3336
<main class="verticalRhythm --rhythm-3">
37+
38+
{{- if .Data.Opts.EnableCost }}
3439
{{ template "email" . }}
3540
{{ template "api_token" . }}
3641
{{ template "cost_settings" . }}
42+
{{- end }}
3743

3844
<h1>Namespace Details</h1>
3945

pkg/dashboard/templates/filter.gohtml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{{ define "filter" }}
22
<noscript>
3-
<p class="controls">{{ len . }} namespaces found</p>
3+
<p class="controls">{{ len .Namespaces }} namespaces found</p>
44
</noscript>
55

66
<form
@@ -31,7 +31,7 @@
3131
3. An output that's always shown visually. We have to remove content from the above two to get them to announce the same content back to back. This would make the words pop in and out visually.
3232
Note that the elements used for dynamic screen reader announcements can't themselves be injected or they won't work. Must be pre-existing containers into which the announcment content is injected.
3333
-->
34-
{{ with $initialStatus := (len .) | printf "%d total namespaces found" }}
34+
{{ with $initialStatus := (len .Namespaces) | printf "%d total namespaces found" }}
3535
<div class="control-block">
3636
<output aria-hidden="true">{{ $initialStatus }}</output>
3737
<output class="visually-hidden" aria-live="polite">{{ $initialStatus }}</output>

pkg/dashboard/templates/head.gohtml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{{ define "head" }}
2-
<base href="{{ .BasePath }}">
2+
<base href="{{ .Opts.BasePath }}">
33
<meta charset="utf-8" />
44
<title>Goldilocks by Fairwinds</title>
55
<meta
@@ -17,8 +17,11 @@
1717
<link rel="stylesheet" href="static/css/utopia.css" />
1818
<link rel="stylesheet" href="static/css/main.css" />
1919
<link rel="stylesheet" href="static/css/fontawesome-5.7.2.css" />
20-
<link rel="stylesheet" href="static/css/prism.css" />
2120

21+
{{- if .Opts.EnableCost }}
22+
<link rel="stylesheet" href="static/css/prism.css" />
2223
<script src="static/js/main.js" type="module"></script>
2324
<script defer src="static/js/prism.js"></script>
25+
{{- end }}
26+
2427
{{ end }}

pkg/dashboard/templates/namespace_list.gohtml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<!DOCTYPE html>
22
<html lang="en-US">
33
<head>
4-
{{ template "head" . }}
4+
{{ template "head" .Data }}
55

6-
{{ if gt (len .Data) 1 }}
6+
{{ if gt (len .Data.Namespaces ) 1 }}
77
<script src="static/js/filter.js" type="module"></script>
88
{{ end }}
99
</head>
@@ -17,16 +17,16 @@
1717
<main class="verticalRhythm">
1818
<h1>Namespaces</h1>
1919

20-
{{ if lt (len .Data) 1 }}
20+
{{ if lt (len .Data.Namespaces) 1 }}
2121
<p>No namespaces are labelled for use by Goldilocks. Try labelling one with <code class="language-shell">kubectl label ns NAMESPACE_NAME goldilocks.fairwinds.com/enabled=true</code></p>
2222

2323
{{ else }}
24-
{{ if gt (len .Data) 1 }}
24+
{{ if gt (len .Data.Namespaces) 1 }}
2525
{{ template "filter" .Data }}
2626
{{ end }}
2727

2828
<ul aria-live="off" class="namespaceList" id="js-filter-container" role="list">
29-
{{ range .Data }}
29+
{{ range .Data.Namespaces }}
3030
<li data-filter="{{ .Name }}">
3131
<a class="buttonLink --withIcon" href="{{ $.BasePath }}dashboard/{{ .Name }}">
3232
{{ .Name }}

0 commit comments

Comments
 (0)