Skip to content

Instantly share code, notes, and snippets.

@sdboyer
Last active May 18, 2022 16:35
Show Gist options
  • Save sdboyer/3a09adb7f5fd881b9fca2147bf853412 to your computer and use it in GitHub Desktop.
Save sdboyer/3a09adb7f5fd881b9fca2147bf853412 to your computer and use it in GitHub Desktop.
Translate the dashboard lineage as OpenAPI
package main
import (
"fmt"
"cuelang.org/go/cue/cuecontext"
"cuelang.org/go/pkg/encoding/yaml"
"github.com/grafana/grafana/pkg/coremodel/dashboard"
"github.com/grafana/thema"
"github.com/grafana/thema/encoding/openapi"
)
func main() {
lib := thema.NewLibrary(cuecontext.New())
lin, _ := dashboard.Lineage(lib)
// Grab the 0.0 version. Or whichever one you want
sch := thema.SchemaP(lin, thema.SV(0, 0))
f, _ := openapi.GenerateSchema(sch, nil)
ystr, _ := yaml.Marshal(lib.Context().BuildFile(f))
fmt.Println(ystr)
}
openapi: 3.0.0
info:
title: dashboard
version: "0.0"
paths: {}
components:
schemas:
dashboard:
type: object
required:
- style
- editable
- graphTooltip
- schemaVersion
properties:
id:
description: |-
Unique numeric identifier for the dashboard.
TODO must isolate or remove identifiers local to a Grafana instance...?
type: integer
format: int64
uid:
description: Unique dashboard identifier that can be generated by anyone. string (8-40)
type: string
title:
description: Title of dashboard.
type: string
description:
description: Description of dashboard.
type: string
gnetId:
type: string
tags:
description: Tags associated with dashboard.
type: array
items:
type: string
style:
description: Theme of dashboard.
type: string
enum:
- dark
- light
default: dark
timezone:
description: Timezone of dashboard,
type: string
enum:
- browser
- utc
- ""
default: browser
editable:
description: Whether a dashboard is editable or not.
type: boolean
default: true
graphTooltip:
type: integer
enum:
- 0
- 1
- 2
default: 0
time:
description: Time range for dashboard, e.g. last 6 hours, last 7 days, etc
type: object
required:
- from
- to
properties:
from:
type: string
default: now-6h
to:
type: string
default: now
timepicker:
description: |-
TODO docs
TODO this appears to be spread all over in the frontend. Concepts will likely need tidying in tandem with schema changes
type: object
required:
- collapse
- enable
- hidden
- refresh_intervals
properties:
collapse:
description: Whether timepicker is collapsed or not.
type: boolean
default: false
enable:
description: Whether timepicker is enabled or not.
type: boolean
default: true
hidden:
description: Whether timepicker is visible or not.
type: boolean
default: false
refresh_intervals:
description: Selectable intervals for auto-refresh.
type: array
items:
type: string
default:
- 5s
- 10s
- 30s
- 1m
- 5m
- 15m
- 30m
- 1h
- 2h
- 1d
fiscalYearStartMonth:
description: TODO docs
type: integer
minimum: 0
exclusiveMinimum: true
maximum: 13
exclusiveMaximum: true
liveNow:
description: TODO docs
type: boolean
weekStart:
description: TODO docs
type: string
refresh:
description: TODO docs
oneOf:
- enum:
- false
- type: string
schemaVersion:
description: |-
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
type: integer
minimum: 0
maximum: 65535
default: 36
version:
description: Version of the dashboard, incremented each time the dashboard is updated.
type: integer
minimum: 0
maximum: 4294967295
panels:
type: array
items:
type: object
oneOf:
- $ref: '#/components/schemas/dashboard.Panel'
- $ref: '#/components/schemas/dashboard.GraphPanel'
- $ref: '#/components/schemas/dashboard.HeatmapPanel'
- $ref: '#/components/schemas/dashboard.RowPanel'
templating:
type: object
required:
- list
properties:
list:
type: array
items:
$ref: '#/components/schemas/dashboard.VariableModel'
annotations:
type: object
required:
- list
properties:
list:
type: array
items:
$ref: '#/components/schemas/dashboard.AnnotationQuery'
links:
description: TODO docs
type: array
items:
$ref: '#/components/schemas/dashboard.DashboardLink'
dashboard.AnnotationQuery:
description: |-
TODO docs
FROM: AnnotationQuery in grafana-data/src/types/annotations.ts
type: object
required:
- datasource
- enable
- builtIn
- type
- showIn
properties:
datasource:
description: Datasource to use for annotation.
type: object
properties:
type:
type: string
uid:
type: string
enable:
description: Whether annotation is enabled.
type: boolean
default: true
name:
description: Name of annotation.
type: string
builtIn:
type: integer
minimum: 0
maximum: 255
default: 0
hide:
description: Whether to hide annotation.
type: boolean
default: false
iconColor:
description: Annotation icon color.
type: string
type:
type: string
default: dashboard
rawQuery:
description: Query for annotation data.
type: string
showIn:
type: integer
minimum: 0
maximum: 255
default: 0
target:
$ref: '#/components/schemas/dashboard.Target'
dashboard.DashboardCursorSync:
description: |-
0 for no shared crosshair or tooltip (default).
1 for shared crosshair.
2 for shared crosshair AND shared tooltip.
type: integer
enum:
- 0
- 1
- 2
default: 0
dashboard.DashboardLink:
description: |-
FROM public/app/features/dashboard/state/DashboardModels.ts - ish
TODO docs
type: object
required:
- title
- type
- tags
- asDropdown
- targetBlank
- includeVars
- keepTime
properties:
title:
type: string
type:
type: string
enum:
- link
- dashboards
icon:
type: string
tooltip:
type: string
url:
type: string
tags:
type: array
items:
type: string
asDropdown:
type: boolean
default: false
targetBlank:
type: boolean
default: false
includeVars:
type: boolean
default: false
keepTime:
type: boolean
default: false
dashboard.DashboardLinkType:
description: TODO docs
type: string
enum:
- link
- dashboards
dashboard.FieldColor:
description: TODO docs
type: object
required:
- mode
properties:
mode:
description: The main color scheme mode
type: string
oneOf:
- enum:
- thresholds
- palette-classic
- palette-saturated
- continuous-GrYlRd
- fixed
- {}
fixedColor:
description: Stores the fixed color value if mode is fixed
type: string
seriesBy:
$ref: '#/components/schemas/dashboard.FieldColorSeriesByMode'
dashboard.FieldColorModeId:
description: TODO docs
type: string
enum:
- thresholds
- palette-classic
- palette-saturated
- continuous-GrYlRd
- fixed
dashboard.FieldColorSeriesByMode:
description: TODO docs
type: string
enum:
- min
- max
- last
dashboard.GraphPanel:
type: object
required:
- type
properties:
type:
description: Support for legacy graph and heatmap panels.
type: string
enum:
- graph
dashboard.HeatmapPanel:
type: object
required:
- type
properties:
type:
type: string
enum:
- heatmap
dashboard.Panel:
description: |-
Dashboard panels. Panels are canonically defined inline
because they share a version timeline with the dashboard
schema; they do not evolve independently.
type: object
required:
- type
- transparent
- repeatDirection
- transformations
- options
- fieldConfig
properties:
type:
description: The panel plugin type id. May not be empty.
type: string
minLength: 1
id:
description: TODO docs
type: integer
minimum: 0
maximum: 4294967295
pluginVersion:
description: FIXME this almost certainly has to be changed in favor of scuemata versions
type: string
tags:
description: TODO docs
type: array
items:
type: string
targets:
description: TODO docs
type: array
items:
$ref: '#/components/schemas/dashboard.Target'
title:
description: Panel title.
type: string
description:
description: Description.
type: string
transparent:
description: Whether to display the panel without a background.
type: boolean
default: false
datasource:
description: The datasource used in all targets.
type: object
properties:
type:
type: string
uid:
type: string
gridPos:
description: Grid position.
type: object
required:
- h
- w
- x
- "y"
properties:
h:
description: Panel
type: integer
minimum: 0
exclusiveMinimum: true
maximum: 4294967295
default: 9
w:
description: Panel
type: integer
minimum: 0
exclusiveMinimum: true
maximum: 24
default: 12
x:
description: Panel x
type: integer
minimum: 0
maximum: 24
exclusiveMaximum: true
default: 0
"y":
description: Panel y
type: integer
minimum: 0
maximum: 4294967295
default: 0
static:
description: true if fixed
type: boolean
links:
description: |-
Panel links.
TODO fill this out - seems there are a couple variants?
type: array
items:
$ref: '#/components/schemas/dashboard.DashboardLink'
repeat:
description: Name of template variable to repeat for.
type: string
repeatDirection:
description: |-
Direction to repeat in if 'repeat' is set.
"h" for horizontal, "v" for vertical.
type: string
enum:
- h
- v
default: h
maxDataPoints:
description: TODO docs
type: number
thresholds:
description: TODO docs
type: array
items: {}
timeRegions:
description: TODO docs
type: array
items: {}
transformations:
type: array
items:
type: object
required:
- id
- options
properties:
id:
type: string
options:
type: object
interval:
description: |-
TODO docs
TODO tighter constraint
type: string
timeFrom:
description: |-
TODO docs
TODO tighter constraint
type: string
timeShift:
description: |-
TODO docs
TODO tighter constraint
type: string
options:
description: |-
options is specified by the PanelOptions field in panel
plugin schemas.
type: object
fieldConfig:
type: object
required:
- defaults
- overrides
properties:
defaults:
type: object
properties:
displayName:
description: The display value for this field. This supports template variables blank is auto
type: string
displayNameFromDS:
description: |-
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.
type: string
description:
description: Human readable field metadata
type: string
path:
description: |-
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
type: string
writeable:
description: True if data source can write a value to the path. Auth/authz are supported separately
type: boolean
filterable:
description: True if data source field supports ad-hoc filters
type: boolean
unit:
description: Numeric Options
type: string
decimals:
description: Significant digits (for display)
type: number
min:
type: number
max:
type: number
mappings:
description: |-
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.
type: array
items:
type: object
thresholds:
$ref: '#/components/schemas/dashboard.ThresholdsConfig'
color:
$ref: '#/components/schemas/dashboard.FieldColor'
links:
description: // The behavior when clicking on a result
type: array
items: {}
noValue:
description: Alternative to empty string
type: string
custom:
description: |-
custom is specified by the PanelFieldConfig field
in panel plugin schemas.
type: object
overrides:
type: array
items:
type: object
required:
- matcher
- properties
properties:
matcher:
type: object
required:
- id
properties:
id:
type: string
default: ""
options: {}
properties:
type: array
items:
type: object
required:
- id
properties:
id:
type: string
default: ""
value: {}
dashboard.RowPanel:
description: Row panel
type: object
required:
- type
- collapsed
- id
- panels
properties:
type:
type: string
enum:
- row
collapsed:
type: boolean
default: false
title:
type: string
datasource:
description: Name of default datasource.
type: object
properties:
type:
type: string
uid:
type: string
gridPos:
type: object
required:
- h
- w
- x
- "y"
properties:
h:
description: Panel
type: integer
minimum: 0
exclusiveMinimum: true
maximum: 4294967295
default: 9
w:
description: Panel
type: integer
minimum: 0
exclusiveMinimum: true
maximum: 24
default: 12
x:
description: Panel x
type: integer
minimum: 0
maximum: 24
exclusiveMaximum: true
default: 0
"y":
description: Panel y
type: integer
minimum: 0
maximum: 4294967295
default: 0
static:
description: true if fixed
type: boolean
id:
type: integer
minimum: 0
maximum: 4294967295
panels:
type: array
items:
type: object
oneOf:
- required:
- type
- transparent
- repeatDirection
- transformations
- options
- fieldConfig
properties:
type:
description: The panel plugin type id. May not be empty.
type: string
minLength: 1
id:
description: TODO docs
type: integer
minimum: 0
maximum: 4294967295
pluginVersion:
description: FIXME this almost certainly has to be changed in favor of scuemata versions
type: string
tags:
description: TODO docs
type: array
items:
type: string
targets:
description: TODO docs
type: array
items:
$ref: '#/components/schemas/dashboard.Target'
title:
description: Panel title.
type: string
description:
description: Description.
type: string
transparent:
description: Whether to display the panel without a background.
type: boolean
default: false
datasource:
description: The datasource used in all targets.
type: object
properties:
type:
type: string
uid:
type: string
gridPos:
description: Grid position.
type: object
required:
- h
- w
- x
- "y"
properties:
h:
description: Panel
type: integer
minimum: 0
exclusiveMinimum: true
maximum: 4294967295
default: 9
w:
description: Panel
type: integer
minimum: 0
exclusiveMinimum: true
maximum: 24
default: 12
x:
description: Panel x
type: integer
minimum: 0
maximum: 24
exclusiveMaximum: true
default: 0
"y":
description: Panel y
type: integer
minimum: 0
maximum: 4294967295
default: 0
static:
description: true if fixed
type: boolean
links:
description: |-
Panel links.
TODO fill this out - seems there are a couple variants?
type: array
items:
$ref: '#/components/schemas/dashboard.DashboardLink'
repeat:
description: Name of template variable to repeat for.
type: string
repeatDirection:
description: |-
Direction to repeat in if 'repeat' is set.
"h" for horizontal, "v" for vertical.
type: string
enum:
- h
- v
default: h
maxDataPoints:
description: TODO docs
type: number
thresholds:
description: TODO docs
type: array
items: {}
timeRegions:
description: TODO docs
type: array
items: {}
transformations:
type: array
items:
type: object
required:
- id
- options
properties:
id:
type: string
options:
type: object
interval:
description: |-
TODO docs
TODO tighter constraint
type: string
timeFrom:
description: |-
TODO docs
TODO tighter constraint
type: string
timeShift:
description: |-
TODO docs
TODO tighter constraint
type: string
options:
description: |-
options is specified by the PanelOptions field in panel
plugin schemas.
type: object
fieldConfig:
type: object
required:
- defaults
- overrides
properties:
defaults:
type: object
properties:
displayName:
description: The display value for this field. This supports template variables blank is auto
type: string
displayNameFromDS:
description: |-
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.
type: string
description:
description: Human readable field metadata
type: string
path:
description: |-
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
type: string
writeable:
description: True if data source can write a value to the path. Auth/authz are supported separately
type: boolean
filterable:
description: True if data source field supports ad-hoc filters
type: boolean
unit:
description: Numeric Options
type: string
decimals:
description: Significant digits (for display)
type: number
min:
type: number
max:
type: number
mappings:
description: |-
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.
type: array
items:
type: object
thresholds:
$ref: '#/components/schemas/dashboard.ThresholdsConfig'
color:
$ref: '#/components/schemas/dashboard.FieldColor'
links:
description: // The behavior when clicking on a result
type: array
items: {}
noValue:
description: Alternative to empty string
type: string
custom:
description: |-
custom is specified by the PanelFieldConfig field
in panel plugin schemas.
type: object
overrides:
type: array
items:
type: object
required:
- matcher
- properties
properties:
matcher:
type: object
required:
- id
properties:
id:
type: string
default: ""
options: {}
properties:
type: array
items:
type: object
required:
- id
properties:
id:
type: string
default: ""
value: {}
- required:
- type
properties:
type:
type: string
enum:
- graph
- required:
- type
properties:
type:
type: string
enum:
- heatmap
repeat:
description: Name of template variable to repeat for.
type: string
dashboard.Target:
description: |-
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.
type: object
dashboard.Threshold:
description: TODO docs
type: object
required:
- color
properties:
value:
description: |-
TODO docs
FIXME the corresponding typescript field is required/non-optional, but nulls currently appear here when serializing -Infinity to JSON
type: number
color:
description: TODO docs
type: string
state:
description: |-
TODO docs
TODO are the values here enumerable into a disjunction?
Some seem to be listed in typescript comment
type: string
dashboard.ThresholdsConfig:
type: object
required:
- mode
- steps
properties:
mode:
type: string
enum:
- absolute
- percentage
steps:
description: Must be sorted by 'value', first value is always -Infinity
type: array
items:
type: object
required:
- color
properties:
value:
description: |-
TODO docs
FIXME the corresponding typescript field is required/non-optional, but nulls currently appear here when serializing -Infinity to JSON
type: number
color:
description: TODO docs
type: string
state:
description: |-
TODO docs
TODO are the values here enumerable into a disjunction?
Some seem to be listed in typescript comment
type: string
dashboard.ThresholdsMode:
type: string
enum:
- absolute
- percentage
dashboard.Transformation:
description: |-
TODO docs
FIXME this is extremely underspecfied; wasn't obvious which typescript types corresponded to it
type: object
required:
- id
- options
properties:
id:
type: string
options:
type: object
dashboard.VariableModel:
description: |-
FROM: packages/grafana-data/src/types/templateVars.ts
TODO docs
TODO what about what's in public/app/features/types.ts?
TODO there appear to be a lot of different kinds of [template] vars here? if so need a disjunction
type: object
required:
- type
- name
properties:
type:
type: string
enum:
- query
- adhoc
- constant
- datasource
- interval
- textbox
- custom
- system
name:
type: string
label:
type: string
dashboard.VariableType:
description: |-
FROM: packages/grafana-data/src/types/templateVars.ts
TODO docs
TODO this implies some wider pattern/discriminated union, probably?
type: string
enum:
- query
- adhoc
- constant
- datasource
- interval
- textbox
- custom
- system
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment