Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions deploy/kustomize/crds/kobs.io_applications.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ spec:
type: string
namespace:
type: string
placeholders:
additionalProperties:
type: string
type: object
title:
type: string
required:
Expand Down
11 changes: 11 additions & 0 deletions deploy/kustomize/crds/kobs.io_dashboards.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ spec:
type: string
namespace:
type: string
placeholders:
items:
properties:
description:
type: string
name:
type: string
required:
- name
type: object
type: array
rows:
items:
properties:
Expand Down
4 changes: 4 additions & 0 deletions deploy/kustomize/crds/kobs.io_teams.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ spec:
type: string
namespace:
type: string
placeholders:
additionalProperties:
type: string
type: object
title:
type: string
required:
Expand Down
4 changes: 3 additions & 1 deletion pkg/api/apis/application/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 17 additions & 10 deletions pkg/api/apis/dashboard/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,18 @@ type DashboardList struct {
}

type DashboardSpec struct {
Cluster string `json:"cluster,omitempty"`
Namespace string `json:"namespace,omitempty"`
Name string `json:"name,omitempty"`
Title string `json:"title,omitempty"`
Cluster string `json:"cluster,omitempty"`
Namespace string `json:"namespace,omitempty"`
Name string `json:"name,omitempty"`
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
Placeholders []Placeholder `json:"placeholders,omitempty"`
Rows []Row `json:"rows"`
}

type Placeholder struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Rows []Row `json:"rows"`
}

type Row struct {
Expand All @@ -56,9 +62,10 @@ type Plugin struct {
}

type Reference struct {
Cluster string `json:"cluster,omitempty"`
Namespace string `json:"namespace,omitempty"`
Name string `json:"name"`
Title string `json:"title"`
Description string `json:"description,omitempty"`
Cluster string `json:"cluster,omitempty"`
Namespace string `json:"namespace,omitempty"`
Name string `json:"name"`
Title string `json:"title"`
Description string `json:"description,omitempty"`
Placeholders map[string]string `json:"placeholders,omitempty"`
}
28 changes: 28 additions & 0 deletions pkg/api/apis/dashboard/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion pkg/api/apis/team/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion pkg/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,12 @@ func New(isDevelopment bool) (*Server, error) {

staticHandler := http.StripPrefix("/", http.FileServer(http.Dir(assetsDir)))
router.HandleFunc("/*", func(w http.ResponseWriter, r *http.Request) {
// When kobs is run in development mode and the request path starts with "/api", we redirect these requests
// to the port, where the API is running ("15220"). We have to return 307 as status code, to preserve the
// used http method. This can be used to test the production build of the React app locally without the need
// of another proxy, which handles the redirect.
if isDevelopment && strings.HasPrefix(r.URL.Path, "/api") {
http.Redirect(w, r, "http://localhost:15220"+r.URL.Path+"?"+r.URL.RawQuery, http.StatusMovedPermanently)
http.Redirect(w, r, "http://localhost:15220"+r.URL.Path+"?"+r.URL.RawQuery, http.StatusTemporaryRedirect)
return
}

Expand Down
13 changes: 11 additions & 2 deletions plugins/dashboards/dashboards.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/kobsio/kobs/pkg/api/clusters"
"github.com/kobsio/kobs/pkg/api/middleware/errresponse"
"github.com/kobsio/kobs/pkg/api/plugins/plugin"
"github.com/kobsio/kobs/plugins/dashboards/pkg/placeholders"

"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
Expand Down Expand Up @@ -79,8 +80,8 @@ func (router *Router) getDashboards(w http.ResponseWriter, r *http.Request) {

// Loop through all the provided references and set the cluster and namespace from the defaults, when it is not
// provided. Then we are using the GetDashboard function for a cluster to get the dashboard by namespace and name.
// Finally we are adding the title from the reference as dashboard title and we are adding the dashboard to a list
// of dashboards.
// Finally we are replacing the placeholders in a dashboard with the provided values and we are adding the title
// from the reference as dashboard title and we are adding the dashboard to a list of dashboards.
for _, reference := range data.References {
if reference.Cluster == "" {
reference.Cluster = data.Defaults.Cluster
Expand All @@ -102,6 +103,14 @@ func (router *Router) getDashboards(w http.ResponseWriter, r *http.Request) {
return
}

if reference.Placeholders != nil {
dashboard, err = placeholders.Replace(reference.Placeholders, *dashboard)
if err != nil {
render.Render(w, r, errresponse.Render(err, http.StatusBadRequest, "could not replace placeholders"))
return
}
}

dashboard.Title = reference.Title
dashboards = append(dashboards, dashboard)
}
Expand Down
40 changes: 40 additions & 0 deletions plugins/dashboards/pkg/placeholders/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package placeholders

import (
"bytes"
"encoding/json"
"html/template"

dashboard "github.com/kobsio/kobs/pkg/api/apis/dashboard/v1beta1"
)

// Replace replaces the placeholders in a dashboard, with the provided values from the placeholders map. The
// placeholders must use the following format in the dashboard to be replaced: "{% .placeholder %}".
// To replace the placeholders we have to convert the dashboard to it's json string representation, which is then passed
// to the template together with the placeholders. The result is then unmarshaled back to the dashboard struct and
// returned.
func Replace(placeholders map[string]string, dash dashboard.DashboardSpec) (*dashboard.DashboardSpec, error) {
out, err := json.Marshal(dash)
if err != nil {
return nil, err
}

tpl, err := template.New("dashboard").Delims("{%", "%}").Parse(string(out))
if err != nil {
return nil, err
}

var buf bytes.Buffer
err = tpl.Execute(&buf, placeholders)
if err != nil {
return nil, err
}

var dashPlaceholders dashboard.DashboardSpec
err = json.Unmarshal([]byte(buf.String()), &dashPlaceholders)
if err != nil {
return nil, err
}

return &dashPlaceholders, nil
}
11 changes: 11 additions & 0 deletions plugins/dashboards/src/utils/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@ export interface IDashboard {
name: string;
title: string;
description?: string;
placeholders?: IPlaceholder[];
rows: IRow[];
}

export interface IPlaceholder {
name: string;
description?: string;
}

export interface IRow {
title?: string;
description?: string;
Expand Down Expand Up @@ -34,4 +40,9 @@ export interface IReference {
name: string;
title: string;
description?: string;
placeholders?: IPlaceholders;
}

export interface IPlaceholders {
[key: string]: string;
}