Move dashboard scuemata to grafana-schema (#38470)

* Relocate dashboard scuemata to grafana-schema

* Update assorted tests, vars with dashboard path

* Remove crufty commented var

* Not sure...why that failed

* Remove prefix from base dashboard path var

* Move cue/ui remnants into grafana-schema

* Update import paths in plugin models

* Remove mudball, add package statements

* Remove cuegen.sh

Wooooo we ain't got no codegen

* Revert "Remove mudball, add package statements"

This reverts commit 9bed3098f1.

* Tidy up all the cue files

* Move dashboard scuemata into scuemata/ subdir

Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
sam boyer 2021-08-25 06:55:04 -04:00 committed by GitHub
parent a19ad25eaa
commit e61bc33163
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 152 additions and 574 deletions

View File

@ -1,178 +0,0 @@
package grafanaschema
// FIXME can't write enums as structs, must use disjunctions
TableCellDisplayMode: {
Auto: "auto",
ColorText: "color-text",
ColorBackground: "color-background",
GradientGauge: "gradient-gauge",
LcdGauge: "lcd-gauge",
JSONView: "json-view",
BasicGauge: "basic",
Image: "image",
} @cuetsy(targetType="enum")
TableFieldOptions: {
width?: number
align: FieldTextAlignment | *"auto"
displayMode: TableCellDisplayMode | *"auto"
hidden?: bool // ?? default is missing or false ??
} @cuetsy(targetType="interface")
TableSortByFieldState: {
displayName: string
desc?: bool
} @cuetsy(targetType="interface")
TooltipDisplayMode: "single" | "multi" | "none" @cuetsy(targetType="enum")
FieldTextAlignment: "auto" | "left" | "right" | "center" @cuetsy(targetType="type")
AxisPlacement: "auto" | "top" | "right" | "bottom" | "left" | "hidden" @cuetsy(targetType="enum")
PointVisibility: "auto" | "never" | "always" @cuetsy(targetType="enum")
DrawStyle: "line" | "bars" | "points" @cuetsy(targetType="enum")
LineInterpolation: "linear" | "smooth" | "stepBefore" | "stepAfter" @cuetsy(targetType="enum")
ScaleDistribution: "linear" | "log" @cuetsy(targetType="enum")
GraphGradientMode: "none" | "opacity" | "hue" | "scheme" @cuetsy(targetType="enum")
StackingMode: "none" | "normal" | "percent" @cuetsy(targetType="enum")
BarValueVisibility: "auto" | "never" | "always" @cuetsy(targetType="enum")
BarAlignment: -1 | 0 | 1 @cuetsy(targetType="enum",memberNames="Before|Center|After")
ScaleOrientation: 0 | 1 @cuetsy(targetType="enum",memberNames="Horizontal|Vertical")
ScaleDirection: 1 | 1 | -1 | -1 @cuetsy(targetType="enum",memberNames="Up|Right|Down|Left")
LineStyle: {
fill?: "solid" | "dash" | "dot" | "square"
dash?: [...number]
} @cuetsy(targetType="interface")
LineConfig: {
lineColor?: string
lineWidth?: number
lineInterpolation?: LineInterpolation
lineStyle?: LineStyle
spanNulls?: bool | number
} @cuetsy(targetType="interface")
BarConfig: {
barAlignment?: BarAlignment
barWidthFactor?: number
barMaxWidth?: number
} @cuetsy(targetType="interface")
FillConfig: {
fillColor?: string
fillOpacity?: number
fillBelowTo?: string
} @cuetsy(targetType="interface")
PointsConfig: {
showPoints?: PointVisibility
pointSize?: number
pointColor?: string
pointSymbol?: string
} @cuetsy(targetType="interface")
ScaleDistributionConfig: {
type: ScaleDistribution
log?: number
} @cuetsy(targetType="interface")
AxisConfig: {
axisPlacement?: AxisPlacement
axisLabel?: string
axisWidth?: number
axisSoftMin?: number
axisSoftMax?: number
scaleDistribution?: ScaleDistributionConfig
} @cuetsy(targetType="interface")
HideSeriesConfig: {
tooltip: bool
legend: bool
viz: bool
} @cuetsy(targetType="interface")
StackingConfig: {
mode?: StackingMode
group?: string
} @cuetsy(targetType="interface")
StackableFieldConfig: {
stacking?: StackingConfig
} @cuetsy(targetType="interface")
HideableFieldConfig: {
hideFrom?: HideSeriesConfig
} @cuetsy(targetType="interface")
GraphTresholdsStyleMode: "off" | "line" | "area" | "line+area" | "series" @cuetsy(targetType="enum",memberNames="Off|Line|Area|LineAndArea|Series")
GraphThresholdsStyleConfig: {
mode: GraphTresholdsStyleMode
} @cuetsy(targetType="interface")
LegendPlacement: "bottom" | "right" @cuetsy(targetType="type")
LegendDisplayMode: "list" | "table" | "hidden" @cuetsy(targetType="enum")
TableFieldOptions: {
width?: number
align: FieldTextAlignment | *"auto"
displayMode: TableCellDisplayMode | *"auto"
hidden?: bool
} @cuetsy(targetType="interface")
GraphFieldConfig: {
LineConfig
FillConfig
PointsConfig
AxisConfig
BarConfig
StackableFieldConfig
HideableFieldConfig
drawStyle?: DrawStyle
gradientMode?: GraphGradientMode
thresholdsStyle?: GraphThresholdsStyleConfig
} @cuetsy(targetType="interface")
VizLegendOptions: {
displayMode: LegendDisplayMode
placement: LegendPlacement
asTable: bool | *false
isVisible: bool | *false
calcs: [...string]
} @cuetsy(targetType="interface")
VizTooltipOptions: {
mode: TooltipDisplayMode
} @cuetsy(targetType="interface")
// TODO copy back to appropriate place
SingleStatBaseOptions: {
OptionsWithTextFormatting
reduceOptions: ReduceDataOptions
orientation: VizOrientation
} @cuetsy(targetType="interface")
// TODO copy back to appropriate place
ReduceDataOptions: {
// If true show each row value
values?: bool
// if showing all values limit
limit?: number
// When !values, pick one value for the whole field
calcs: [...string]
// Which fields to show. By default this is only numeric fields
fields?: string
} @cuetsy(targetType="interface")
// TODO copy back to appropriate place
VizOrientation: "auto" | "vertical" | "horizontal" @cuetsy(targetType="enum")
// TODO copy back to appropriate place
OptionsWithTooltip: {
// FIXME this field is non-optional in the corresponding TS type
tooltip?: VizTooltipOptions
} @cuetsy(targetType="interface")
// TODO copy back to appropriate place
OptionsWithLegend: {
// FIXME this field is non-optional in the corresponding TS type
legend?: VizLegendOptions
} @cuetsy(targetType="interface")
// TODO copy back to appropriate place
OptionsWithTextFormatting: {
text?: VizTextDisplayOptions
} @cuetsy(targetType="interface")
// TODO copy back to appropriate place
VizTextDisplayOptions: {
// Explicit title text size
titleSize?: number
// Explicit value text size
valueSize?: number
} @cuetsy(targetType="interface")
// TODO copy back to appropriate place
BigValueColorMode: "value" | "background" | "none" @cuetsy(targetType="enum")
// TODO copy back to appropriate place
BigValueGraphMode: "none" | "line" | "area" @cuetsy(targetType="enum")
// TODO copy back to appropriate place
BigValueJustifyMode: "auto" | "center" @cuetsy(targetType="enum")
// TODO copy back to appropriate place
// TODO does cuetsy handle underscores the expected way?
BigValueTextMode: "auto" | "value" | "value_and_name" | "name" | "none" @cuetsy(targetType="enum")
// TODO copy back to appropriate place
BarGaugeDisplayMode: "basic" | "lcd" | "gradient" @cuetsy(targetType="enum")

View File

@ -5,15 +5,11 @@ import (
"io/fs"
)
// CoreSchema embeds all CUE files within the cue/ subdirectory.
// CoreSchema embeds all core CUE files, which live in packages/grafana-schema/src
//
// TODO good rule about where to search
//
//go:embed cue/*/*.cue
//go:embed cue.mod cue packages/grafana-schema/src/schema/*.cue packages/grafana-schema/src/scuemata/*/*.cue
var CoreSchema embed.FS
// TODO good rule about where to search
//
//go:embed public/app/plugins/*/*/*.cue public/app/plugins/*/*/plugin.json
var base embed.FS

View File

@ -1,213 +0,0 @@
package grafanaschema
import "github.com/grafana/grafana/cue/scuemata"
Family: scuemata.#Family & {
lineages: [
[
{ // 0.0
// Unique numeric identifier for the dashboard.
// TODO must isolate or remove identifiers local to a Grafana instance...?
id?: number
// Unique dashboard identifier that can be generated by anyone. string (8-40)
uid: string
// Title of dashboard.
title?: string
// Description of dashboard.
description?: string
gnetId?: string
// Tags associated with dashboard.
tags?: [...string]
// Theme of dashboard.
style: *"light" | "dark"
// Timezone of dashboard,
timezone?: *"browser" | "utc"
// Whether a dashboard is editable or not.
editable: bool | *true
// 0 for no shared crosshair or tooltip (default).
// 1 for shared crosshair.
// 2 for shared crosshair AND shared tooltip.
graphTooltip: >=0 & <=2 | *0
// Time range for dashboard, e.g. last 6 hours, last 7 days, etc
time?: {
from: string | *"now-6h"
to: string | *"now"
}
// Timepicker metadata.
timepicker?: {
// Whether timepicker is collapsed or not.
collapse: bool | *false
// Whether timepicker is enabled or not.
enable: bool | *true
// Whether timepicker is visible or not.
hidden: bool | *false
// Selectable intervals for auto-refresh.
refresh_intervals: [...string] | *["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
}
// Templating.
templating?: list: [...{...}]
// Annotations.
annotations?: list: [...{
builtIn: number | *0
// Datasource to use for annotation.
datasource: string
// Whether annotation is enabled.
enable?: bool | *true
// Whether to hide annotation.
hide?: bool | *false
// Annotation icon color.
iconColor?: string
// Name of annotation.
name?: string
type: string | *"dashboard"
// Query for annotation data.
rawQuery?: string
showIn: number | *0
}]
// Auto-refresh interval.
refresh?: string
// Version of the JSON schema, incremented each time a Grafana update brings
// changes to said schema.
schemaVersion: number | *25
// Version of the dashboard, incremented each time the dashboard is updated.
version?: number
panels?: [...#Panel]
// 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,
// synthetic Family to represent them in Go, for ease of generating
// e.g. JSON Schema.
#Panel: {
// The panel plugin type id.
type: !=""
// 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
// possible to figure out which schema version matched on a successful
// unification.
// _pv: { maj: int, min: int }
// The major and minor versions of the panel plugin for this schema.
// TODO 2-tuple list instead of struct?
panelSchema: { maj: number, min: number }
// Panel title.
title?: string
// Description.
description?: string
// Whether to display the panel without a background.
transparent: bool | *false
// Name of default datasource.
datasource?: string
// Grid position.
gridPos?: {
// Panel
h: number & >0 | *9
// Panel
w: number & >0 & <=24 | *12
// Panel x
x: number & >=0 & <24 | *0
// Panel y
y: number & >=0 | *0
// true if fixed
static?: bool
}
// Panel links.
// links?: [..._panelLink]
// 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?: [...{}]
// The values depend on panel type
options: {...}
fieldConfig: {
defaults: {
// The display value for this field. This supports template variables blank is auto
displayName?: string
// 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
// Human readable field metadata
description?: string
// 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
// True if data source can write a value to the path. Auth/authz are supported separately
writeable?: bool
// True if data source field supports ad-hoc filters
filterable?: bool
// Numeric Options
unit?: string
// Significant digits (for display)
decimals?: number
min?: number
max?: number
// // Convert input values into a display string
// mappings?: ValueMapping[];
// // Map numeric values to states
// thresholds?: ThresholdsConfig;
// // Map values to a display color
// color?: FieldColor;
// // Used when reducing field values
// nullValueMode?: NullValueMode;
// // The behavior when clicking on a result
// links?: DataLink[];
// Alternative to empty string
noValue?: string
// Can always exist. Valid fields within this are
// defined by the panel plugin - that's the
// PanelFieldConfig that comes from the plugin.
custom?: {...}
}
overrides: [...{
matcher: {
id: string | *""
options?: _
}
properties: [...{
id: string | *""
value?: _
}]
}]
}
}
}
]
]
}
#Latest: {
#Dashboard: dashboardFamily.latest
#Panel: dashboardFamily.latest._Panel
}

