From 333195ce2167874aee98fc29347f0aaeba38a5d1 Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Wed, 1 Jun 2022 15:05:27 +0100 Subject: [PATCH] Chore: Dashboard schema (#49993) * user essentials mob! :trident: * user essentials mob! :trident: lastFile:pkg/coremodel/dashboard/lineage.cue * user essentials mob! :trident: Co-authored-by: joshhunt Co-authored-by: polinaboneva --- .../dashboard/dashboard_experimental.gen.ts | 22 +- pkg/coremodel/dashboard/coremodel_gen.go | 63 ++--- pkg/coremodel/dashboard/lineage.cue | 265 +++++++++--------- 3 files changed, 170 insertions(+), 180 deletions(-) diff --git a/packages/grafana-schema/src/schema/dashboard/dashboard_experimental.gen.ts b/packages/grafana-schema/src/schema/dashboard/dashboard_experimental.gen.ts index 33850d2d83d..7a81453e012 100644 --- a/packages/grafana-schema/src/schema/dashboard/dashboard_experimental.gen.ts +++ b/packages/grafana-schema/src/schema/dashboard/dashboard_experimental.gen.ts @@ -76,6 +76,21 @@ interface FieldColor { seriesBy?: FieldColorSeriesByMode; } +interface GridPos { + h: number; + static?: boolean; + w: number; + x: number; + y: number; +} + +const defaultGridPos: Partial = { + h: 9, + w: 12, + x: 0, + y: 0, +}; + interface Threshold { color: string; state?: string; @@ -123,12 +138,7 @@ interface Panel { }[]; }[]; }; - gridPos?: { - h: number; - w: number; - x: number; - y: number; - }; + gridPos?: GridPos; id?: number; interval?: string; links?: DashboardLink[]; diff --git a/pkg/coremodel/dashboard/coremodel_gen.go b/pkg/coremodel/dashboard/coremodel_gen.go index 56d19f5494f..6f6be5b51f0 100644 --- a/pkg/coremodel/dashboard/coremodel_gen.go +++ b/pkg/coremodel/dashboard/coremodel_gen.go @@ -370,6 +370,27 @@ type ModelGraphPanel struct { // Equivalent Go types at stable import paths are provided in https://github.com/grafana/grok. type ModelGraphPanelType string +// DashboardGridPos defines model for dashboard.GridPos. +// +// THIS TYPE IS INTENDED FOR INTERNAL USE BY THE GRAFANA BACKEND, AND IS SUBJECT TO BREAKING CHANGES. +// Equivalent Go types at stable import paths are provided in https://github.com/grafana/grok. +type ModelGridPos struct { + // Panel + H int `json:"h"` + + // true if fixed + Static *bool `json:"static,omitempty"` + + // Panel + W int `json:"w"` + + // Panel x + X int `json:"x"` + + // Panel y + Y int `json:"y"` +} + // DashboardHeatmapPanel defines model for dashboard.HeatmapPanel. // // THIS TYPE IS INTENDED FOR INTERNAL USE BY THE GRAFANA BACKEND, AND IS SUBJECT TO BREAKING CHANGES. @@ -468,24 +489,7 @@ type ModelPanel struct { } `json:"properties"` } `json:"overrides"` } `json:"fieldConfig"` - - // Grid position. - GridPos *struct { - // Panel - H int `json:"h"` - - // true if fixed - Static *bool `json:"static,omitempty"` - - // Panel - W int `json:"w"` - - // Panel x - X int `json:"x"` - - // Panel y - Y int `json:"y"` - } `json:"gridPos,omitempty"` + GridPos *ModelGridPos `json:"gridPos,omitempty"` // TODO docs Id *int `json:"id,omitempty"` @@ -521,7 +525,7 @@ type ModelPanel struct { // TODO docs Targets *[]ModelTarget `json:"targets,omitempty"` - // TODO docs + // TODO docs - seems to be an old field from old dashboard alerts? Thresholds *[]interface{} `json:"thresholds,omitempty"` // TODO docs @@ -568,24 +572,9 @@ type ModelRowPanel struct { Type *string `json:"type,omitempty"` Uid *string `json:"uid,omitempty"` } `json:"datasource,omitempty"` - GridPos *struct { - // Panel - H int `json:"h"` - - // true if fixed - Static *bool `json:"static,omitempty"` - - // Panel - W int `json:"w"` - - // Panel x - X int `json:"x"` - - // Panel y - Y int `json:"y"` - } `json:"gridPos,omitempty"` - Id int `json:"id"` - Panels []interface{} `json:"panels"` + GridPos *ModelGridPos `json:"gridPos,omitempty"` + Id int `json:"id"` + Panels []interface{} `json:"panels"` // Name of template variable to repeat for. Repeat *string `json:"repeat,omitempty"` diff --git a/pkg/coremodel/dashboard/lineage.cue b/pkg/coremodel/dashboard/lineage.cue index d622d638066..f0f45bdf4de 100644 --- a/pkg/coremodel/dashboard/lineage.cue +++ b/pkg/coremodel/dashboard/lineage.cue @@ -22,21 +22,21 @@ seqs: [ // Description of dashboard. description?: string - gnetId?: string + gnetId?: string @reviewme() // Tags associated with dashboard. - tags?: [...string] + tags?: [...string] @reviewme() // Theme of dashboard. - style: "light" | *"dark" + style: "light" | *"dark" @reviewme() // Timezone of dashboard, - timezone?: *"browser" | "utc" | "" + timezone?: *"browser" | "utc" | "" @reviewme() // Whether a dashboard is editable or not. editable: bool | *true - graphTooltip: #DashboardCursorSync + graphTooltip: #DashboardCursorSync @reviewme() // Time range for dashboard, e.g. last 6 hours, last 7 days, etc time?: { from: string | *"now-6h" to: string | *"now" - } + } @reviewme() // TODO docs // TODO this appears to be spread all over in the frontend. Concepts will likely need tidying in tandem with schema changes @@ -49,29 +49,29 @@ seqs: [ hidden: bool | *false // Selectable intervals for auto-refresh. refresh_intervals: [...string] | *["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] - } + } @reviewme() // TODO docs - fiscalYearStartMonth?: uint8 & >0 & <13 + fiscalYearStartMonth?: uint8 & >0 & <13 @reviewme() // TODO docs - liveNow?: bool + liveNow?: bool @reviewme() // TODO docs - weekStart?: string + weekStart?: string @reviewme() // TODO docs - refresh?: string | false + refresh?: string | false @reviewme() // Version of the JSON schema, incremented each time a Grafana update brings // changes to said schema. // TODO this is the existing schema numbering system. It will be replaced by Thema's themaVersion - schemaVersion: uint16 | *36 + schemaVersion: uint16 | *36 @reviewme() // Version of the dashboard, incremented each time the dashboard is updated. - version?: uint32 - panels?: [...(#Panel | #GraphPanel | #HeatmapPanel | #RowPanel)] + version?: uint32 @reviewme() + panels?: [...(#Panel | #GraphPanel | #HeatmapPanel | #RowPanel)] @reviewme() // TODO docs - templating?: list: [...#VariableModel] + templating?: list: [...#VariableModel] @reviewme() // TODO docs - annotations?: list: [...#AnnotationQuery] + annotations?: list: [...#AnnotationQuery] @reviewme() // TODO docs - links?: [...#DashboardLink] + links?: [...#DashboardLink] @reviewme() /////////////////////////////////////// // Definitions (referenced above) are declared below @@ -83,22 +83,22 @@ seqs: [ datasource: { type?: string uid?: string - } + } @reviewme() // Whether annotation is enabled. - enable: bool | *true + enable: bool | *true @reviewme() // Name of annotation. - name?: string - builtIn: uint8 | *0 // TODO should this be persisted at all? + name?: string @reviewme() + builtIn: uint8 | *0 @reviewme() // TODO should this be persisted at all? // Whether to hide annotation. - hide?: bool | *false + hide?: bool | *false @reviewme() // Annotation icon color. - iconColor?: string - type: string | *"dashboard" + iconColor?: string @reviewme() + type: string | *"dashboard" @reviewme() // Query for annotation data. - rawQuery?: string - showIn: uint8 | *0 - target?: #Target // TODO currently a generic in AnnotationQuery + rawQuery?: string @reviewme() + showIn: uint8 | *0 @reviewme() + target?: #Target @reviewme() // TODO currently a generic in AnnotationQuery } @cuetsy(kind="interface") // FROM: packages/grafana-data/src/types/templateVars.ts @@ -110,36 +110,36 @@ seqs: [ name: string label?: string ... - } @cuetsy(kind="interface") + } @cuetsy(kind="interface") @reviewme() // FROM public/app/features/dashboard/state/DashboardModels.ts - ish // TODO docs #DashboardLink: { - title: string - type: #DashboardLinkType - icon?: string - tooltip?: string - url?: string - tags: [...string] - asDropdown: bool | *false - targetBlank: bool | *false - includeVars: bool | *false - keepTime: bool | *false + title: string @reviewme() + type: #DashboardLinkType @reviewme() + icon?: string @reviewme() + tooltip?: string @reviewme() + url?: string @reviewme() + tags: [...string] @reviewme() + asDropdown: bool | *false @reviewme() + targetBlank: bool | *false @reviewme() + includeVars: bool | *false @reviewme() + keepTime: bool | *false @reviewme() } @cuetsy(kind="interface") // TODO docs - #DashboardLinkType: "link" | "dashboards" @cuetsy(kind="type") + #DashboardLinkType: "link" | "dashboards" @cuetsy(kind="type") @reviewme() // FROM: packages/grafana-data/src/types/templateVars.ts // TODO docs // TODO this implies some wider pattern/discriminated union, probably? - #VariableType: "query" | "adhoc" | "constant" | "datasource" | "interval" | "textbox" | "custom" | "system" @cuetsy(kind="type") + #VariableType: "query" | "adhoc" | "constant" | "datasource" | "interval" | "textbox" | "custom" | "system" @cuetsy(kind="type") @reviewme() // TODO docs - #FieldColorModeId: "thresholds" | "palette-classic" | "palette-saturated" | "continuous-GrYlRd" | "fixed" @cuetsy(kind="enum",memberNames="Thresholds|PaletteClassic|PaletteSaturated|ContinuousGrYlRd|Fixed") + #FieldColorModeId: "thresholds" | "palette-classic" | "palette-saturated" | "continuous-GrYlRd" | "fixed" @cuetsy(kind="enum",memberNames="Thresholds|PaletteClassic|PaletteSaturated|ContinuousGrYlRd|Fixed") @reviewme() // TODO docs - #FieldColorSeriesByMode: "min" | "max" | "last" @cuetsy(kind="type") + #FieldColorSeriesByMode: "min" | "max" | "last" @cuetsy(kind="type") @reviewme() // TODO docs #FieldColor: { @@ -149,41 +149,54 @@ seqs: [ fixedColor?: string // Some visualizations need to know how to assign a series color from by value color schemes seriesBy?: #FieldColorSeriesByMode - } @cuetsy(kind="interface") + } @cuetsy(kind="interface") @reviewme() + + #GridPos: { + // Panel + h: uint32 & >0 | *9 @reviewme() + // Panel + w: uint32 & >0 & <=24 | *12 @reviewme() + // Panel x + x: uint32 & >=0 & <24 | *0 @reviewme() + // Panel y + y: uint32 & >=0 | *0 @reviewme() + // true if fixed + static?: bool @reviewme() + } @cuetsy(kind="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 + value?: number @reviewme() // TODO docs - color: string + color: string @reviewme() // TODO docs // TODO are the values here enumerable into a disjunction? // Some seem to be listed in typescript comment - state?: string - } @cuetsy(kind="interface") + state?: string @reviewme() + } @cuetsy(kind="interface") @reviewme() - #ThresholdsMode: "absolute" | "percentage" @cuetsy(kind="enum") + #ThresholdsMode: "absolute" | "percentage" @cuetsy(kind="enum") @reviewme() #ThresholdsConfig: { - mode: #ThresholdsMode + mode: #ThresholdsMode @reviewme() // Must be sorted by 'value', first value is always -Infinity - steps: [...#Threshold] - } @cuetsy(kind="interface") + steps: [...#Threshold] @reviewme() + } @cuetsy(kind="interface") @reviewme() // TODO docs // FIXME this is extremely underspecfied; wasn't obvious which typescript types corresponded to it #Transformation: { id: string options: {...} - } @cuetsy(kind="interface") + } @cuetsy(kind="interface") @reviewme() // 0 for no shared crosshair or tooltip (default). // 1 for shared crosshair. // 2 for shared crosshair AND shared tooltip. - #DashboardCursorSync: *0 | 1 | 2 @cuetsy(kind="enum",memberNames="Off|Crosshair|Tooltip") + #DashboardCursorSync: *0 | 1 | 2 @cuetsy(kind="enum",memberNames="Off|Crosshair|Tooltip") @reviewme() // Schema for panel targets is specified by datasource // plugins. We use a placeholder definition, which the Go @@ -192,121 +205,110 @@ seqs: [ // 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: {...} + #Target: {...} @reviewme() // Dashboard panels. Panels are canonically defined inline // because they share a version timeline with the dashboard // schema; they do not evolve independently. #Panel: { // The panel plugin type id. May not be empty. - type: string & strings.MinRunes(1) + type: string & strings.MinRunes(1) @reviewme() // TODO docs - id?: uint32 + id?: uint32 @reviewme() // FIXME this almost certainly has to be changed in favor of scuemata versions - pluginVersion?: string + pluginVersion?: string @reviewme() // TODO docs - tags?: [...string] + tags?: [...string] @reviewme() // TODO docs - targets?: [...#Target] + targets?: [...#Target] @reviewme() // Panel title. - title?: string + title?: string @reviewme() // Description. - description?: string + description?: string @reviewme() // Whether to display the panel without a background. - transparent: bool | *false + transparent: bool | *false @reviewme() // The datasource used in all targets. datasource?: { type?: string uid?: string - } + } @reviewme() // Grid position. - gridPos?: { - // Panel - h: uint32 & >0 | *9 - // Panel - w: uint32 & >0 & <=24 | *12 - // Panel x - x: uint32 & >=0 & <24 | *0 - // Panel y - y: uint32 & >=0 | *0 - // true if fixed - static?: bool - } + gridPos?: #GridPos // Panel links. // TODO fill this out - seems there are a couple variants? - links?: [...#DashboardLink] + links?: [...#DashboardLink] @reviewme() // Name of template variable to repeat for. - repeat?: string + repeat?: string @reviewme() // Direction to repeat in if 'repeat' is set. // "h" for horizontal, "v" for vertical. - repeatDirection: *"h" | "v" + repeatDirection: *"h" | "v" @reviewme() // TODO docs - maxDataPoints?: number + maxDataPoints?: number @reviewme() + + // TODO docs - seems to be an old field from old dashboard alerts? + thresholds?: [...] @reviewme() // TODO docs - thresholds?: [...] + timeRegions?: [...] @reviewme() - // TODO docs - timeRegions?: [...] - - transformations: [...#Transformation] + transformations: [...#Transformation] @reviewme() // TODO docs // TODO tighter constraint - interval?: string + interval?: string @reviewme() // TODO docs // TODO tighter constraint - timeFrom?: string + timeFrom?: string @reviewme() // TODO docs // TODO tighter constraint - timeShift?: string + timeShift?: string @reviewme() // options is specified by the PanelOptions field in panel // plugin schemas. - options: {...} + options: {...} @reviewme() fieldConfig: { defaults: { // The display value for this field. This supports template variables blank is auto - displayName?: string + displayName?: string @reviewme() // This can be used by data sources that return and explicit naming structure for values and labels // When this property is configured, this value is used rather than the default naming strategy. - displayNameFromDS?: string + displayNameFromDS?: string @reviewme() // Human readable field metadata - description?: string + description?: string @reviewme() // An explict path to the field in the datasource. When the frame meta includes a path, // This will default to `${frame.meta.path}/${field.name} // // When defined, this value can be used as an identifier within the datasource scope, and // may be used to update the results - path?: string + path?: string @reviewme() // True if data source can write a value to the path. Auth/authz are supported separately - writeable?: bool + writeable?: bool @reviewme() // True if data source field supports ad-hoc filters - filterable?: bool + filterable?: bool @reviewme() // Numeric Options - unit?: string + unit?: string @reviewme() // Significant digits (for display) - decimals?: number + decimals?: number @reviewme() - min?: number - max?: number + min?: number @reviewme() + max?: number @reviewme() // Convert input values into a display string // @@ -317,79 +319,68 @@ seqs: [ // 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?: [...{...}] + mappings?: [...{...}] @reviewme() // Map numeric values to states - thresholds?: #ThresholdsConfig + thresholds?: #ThresholdsConfig @reviewme() // // Map values to a display color - color?: #FieldColor + color?: #FieldColor @reviewme() // // Used when reducing field values // nullValueMode?: NullValueMode // // The behavior when clicking on a result - links?: [...] + links?: [...] @reviewme() // Alternative to empty string - noValue?: string + noValue?: string @reviewme() // custom is specified by the PanelFieldConfig field // in panel plugin schemas. - custom?: {...} - } + custom?: {...} @reviewme() + } @reviewme() overrides: [...{ matcher: { - id: string | *"" - options?: _ + id: string | *"" @reviewme() + options?: _ @reviewme() } properties: [...{ - id: string | *"" - value?: _ + id: string | *"" @reviewme() + value?: _ @reviewme() }] - }] + }] @reviewme() } - } @cuetsy(kind="interface") + } @cuetsy(kind="interface") @reviewme() // Row panel #RowPanel: { - type: "row" - collapsed: bool | *false - title?: string + type: "row" @reviewme() + collapsed: bool | *false @reviewme() + title?: string @reviewme() // Name of default datasource. datasource?: { - type?: string - uid?: string - } + type?: string @reviewme() + uid?: string @reviewme() + } @reviewme() - gridPos?: { - // Panel - h: uint32 & >0 | *9 - // Panel - w: uint32 & >0 & <=24 | *12 - // Panel x - x: uint32 & >=0 & <24 | *0 - // Panel y - y: uint32 & >=0 | *0 - // true if fixed - static?: bool - } - id: uint32 - panels: [...(#Panel | #GraphPanel | #HeatmapPanel)] + gridPos?: #GridPos + id: uint32 @reviewme() + panels: [...(#Panel | #GraphPanel | #HeatmapPanel)] @reviewme() // Name of template variable to repeat for. - repeat?: string - } + repeat?: string @reviewme() + } @reviewme() // Support for legacy graph and heatmap panels. #GraphPanel: { - type: "graph" + type: "graph" @reviewme() ... - } + } @reviewme() #HeatmapPanel: { - type: "heatmap" + type: "heatmap" @reviewme() ... - } + } @reviewme() }, ] },