mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2025-10-02 20:54:32 +02:00
Implement UI config handling
This commit is contained in:
177
web/configSchema.go
Normal file
177
web/configSchema.go
Normal file
@@ -0,0 +1,177 @@
|
||||
// Copyright (C) NHR@FAU, University Erlangen-Nuremberg.
|
||||
// All rights reserved. This file is part of cc-backend.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package web
|
||||
|
||||
var configSchema = `
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"jobList": {
|
||||
"description": "Job list defaults. Applies to user- and jobs views.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"usePaging": {
|
||||
"description": "If classic paging is used instead of continuous scrolling by default.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"showFootprint": {
|
||||
"description": "If footprint bars are shown as first column by default.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": ["usePaging", "showFootprint"]
|
||||
},
|
||||
"nodeList": {
|
||||
"description": "Node list defaults. Applies to node list view.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"usePaging": {
|
||||
"description": "If classic paging is used instead of continuous scrolling by default.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": ["usePaging"]
|
||||
},
|
||||
"jobView": {
|
||||
"description": "Job view defaults.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"showPolarPlot": {
|
||||
"description": "If the job metric footprints polar plot is shown by default.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"showFootprint": {
|
||||
"description": "If the annotated job metric footprint bars are shown by default.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"showRoofline": {
|
||||
"description": "If the job roofline plot is shown by default.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"showStatTable": {
|
||||
"description": "If the job metric statistics table is shown by default.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": ["showFootprint"]
|
||||
},
|
||||
"metricConfig": {
|
||||
"description": "Global initial metric selections for primary views of all clusters.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"jobListMetrics": {
|
||||
"description": "Initial metrics shown for new users in job lists (User and jobs view).",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minItems": 1
|
||||
}
|
||||
},
|
||||
"jobViewPlotMetrics": {
|
||||
"description": "Initial metrics shown for new users as job view metric plots.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minItems": 1
|
||||
}
|
||||
},
|
||||
"jobViewTableMetrics": {
|
||||
"description": "Initial metrics shown for new users in job view statistics table.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minItems": 1
|
||||
}
|
||||
},
|
||||
"clusters": {
|
||||
"description": "Overrides for global defaults by cluster and subcluster.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "The name of the cluster.",
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"enum": ["influxdb", "prometheus", "cc-metric-store", "cc-metric-store-internal", "test"]
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"subClusters" {
|
||||
"description": "The array of overrides per subcluster.",
|
||||
"type":"array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "The name of the subcluster.",
|
||||
"type": "string"
|
||||
},
|
||||
"jobListMetrics": {
|
||||
"description": "Initial metrics shown for new users in job lists (User and jobs view) for subcluster.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minItems": 1
|
||||
}
|
||||
},
|
||||
"jobViewPlotMetrics": {
|
||||
"description": "Initial metrics shown for new users as job view timeplots for subcluster.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minItems": 1
|
||||
}
|
||||
},
|
||||
"jobViewTableMetrics": {
|
||||
"description": "Initial metrics shown for new users in job view statistics table for subcluster.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minItems": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["name"],
|
||||
"minItems": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["name", "subClusters"],
|
||||
"minItems": 1
|
||||
}
|
||||
},
|
||||
"required": ["jobListMetrics", "jobViewPlotMetrics", "jobViewTableMetrics"]
|
||||
}
|
||||
},
|
||||
"plotConfiguration": {
|
||||
"description": "Initial settings for plot render options.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"colorBackground": {
|
||||
"description": "If the metric plot backgrounds are initially colored by threshold limits.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"plotsPerRow": {
|
||||
"description": "How many plots are initially rendered in per row. Applies to job, single node, and analysis views.",
|
||||
"type": "integer"
|
||||
},
|
||||
"lineWidth": {
|
||||
"description": "Initial thickness of rendered plotlines. Applies to metric plot, job compare plot and roofline.",
|
||||
"type": "integer"
|
||||
},
|
||||
"colorScheme": {
|
||||
"description": "Initial colorScheme to be used for metric plots.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["colorBackground", "plotsPerRow", "lineWidth"]
|
||||
}
|
||||
}`
|
120
web/web.go
120
web/web.go
@@ -1,15 +1,19 @@
|
||||
// Copyright (C) NHR@FAU, University Erlangen-Nuremberg.
|
||||
// All rights reserved.
|
||||
// All rights reserved. This file is part of cc-backend.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package web implements the HTML templating and web frontend configuration
|
||||
package web
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"html/template"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/ClusterCockpit/cc-backend/internal/config"
|
||||
"github.com/ClusterCockpit/cc-backend/pkg/archive"
|
||||
@@ -18,8 +22,114 @@ import (
|
||||
"github.com/ClusterCockpit/cc-lib/util"
|
||||
)
|
||||
|
||||
/// Go's embed is only allowed to embed files in a subdirectory of the embedding package ([see here](https://github.com/golang/go/issues/46056)).
|
||||
type WebConfig struct {
|
||||
JobList JobListConfig `json:"jobList"`
|
||||
NodeList NodeListConfig `json:"nodeList"`
|
||||
JobView JobViewConfig `json:"jobView"`
|
||||
MetricConfig MetricConfig `json:"metricConfig"`
|
||||
PlotConfiguration PlotConfiguration `json:"plotConfiguration"`
|
||||
}
|
||||
|
||||
type JobListConfig struct {
|
||||
UsePaging bool `json:"usePaging"`
|
||||
ShowFootprint bool `json:"showFootprint"`
|
||||
}
|
||||
|
||||
type NodeListConfig struct {
|
||||
UsePaging bool `json:"usePaging"`
|
||||
}
|
||||
|
||||
type JobViewConfig struct {
|
||||
ShowPolarPlot bool `json:"showPolarPlot"`
|
||||
ShowFootprint bool `json:"showFootprint"`
|
||||
ShowRoofline bool `json:"showRoofline"`
|
||||
ShowStatTable bool `json:"showStatTable"`
|
||||
}
|
||||
|
||||
type MetricConfig struct {
|
||||
JobListMetrics []string `json:"jobListMetrics"`
|
||||
JobViewPlotMetrics []string `json:"jobViewPlotMetrics"`
|
||||
JobViewTableMetrics []string `json:"jobViewTableMetrics"`
|
||||
Clusters []ClusterConfig `json:"clusters"`
|
||||
}
|
||||
|
||||
type ClusterConfig struct {
|
||||
Name string `json:"name"`
|
||||
SubClusters []SubClusterConfig `json:"subClusters"`
|
||||
}
|
||||
|
||||
type SubClusterConfig struct {
|
||||
Name string `json:"name"`
|
||||
JobListMetrics []string `json:"jobListMetrics"`
|
||||
JobViewPlotMetrics []string `json:"jobViewPlotMetrics"`
|
||||
JobViewTableMetrics []string `json:"jobViewTableMetrics"`
|
||||
}
|
||||
|
||||
type PlotConfiguration struct {
|
||||
ColorBackground bool `json:"colorBackground"`
|
||||
PlotsPerRow int `json:"plotsPerRow"`
|
||||
LineWidth int `json:"lineWidth"`
|
||||
ColorScheme []string `json:"colorScheme"`
|
||||
}
|
||||
|
||||
var initOnce sync.Once
|
||||
|
||||
var Keys = WebConfig{
|
||||
JobList: JobListConfig{
|
||||
UsePaging: false,
|
||||
ShowFootprint: true,
|
||||
},
|
||||
NodeList: NodeListConfig{
|
||||
UsePaging: true,
|
||||
},
|
||||
JobView: JobViewConfig{
|
||||
ShowPolarPlot: true,
|
||||
ShowFootprint: true,
|
||||
ShowRoofline: true,
|
||||
ShowStatTable: true,
|
||||
},
|
||||
MetricConfig: MetricConfig{
|
||||
JobListMetrics: []string{"flops_any", "mem_bw", "mem_used"},
|
||||
JobViewPlotMetrics: []string{"flops_any", "mem_bw", "mem_used"},
|
||||
JobViewTableMetrics: []string{"flops_any", "mem_bw", "mem_used"},
|
||||
},
|
||||
PlotConfiguration: PlotConfiguration{
|
||||
ColorBackground: true,
|
||||
PlotsPerRow: 3,
|
||||
LineWidth: 3,
|
||||
ColorScheme: []string{"#00bfff", "#0000ff", "#ff00ff", "#ff0000", "#ff8000", "#ffff00", "#80ff00"},
|
||||
},
|
||||
}
|
||||
|
||||
//
|
||||
// map[string]any{
|
||||
// "analysis_view_histogramMetrics": []string{"flops_any", "mem_bw", "mem_used"},
|
||||
// "analysis_view_scatterPlotMetrics": [][]string{{"flops_any", "mem_bw"}, {"flops_any", "cpu_load"}, {"cpu_load", "mem_bw"}},
|
||||
// "job_view_nodestats_selectedMetrics": []string{"flops_any", "mem_bw", "mem_used"},
|
||||
// "plot_list_jobsPerPage": 50,
|
||||
// "system_view_selectedMetric": "cpu_load",
|
||||
// "analysis_view_selectedTopEntity": "user",
|
||||
// "analysis_view_selectedTopCategory": "totalWalltime",
|
||||
// "status_view_selectedTopUserCategory": "totalJobs",
|
||||
// "status_view_selectedTopProjectCategory": "totalJobs",
|
||||
// }
|
||||
|
||||
func Init(rawConfig json.RawMessage, disableArchive bool) error {
|
||||
var err error
|
||||
|
||||
initOnce.Do(func() {
|
||||
config.Validate(configSchema, rawConfig)
|
||||
if err = json.Unmarshal(rawConfig, &Keys); err != nil {
|
||||
cclog.Warn("Error while unmarshaling raw config json")
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// / Go's embed is only allowed to embed files in a subdirectory of the embedding package ([see here](https://github.com/golang/go/issues/46056)).
|
||||
//
|
||||
//go:embed frontend/public/*
|
||||
var frontendFiles embed.FS
|
||||
|
||||
@@ -92,9 +202,9 @@ type Page struct {
|
||||
Build Build // Latest information about the application
|
||||
Clusters []config.ClusterConfig // List of all clusters for use in the Header
|
||||
SubClusters map[string][]string // Map per cluster of all subClusters for use in the Header
|
||||
FilterPresets map[string]interface{} // For pages with the Filter component, this can be used to set initial filters.
|
||||
Infos map[string]interface{} // For generic use (e.g. username for /monitoring/user/<id>, job id for /monitoring/job/<id>)
|
||||
Config map[string]interface{} // UI settings for the currently logged in user (e.g. line width, ...)
|
||||
FilterPresets map[string]any // For pages with the Filter component, this can be used to set initial filters.
|
||||
Infos map[string]any // For generic use (e.g. username for /monitoring/user/<id>, job id for /monitoring/job/<id>)
|
||||
Config map[string]any // UI settings for the currently logged in user (e.g. line width, ...)
|
||||
Resampling *config.ResampleConfig // If not nil, defines resampling trigger and resolutions
|
||||
Redirect string // The originally requested URL, for intermediate login handling
|
||||
}
|
||||
|
Reference in New Issue
Block a user