Adapt dashboard schema to validate on some devenv dashboards (#37594)

* Remove null values from JSON

* Specify the color field

* Add note about openness of custom field's struct

* Update schemaVersion

* Specify thresholds

* Add panel id

* Add maxDataPoints and interval

* Add mappings, albeit very under-specified

* Allow empty string for timezone field

This is probably not a good idea - same as allowing nulls.

* Allow false for refresh - otherwise, string

* Make threshold value optional

* Make interval optional

* Fix broken and changed decls in ui models

* Add models.cue for timeseries panel

* Fixups for home dashboard

* Add timeShift, timeFrom

* Abstract out #Target, rejigger comments
This commit is contained in:
sam boyer 2021-08-09 12:49:58 -04:00 committed by GitHub
parent e1637f70bd
commit 6ae5db5608
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 156 additions and 23 deletions

View File

@ -22,7 +22,7 @@ Family: scuemata.#Family & {
// Theme of dashboard.
style: *"light" | "dark"
// Timezone of dashboard,
timezone?: *"browser" | "utc"
timezone?: *"browser" | "utc" | ""
// Whether a dashboard is editable or not.
editable: bool | *true
// 0 for no shared crosshair or tooltip (default).
@ -66,14 +66,62 @@ Family: scuemata.#Family & {
showIn: number | *0
}]
// Auto-refresh interval.
refresh?: string
refresh?: string | false
// Version of the JSON schema, incremented each time a Grafana update brings
// changes to said schema.
schemaVersion: number | *25
// FIXME this is the old schema numbering system, and will be replaced by scuemata
schemaVersion: number | *30
// Version of the dashboard, incremented each time the dashboard is updated.
version?: number
panels?: [...#Panel]
// TODO docs
#FieldColorModeId: "thresholds" | "palette-classic" | "palette-saturated" | "continuous-GrYlRd" | "fixed" @cuetsy(targetType="enum")
// TODO docs
#FieldColorSeriesByMode: "min" | "max" | "last" @cuetsy(targetType="type")
// TODO docs
#FieldColor: {
// The main color scheme mode
mode: #FieldColorModeId | string
// Stores the fixed color value if mode is fixed
fixedColor?: string
// Some visualizations need to know how to assign a series color from by value color schemes
seriesBy?: #FieldColorSeriesByMode
} @cuetsy(targetType="interface")
// TODO docs
#Threshold: {
// TODO docs
// FIXME the corresponding typescript field is required/non-optional, but nulls currently appear here when serializing -Infinity to JSON
value?: number
// TODO docs
color: string
// TODO docs
// TODO are the values here enumerable into a disjunction?
// Some seem to be listed in typescript comment
state?: string
} @cuetsy(targetType="interface")
#ThresholdsMode: "absolute" | "percentage" @cuetsy(targetType="enum")
#ThresholdsConfig: {
mode: #ThresholdsMode
// Must be sorted by 'value', first value is always -Infinity
steps: [...#Threshold]
} @cuetsy(targetType="interface")
// Schema for panel targets is specified by datasource
// plugins. We use a placeholder definition, which the Go
// schema loader either left open/as-is with the Base
// variant of the Dashboard and Panel families, or filled
// with types derived from plugins in the Instance variant.
// When working directly from CUE, importers can extend this
// type directly to achieve the same effect.
#Target: {...}
// Dashboard panels. Panels are canonically defined inline
// because they share a version timeline with the dashboard
// schema; they do not vary independently. We create a separate,
@ -83,6 +131,15 @@ Family: scuemata.#Family & {
// The panel plugin type id.
type: !=""
// TODO docs
id?: number
// FIXME this almost certainly has to be changed in favor of scuemata versions
pluginVersion?: string
// TODO docs
tags?: [...string]
// Internal - the exact major and minor versions of the panel plugin
// schema. Hidden and therefore not a part of the data model, but
// expected to be filled with panel plugin schema versions so that it's
@ -93,6 +150,9 @@ Family: scuemata.#Family & {
// TODO 2-tuple list instead of struct?
panelSchema?: { maj: number, min: number }
// TODO docs
targets?: [...#Target]
// Panel title.
title?: string
// Description.
@ -115,20 +175,33 @@ Family: scuemata.#Family & {
static?: bool
}
// Panel links.
// links?: [..._panelLink]
// FIXME this is temporarily specified as a closed list so
// that validation will pass when no links are present, but
// to force a failure as soon as it's checked against there
// being anything in the list so it can be fixed in
// accordance with that object
links?: []
// Name of template variable to repeat for.
repeat?: string
// Direction to repeat in if 'repeat' is set.
// "h" for horizontal, "v" for vertical.
repeatDirection: *"h" | "v"
// Schema for panel targets is specified by datasource
// plugins. We use a placeholder definition, which the Go
// schema loader either left open/as-is with the Base
// variant of the Dashboard and Panel families, or filled
// with types derived from plugins in the Instance variant.
// When working directly from CUE, importers can extend this
// type directly to achieve the same effect.
targets?: [...{...}]
// TODO docs
maxDataPoints?: number
// TODO docs
// TODO tighter constraint
interval?: string
// TODO docs
// TODO tighter constraint
timeFrom?: string
// TODO docs
// TODO tighter constraint
timeShift?: string
// The values depend on panel type
options: {...}
@ -166,17 +239,25 @@ Family: scuemata.#Family & {
min?: number
max?: number
// // Convert input values into a display string
// mappings?: ValueMapping[];
// Convert input values into a display string
//
// TODO this one corresponds to a complex type with
// generics on the typescript side. Ouch. Will
// either need special care, or we'll just need to
// accept a very loosely specified schema. It's very
// unlikely we'll be able to translate cue to
// typescript generics in the general case, though
// this particular one *may* be able to work.
mappings?: [...{...}]
// // Map numeric values to states
// thresholds?: ThresholdsConfig;
// Map numeric values to states
thresholds?: #ThresholdsConfig
// // Map values to a display color
// color?: FieldColor;
color?: #FieldColor
// // Used when reducing field values
// nullValueMode?: NullValueMode;
// nullValueMode?: NullValueMode
// // The behavior when clicking on a result
links?: [...]
@ -184,10 +265,17 @@ Family: scuemata.#Family & {
// Alternative to empty string
noValue?: string
// TODO conundrum: marking this struct as open would
// - i think - preclude closed validation of
// plugin-defined config bits. But, marking it
// closed makes it impossible to use just this
// schema (the "base" variant) to validate the base
// components of a dashboard.
//
// Can always exist. Valid fields within this are
// defined by the panel plugin - that's the
// PanelFieldConfig that comes from the plugin.
custom?: {}
custom?: {...}
}
overrides: [...{
matcher: {

View File

@ -33,7 +33,7 @@ ScaleDistribution: "linear" | "log" @c
GraphGradientMode: "none" | "opacity" | "hue" | "scheme" @cuetsy(targetType="enum")
LineStyle: {
fill?: "solid" | "dash" | "dot" | "square"
dash?: [number]
dash?: [...number]
} @cuetsy(targetType="interface")
LineConfig: {
lineColor?: string
@ -68,7 +68,7 @@ AxisConfig: {
HideSeriesConfig: {
tooltip: bool
legend: bool
graph: bool
viz: bool
} @cuetsy(targetType="interface")
LegendPlacement: "bottom" | "right" @cuetsy(targetType="type")
LegendDisplayMode: "list" | "table" | "hidden" @cuetsy(targetType="enum")
@ -86,7 +86,7 @@ GraphFieldConfig: LineConfig & FillConfig & PointsConfig & AxisConfig & {
VizLegendOptions: {
displayMode: LegendDisplayMode
placement: LegendPlacement
calcs: [string]
calcs: [...string]
} @cuetsy(targetType="interface")
VizTooltipOptions: {
mode: TooltipDisplayMode

View File

@ -50,9 +50,12 @@ AxisConfig: {
HideSeriesConfig: {
tooltip: bool
legend: bool
graph: bool
viz: bool
} @cuetsy(targetType="interface")
// TODO This is the same composition as what's used in the timeseries panel's
// PanelFieldConfig. If that's the only place it's used, it probably shouldn't
// be assembled here, too
GraphFieldConfig: LineConfig & FillConfig & PointsConfig & AxisConfig & {
drawStyle?: DrawStyle
gradientMode?: GraphGradientMode

View File

@ -0,0 +1,42 @@
// Copyright 2021 Grafana Labs
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package grafanaschema
import (
ui "github.com/grafana/grafana/cue/ui:grafanaschema"
)
Family: {
lineages: [
[
{
PanelOptions: {
legend: ui.VizLegendOptions
tooltip: ui.VizTooltipOptions
}
PanelFieldConfig: {
ui.LineConfig
ui.FillConfig
ui.PointsConfig
ui.AxisConfig
drawStyle?: ui.DrawStyle
gradientMode?: ui.GraphGradientMode
hideFrom?: ui.HideSeriesConfig
}
}
]
]
migrations: []
}