View File

@ -1,14 +1,16 @@
AxisPlacement: "auto" | "top" | "right" | "bottom" | "left" | "hidden" @cuetsy(targetType="enum")
PointVisibility: "auto" | "never" | "always" @cuetsy(targetType="enum")
DrawStyle: "line" | "bars" | "points" @cuetsy(targetType="enum")
LineInterpolation: "linear" | "smooth" | "stepBefore" | "stepAfter" @cuetsy(targetType="enum")
ScaleDistribution: "linear" | "log" @cuetsy(targetType="enum")
GraphGradientMode: "none" | "opacity" | "hue" | "scheme" @cuetsy(targetType="enum")
StackingMode: "none" | "normal" | "percent" @cuetsy(targetType="enum")
BarValueVisibility: "auto" | "never" | "always" @cuetsy(targetType="enum")
BarAlignment: -1 | 0 | 1 @cuetsy(targetType="enum",memberNames="Before|Center|After")
ScaleOrientation: 0 | 1 @cuetsy(targetType="enum",memberNames="Horizontal|Vertical")
ScaleDirection: 1 | 1 | -1 | -1 @cuetsy(targetType="enum",memberNames="Up|Right|Down|Left")
package schema
AxisPlacement: "auto" | "top" | "right" | "bottom" | "left" | "hidden" @cuetsy(targetType="enum")
PointVisibility: "auto" | "never" | "always" @cuetsy(targetType="enum")
DrawStyle: "line" | "bars" | "points" @cuetsy(targetType="enum")
LineInterpolation: "linear" | "smooth" | "stepBefore" | "stepAfter" @cuetsy(targetType="enum")
ScaleDistribution: "linear" | "log" @cuetsy(targetType="enum")
GraphGradientMode: "none" | "opacity" | "hue" | "scheme" @cuetsy(targetType="enum")
StackingMode: "none" | "normal" | "percent" @cuetsy(targetType="enum")
BarValueVisibility: "auto" | "never" | "always" @cuetsy(targetType="enum")
BarAlignment: -1 | 0 | 1 @cuetsy(targetType="enum",memberNames="Before|Center|After")
ScaleOrientation: 0 | 1 @cuetsy(targetType="enum",memberNames="Horizontal|Vertical")
ScaleDirection: 1 | 1 | -1 | -1 @cuetsy(targetType="enum",memberNames="Up|Right|Down|Left")
LineStyle: {
fill?: "solid" | "dash" | "dot" | "square"
dash?: [...number]
@ -21,9 +23,9 @@ LineConfig: {
spanNulls?: bool | number
} @cuetsy(targetType="interface")
BarConfig: {
barAlignment?: BarAlignment
barAlignment?: BarAlignment
barWidthFactor?: number
barMaxWidth?: number
barMaxWidth?: number
} @cuetsy(targetType="interface")
FillConfig: {
fillColor?: string
@ -51,31 +53,31 @@ AxisConfig: {
HideSeriesConfig: {
tooltip: bool
legend: bool
viz: bool
viz: bool
} @cuetsy(targetType="interface")
StackingConfig: {
mode?: StackingMode
group?: string
mode?: StackingMode
group?: string
} @cuetsy(targetType="interface")
StackableFieldConfig: {
stacking?: StackingConfig
stacking?: StackingConfig
} @cuetsy(targetType="interface")
HideableFieldConfig: {
hideFrom?: HideSeriesConfig
hideFrom?: HideSeriesConfig
} @cuetsy(targetType="interface")
GraphTresholdsStyleMode: "off" | "line" | "area" | "line+area" | "series" @cuetsy(targetType="enum",memberNames="Off|Line|Area|LineAndArea|Series")
GraphThresholdsStyleConfig: {
mode: GraphTresholdsStyleMode
mode: GraphTresholdsStyleMode
} @cuetsy(targetType="interface")
GraphFieldConfig: {
LineConfig
FillConfig
PointsConfig
AxisConfig
BarConfig
StackableFieldConfig
HideableFieldConfig
drawStyle?: DrawStyle
gradientMode?: GraphGradientMode
thresholdsStyle?: GraphThresholdsStyleConfig
} @cuetsy(targetType="interface")
LineConfig
FillConfig
PointsConfig
AxisConfig
BarConfig
StackableFieldConfig
HideableFieldConfig
drawStyle?: DrawStyle
gradientMode?: GraphGradientMode
thresholdsStyle?: GraphThresholdsStyleConfig
} @cuetsy(targetType="interface")

View File

@ -1,13 +1,13 @@
package schema
LegendPlacement: "bottom" | "right" @cuetsy(targetType="type")
LegendPlacement: "bottom" | "right" @cuetsy(targetType="type")
LegendDisplayMode: "list" | "table" | "hidden" @cuetsy(targetType="enum")
VizLegendOptions: {
displayMode: LegendDisplayMode
placement: LegendPlacement
asTable: bool | *false
isVisible: bool | *false
asTable: bool | *false
isVisible: bool | *false
calcs: [...string]
} @cuetsy(targetType="interface")

View File

@ -0,0 +1,53 @@
package schema
// Use this file as a big TODO list - if it's still in here, it's a TODO to
// separate it out into a discrete file.
TableSortByFieldState: {
displayName: string
desc?: bool
} @cuetsy(targetType="interface")
SingleStatBaseOptions: {
OptionsWithTextFormatting
reduceOptions: ReduceDataOptions
orientation: VizOrientation
} @cuetsy(targetType="interface")
// TODO copy back to appropriate place
ReduceDataOptions: {
// If true show each row value
values?: bool
// if showing all values limit
limit?: number
// When !values, pick one value for the whole field
calcs: [...string]
// Which fields to show. By default this is only numeric fields
fields?: string
} @cuetsy(targetType="interface")
// TODO copy back to appropriate place
VizOrientation: "auto" | "vertical" | "horizontal" @cuetsy(targetType="enum")
// TODO copy back to appropriate place
OptionsWithTooltip: {
// FIXME this field is non-optional in the corresponding TS type
tooltip?: VizTooltipOptions
} @cuetsy(targetType="interface")
// TODO copy back to appropriate place
OptionsWithLegend: {
// FIXME this field is non-optional in the corresponding TS type
legend?: VizLegendOptions
} @cuetsy(targetType="interface")
// TODO copy back to appropriate place
OptionsWithTextFormatting: {
text?: VizTextDisplayOptions
} @cuetsy(targetType="interface")
// TODO copy back to appropriate place
BigValueColorMode: "value" | "background" | "none" @cuetsy(targetType="enum")
// TODO copy back to appropriate place
BigValueGraphMode: "none" | "line" | "area" @cuetsy(targetType="enum")
// TODO copy back to appropriate place
BigValueJustifyMode: "auto" | "center" @cuetsy(targetType="enum")
// TODO copy back to appropriate place
// TODO does cuetsy handle underscores the expected way?
BigValueTextMode: "auto" | "value" | "value_and_name" | "name" | "none" @cuetsy(targetType="enum")
// TODO copy back to appropriate place
BarGaugeDisplayMode: "basic" | "lcd" | "gradient" @cuetsy(targetType="enum")

View File

@ -1,21 +1,23 @@
package schema
// TODO -- should not be table specific!
FieldTextAlignment: "auto" | "left" | "right" | "center" @cuetsy(targetType="type")
// FIXME can't write enums as structs, must use disjunctions
TableCellDisplayMode: {
Auto: "auto",
ColorText: "color-text",
ColorBackground: "color-background",
GradientGauge: "gradient-gauge",
LcdGauge: "lcd-gauge",
JSONView: "json-view",
BasicGauge: "basic",
Image: "image",
Auto: "auto"
ColorText: "color-text"
ColorBackground: "color-background"
GradientGauge: "gradient-gauge"
LcdGauge: "lcd-gauge"
JSONView: "json-view"
BasicGauge: "basic"
Image: "image"
} @cuetsy(targetType="enum")
TableFieldOptions: {
width?: number
align: FieldTextAlignment | *"auto"
displayMode: TableCellDisplayMode | *"auto"
hidden?: bool // ?? default is missing or false ??
width?: number
align: FieldTextAlignment | *"auto"
displayMode: TableCellDisplayMode | *"auto"
hidden?: bool // ?? default is missing or false ??
} @cuetsy(targetType="interface")

View File

@ -1,3 +1,4 @@
package schema
VizTextDisplayOptions: {
// Explicit title text size

View File

@ -1,5 +1,7 @@
TooltipDisplayMode: "single" | "multi" | "none" @cuetsy(targetType="enum")
package schema
TooltipDisplayMode: "single" | "multi" | "none" @cuetsy(targetType="enum")
VizTooltipOptions: {
mode: TooltipDisplayMode
} @cuetsy(targetType="interface")
mode: TooltipDisplayMode
} @cuetsy(targetType="interface")

View File

@ -1,4 +1,4 @@
package grafanaschema
package dashboard
import "github.com/grafana/grafana/cue/scuemata"

View File

@ -28,11 +28,11 @@ func TestValidateScuemataBasics(t *testing.T) {
})
t.Run("Testing scuemata validity with invalid cue schemas - family missing", func(t *testing.T) {
genCue, err := os.ReadFile("testdata/missing_family_gen.cue")
genCue, err := os.ReadFile("testdata/missing_family.cue")
require.NoError(t, err)
filesystem := fstest.MapFS{
"cue/data/gen.cue": &fstest.MapFile{Data: genCue},
"packages/grafana-schema/src/scuemata/dashboard/dashboard.cue": &fstest.MapFile{Data: genCue},
}
mergedFS := mergefs.Merge(filesystem, defaultBaseLoadPaths.BaseCueFS)
@ -46,11 +46,11 @@ func TestValidateScuemataBasics(t *testing.T) {
})
t.Run("Testing scuemata validity with invalid cue schemas - panel missing ", func(t *testing.T) {
genCue, err := os.ReadFile("testdata/missing_panel_gen.cue")
genCue, err := os.ReadFile("testdata/missing_panel.cue")
require.NoError(t, err)
filesystem := fstest.MapFS{
"cue/data/gen.cue": &fstest.MapFile{Data: genCue},
"packages/grafana-schema/src/scuemata/dashboard/dashboard.cue": &fstest.MapFile{Data: genCue},
}
mergedFS := mergefs.Merge(filesystem, defaultBaseLoadPaths.BaseCueFS)

View File

@ -12,6 +12,8 @@ import (
var panelSubpath = cue.MakePath(cue.Def("#Panel"))
var dashboardDir = filepath.Join("packages", "grafana-schema", "src", "scuemata", "dashboard")
func defaultOverlay(p BaseLoadPaths) (map[string]load.Source, error) {
overlay := make(map[string]load.Source)
@ -38,8 +40,14 @@ func BaseDashboardFamily(p BaseLoadPaths) (schema.VersionedCueSchema, error) {
if err != nil {
return nil, err
}
cfg := &load.Config{Overlay: overlay}
inst, err := rt.Build(load.Instances([]string{filepath.Join(prefix, "cue", "data", "gen.cue")}, cfg)[0])
cfg := &load.Config{
Overlay: overlay,
ModuleRoot: prefix,
Module: "github.com/grafana/grafana",
Dir: filepath.Join(prefix, dashboardDir),
}
inst, err := rt.Build(load.Instances(nil, cfg)[0])
if err != nil {
cueError := schema.WrapCUEError(err)
if err != nil {

View File

@ -156,26 +156,24 @@ func TestPanelValidity(t *testing.T) {
}
func TestCueErrorWrapper(t *testing.T) {
t.Run("Testing cue error wrapper", func(t *testing.T) {
a := fstest.MapFS{
"cue/data/gen.cue": &fstest.MapFile{Data: []byte("{;;;;;;;;}")},
}
a := fstest.MapFS{
filepath.Join(dashboardDir, "dashboard.cue"): &fstest.MapFile{Data: []byte("package dashboard\n{;;;;;;;;}")},
}
filesystem := mergefs.Merge(a, GetDefaultLoadPaths().BaseCueFS)
filesystem := mergefs.Merge(a, GetDefaultLoadPaths().BaseCueFS)
var baseLoadPaths = BaseLoadPaths{
BaseCueFS: filesystem,
DistPluginCueFS: GetDefaultLoadPaths().DistPluginCueFS,
}
var baseLoadPaths = BaseLoadPaths{
BaseCueFS: filesystem,
DistPluginCueFS: GetDefaultLoadPaths().DistPluginCueFS,
}
_, err := BaseDashboardFamily(baseLoadPaths)
require.Error(t, err)
require.Contains(t, err.Error(), "in file")
require.Contains(t, err.Error(), "line: ")
_, err := BaseDashboardFamily(baseLoadPaths)
require.Error(t, err)
require.Contains(t, err.Error(), "in file")
require.Contains(t, err.Error(), "line: ")
_, err = DistDashboardFamily(baseLoadPaths)
require.Error(t, err)
require.Contains(t, err.Error(), "in file")
require.Contains(t, err.Error(), "line: ")
})
_, err = DistDashboardFamily(baseLoadPaths)
require.Error(t, err)
require.Contains(t, err.Error(), "in file")
require.Contains(t, err.Error(), "line: ")
}

View File

@ -15,7 +15,7 @@
package grafanaschema
import (
ui "github.com/grafana/grafana/cue/ui:grafanaschema"
ui "github.com/grafana/grafana/packages/grafana-schema/src/schema"
)
Family: {

View File

@ -14,7 +14,7 @@
package grafanaschema
import ui "github.com/grafana/grafana/cue/ui:grafanaschema"
import ui "github.com/grafana/grafana/packages/grafana-schema/src/schema"
Family: {
lineages: [

View File

@ -14,7 +14,7 @@
package grafanaschema
import ui "github.com/grafana/grafana/cue/ui:grafanaschema"
import ui "github.com/grafana/grafana/packages/grafana-schema/src/schema"
Family: {
lineages: [

View File

@ -14,7 +14,7 @@
package grafanaschema
import ui "github.com/grafana/grafana/cue/ui:grafanaschema"
import ui "github.com/grafana/grafana/packages/grafana-schema/src/schema"
Family: {
lineages: [

View File

@ -14,7 +14,7 @@
package grafanaschema
import ui "github.com/grafana/grafana/cue/ui:grafanaschema"
import ui "github.com/grafana/grafana/packages/grafana-schema/src/schema"
Family: {
lineages: [

View File

@ -15,7 +15,7 @@
package grafanaschema
import (
ui "github.com/grafana/grafana/cue/ui:grafanaschema"
ui "github.com/grafana/grafana/packages/grafana-schema/src/schema"
)
Family: {

View File

@ -15,7 +15,7 @@
package grafanaschema
import (
ui "github.com/grafana/grafana/cue/ui:grafanaschema"
ui "github.com/grafana/grafana/packages/grafana-schema/src/schema"
)
Family: {

View File

@ -15,7 +15,7 @@
package grafanaschema
import (
ui "github.com/grafana/grafana/cue/ui:grafanaschema"
ui "github.com/grafana/grafana/packages/grafana-schema/src/schema"
)
Family: {

View File

@ -15,7 +15,7 @@
package grafanaschema
import (
ui "github.com/grafana/grafana/cue/ui:grafanaschema"
ui "github.com/grafana/grafana/packages/grafana-schema/src/schema"
)
Family: {

View File

@ -1,93 +0,0 @@
#!/usr/bin/env bash
set -eo pipefail
# MUST BE RUN FROM GRAFANA ROOT DIR
test -d cue
# Must have latest cue and cuetsy
if ! command -v cue &> /dev/null; then
echo "must install cue on PATH"
exit 1
fi
if ! command -v cuetsy &> /dev/null; then
echo "must install cuetsy on PATH"
exit 1
fi
# TODO Everything here needs to be moved into custom CUE logic in a Go program.
# It _might_ be possible to do what we want with some CUE tools magic
# (https://pkg.go.dev/cuelang.org/go@v0.3.0-beta.5/pkg/tool), but unless that
# turns out to be pretty straightforward, it's probably better to encode our
# filesystem semantics there.
# Enumerate and move all CUE files under packages/grafana-{data,ui} into
# respective cue subdir. These subdirs are where we place assembled
# definitions, where Go loads from, and where other CUE - including CUE defined
# in plugins - import from.
mkdir -p cue/ui cue/data
rm -f {cue/ui/gen.cue,cue/data/gen.cue}
# TODO decide if multiple or single files seems like better ergonomics
# shellcheck disable=SC2046
cue def -s $(find packages/grafana-ui -type f -name "*.cue") > cue/ui/gen.cue
# shellcheck disable=SC2046
cue def -s $(find packages/grafana-data -type f -name "*.cue") > cue/data/gen.cue
# Horrible hack to remove import statements.
#
# HACK-IMPOSED CONSTRAINT: Only works for single-line imports, so we can ONLY use
# single-line imports in CUE files until this is improved! Expressly only here
# as a hack because we can't make this better with vanilla cue.
#
# HACK-IMPOSED CONSTRAINT: Can't import between @grafana/ui and @grafana/data,
# because those imports will also be removed
#
# TODO move a more careful import-elimination check into a Go tool
#
# It's important to understand why this is necessary, though. We are expecting
# that these core components may depend on each other - e.g., how
# VizTooltipOptions composes in TooltipDisplayMode. We have to preserve those
# literal identifiers in our assembled CUE, so that when a panel plugin's
# models.cue imports and references something like VizTooltipOptions in CUE,
# it's still the same identifier as appeared in the original core models.cue
# files, AND therefore is exactly the identifier that appears in
# cuetsy-generated @grafana/{ui,data} packages. That is, as long as we preserve
# the relation between the identifier "VizTooltipOptions" as a top-level
# importable thing at all stages on the CUE side, then everything on the
# TypeScript side will line up.
sed -i -e 's/^import.*//g' {cue/ui/gen.cue,cue/data/gen.cue}
# Remove all qualified identifiers
# (https://cuelang.org/docs/references/spec/#qualified-identifiers) from the
# generated CUE files.
#
# Even worse hack than the above, but part and parcel with having imports. By
# assembling the CUE inputs together into a single dir in a single package (and
# even in a single file, though single dir is sufficient), we've obviated the
# need for imports and qualified identifiers; CUE's loader logic concats
# everything into a single instance.
#
# HACK-IMPOSED CONSTRAINT: No selectors (foo.bar,
# https://cuelang.org/docs/references/spec/#qualified-identifiers), at all.
# Thus, no nested identifiers. This is a horrible sledgehammer. It makes it
# impossible to correctly consume a CUE file that references a nested
# identifier (foo.bar), because this stupid logic can't disambiguate between
# those and referencing a label from an import.
#
# HACK-IMPOSED CONSTRAINT: We can't experiment with the sort of complex
# structures necessary for revisioning as long as we're doing this, as they're
# necessarily going to involve some nesting.
#
# TODO move into grafana-cli and do a more careful check that we're only
# eliminating qualified identifiers from imports we're also eliminating
sed -i -e "s/[A-Za-z]*\.\([A-Za-z]*\)/\1/g" {cue/ui/gen.cue,cue/data/gen.cue}
# uuuugghhhh OSX sed
rm -f {cue/ui/gen.cue-e,cue/data/gen.cue-e}
# Check that our output is still valid CUE.
cue eval -E {cue/ui/gen.cue,cue/data/gen.cue} > /dev/null
# Run cuetsy over all core .cue files.
find packages -type f -name '*.cue' -exec cuetsy {} \;
find public/app/plugins -type f -name '*.cue' -exec cuetsy {} \;