From 806fdcef8537b700d9019ac99011374db86e17b1 Mon Sep 17 00:00:00 2001 From: Duologic Date: Sun, 6 Nov 2022 21:29:49 +0100 Subject: [PATCH 1/8] poc: Generate jsonnet library from upstream schema --- grafonnext/.gitignore | 2 + grafonnext/Makefile | 7 + grafonnext/bin/mkimport.sh | 19 + grafonnext/bin/mkschema.sh | 33 + grafonnext/example.libsonnet | 8 + grafonnext/jsonnetfile.json | 15 + grafonnext/main.libsonnet | 54 + grafonnext/schemas.libsonnet | 6 + grafonnext/schemas/v9.2.3/dashboard.json | 1279 ++++++++++++++++++++++ 9 files changed, 1423 insertions(+) create mode 100644 grafonnext/.gitignore create mode 100644 grafonnext/Makefile create mode 100644 grafonnext/bin/mkimport.sh create mode 100644 grafonnext/bin/mkschema.sh create mode 100644 grafonnext/example.libsonnet create mode 100644 grafonnext/jsonnetfile.json create mode 100644 grafonnext/main.libsonnet create mode 100644 grafonnext/schemas.libsonnet create mode 100644 grafonnext/schemas/v9.2.3/dashboard.json diff --git a/grafonnext/.gitignore b/grafonnext/.gitignore new file mode 100644 index 00000000..f9bf6ba8 --- /dev/null +++ b/grafonnext/.gitignore @@ -0,0 +1,2 @@ +jsonnetfile.lock.json +vendor diff --git a/grafonnext/Makefile b/grafonnext/Makefile new file mode 100644 index 00000000..3e4dad17 --- /dev/null +++ b/grafonnext/Makefile @@ -0,0 +1,7 @@ +ROOT:=$PWD + +schemas/%: + sh bin/mkschema.sh $* $(abspath schemas) + +schemas.libsonnet: + sh bin/mkimport.sh diff --git a/grafonnext/bin/mkimport.sh b/grafonnext/bin/mkimport.sh new file mode 100644 index 00000000..8b1ad2ab --- /dev/null +++ b/grafonnext/bin/mkimport.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euo pipefail +IFS=$'\n\t' + +function gen() { + echo "{" + echo "// Generated with make schemas.libsonnet" + for VERSION in $(find schemas/* -maxdepth 0 -type d); do + V=$(basename $VERSION) + echo "'$V': [" + for FILE in $(find $VERSION/* -maxdepth 0 -type f); do + echo "import '$FILE'," + done + echo "]," + done + echo "}" +} + +gen | jsonnetfmt - > schemas.libsonnet diff --git a/grafonnext/bin/mkschema.sh b/grafonnext/bin/mkschema.sh new file mode 100644 index 00000000..8bbe9599 --- /dev/null +++ b/grafonnext/bin/mkschema.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -euo pipefail +IFS=$'\n\t' + +if [ "$#" != 2 ]; then + echo "Usage: $(basename "$0") VERSION OUTPUTDIR" + exit 1 +fi + +VERSION="$1" +OUTPUTDIR="$2" + +mkdir -p "$OUTPUTDIR/$VERSION" + +TEMPDIR=$(mktemp -d) + +trap "rm -rf $TEMPDIR" EXIT + +git clone --branch "$VERSION" --depth 1 https://github.com/grafana/grafana.git "$TEMPDIR" +cd "$TEMPDIR" + +cd pkg/coremodel/dashboard +thema lineage gen jsonschema > "$OUTPUTDIR/$VERSION/dashboard.json" +cd - + +# Made an assumption here, generating jsonschema for these don't work. +#for FILE in $(find public -name models.cue); do +# DIR=$(dirname "$FILE") +# NAME=$(basename "$DIR") +# cd "$DIR" +# thema lineage gen jsonschema > "$OUTPUTDIR/$VERSION/$NAME.json" +# cd - +#done diff --git a/grafonnext/example.libsonnet b/grafonnext/example.libsonnet new file mode 100644 index 00000000..0283b77c --- /dev/null +++ b/grafonnext/example.libsonnet @@ -0,0 +1,8 @@ +local grafonnet = (import './main.libsonnet')('v9.2.3'); +local dashboard = grafonnet.dashboard; +local panel = grafonnet.dashboard.panels.panel; + +dashboard.new('testDashboard') ++ dashboard.withPanels( + panel.new('testPanel', 'timeseries') +) diff --git a/grafonnext/jsonnetfile.json b/grafonnext/jsonnetfile.json new file mode 100644 index 00000000..b211cbb4 --- /dev/null +++ b/grafonnext/jsonnetfile.json @@ -0,0 +1,15 @@ +{ + "version": 1, + "dependencies": [ + { + "source": { + "git": { + "remote": "https://github.com/Duologic/crdsonnet.git", + "subdir": "crdsonnet" + } + }, + "version": "master" + } + ], + "legacyImports": true +} diff --git a/grafonnext/main.libsonnet b/grafonnext/main.libsonnet new file mode 100644 index 00000000..0269e828 --- /dev/null +++ b/grafonnext/main.libsonnet @@ -0,0 +1,54 @@ +local crdsonnet = import 'github.com/Duologic/crdsonnet/crdsonnet/main.libsonnet'; +local render = import 'github.com/Duologic/crdsonnet/crdsonnet/render.libsonnet'; +local schemas = import 'schemas.libsonnet'; + +function(version='v9.2.3') + + local schema = { + [s.info.title]: s + for s in schemas[version] + }.dashboard; + local component = schema.components.schemas.dashboard; + + crdsonnet.fromOpenAPI( + 'dashboard', + component, + schema, + render='dynamic', + ) + + { + dashboard+: { + new(title): + self.withTitle(title) + + self.withTimezone('utc') + + self.time.withFrom('now-6h') + + self.time.withTo('now'), + + panels+: { + 'dashboard.GraphPanel'+:: {}, + graphPanel+: self['dashboard.GraphPanel'] { + new(title): + self.withTitle(title) + + self.withType('graph'), + }, + 'dashboard.HeatmapPanel'+:: {}, + heatmapPanel+: self['dashboard.HeatmapPanel'] { + new(title): + self.withTitle(title) + + self.withType('heatmap'), + }, + 'dashboard.Panel'+:: {}, + panel+: self['dashboard.Panel'] { + new(title, type): + self.withTitle(title) + + self.withType(type), + }, + 'dashboard.RowPanel'+:: {}, + rowPanel+: self['dashboard.RowPanel'] { + new(title): + self.withTitle(title) + + self.withType(), + }, + }, + }, + } diff --git a/grafonnext/schemas.libsonnet b/grafonnext/schemas.libsonnet new file mode 100644 index 00000000..ad0cf420 --- /dev/null +++ b/grafonnext/schemas.libsonnet @@ -0,0 +1,6 @@ +{ + // Generated with make schemas.libsonnet + 'v9.2.3': [ + import 'schemas/v9.2.3/dashboard.json', + ], +} diff --git a/grafonnext/schemas/v9.2.3/dashboard.json b/grafonnext/schemas/v9.2.3/dashboard.json new file mode 100644 index 00000000..27f7c641 --- /dev/null +++ b/grafonnext/schemas/v9.2.3/dashboard.json @@ -0,0 +1,1279 @@ +{ + "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.\nTODO 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\nTODO 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", + "time_options" + ], + "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" + ] + }, + "time_options": { + "description": "TODO docs", + "type": "array", + "items": { + "type": "string" + }, + "default": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + } + } + }, + "fiscalYearStartMonth": { + "description": "TODO docs", + "type": "integer", + "minimum": 0, + "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\nchanges to said schema.\nTODO 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.RowPanel" + }, + { + "$ref": "#/components/schemas/dashboard.GraphPanel" + }, + { + "$ref": "#/components/schemas/dashboard.HeatmapPanel" + } + ] + } + }, + "templating": { + "type": "object", + "required": [ + "list" + ], + "properties": { + "list": { + "description": "TODO docs", + "type": "array", + "items": { + "$ref": "#/components/schemas/dashboard.VariableModel" + } + } + } + }, + "annotations": { + "type": "object", + "required": [ + "list" + ], + "properties": { + "list": { + "description": "TODO docs", + "type": "array", + "items": { + "$ref": "#/components/schemas/dashboard.AnnotationQuery" + } + } + } + }, + "links": { + "description": "TODO docs", + "type": "array", + "items": { + "$ref": "#/components/schemas/dashboard.DashboardLink" + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.AnnotationQuery": { + "description": "TODO docs\nFROM: 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" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.DashboardCursorSync": { + "description": "0 for no shared crosshair or tooltip (default).\n1 for shared crosshair.\n2 for shared crosshair AND shared tooltip.", + "type": "integer", + "enum": [ + 0, + 1, + 2 + ], + "default": 0, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.DashboardLink": { + "description": "FROM public/app/features/dashboard/state/DashboardModels.ts - ish\nTODO 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 + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.DashboardLinkType": { + "description": "TODO docs", + "type": "string", + "enum": [ + "link", + "dashboards" + ], + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "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" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.FieldColorModeId": { + "description": "TODO docs", + "type": "string", + "enum": [ + "thresholds", + "palette-classic", + "palette-saturated", + "continuous-GrYlRd", + "fixed" + ], + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.FieldColorSeriesByMode": { + "description": "TODO docs", + "type": "string", + "enum": [ + "min", + "max", + "last" + ], + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.GraphPanel": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "description": "Support for legacy graph and heatmap panels.", + "type": "string", + "enum": [ + "graph" + ] + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.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" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.HeatmapPanel": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "heatmap" + ] + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.Panel": { + "description": "Dashboard panels. Panels are canonically defined inline\nbecause they share a version timeline with the dashboard\nschema; 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": { + "$ref": "#/components/schemas/dashboard.GridPos" + }, + "links": { + "description": "Panel links.\nTODO 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.\n\"h\" for horizontal, \"v\" for vertical.", + "type": "string", + "enum": [ + "h", + "v" + ], + "default": "h" + }, + "maxDataPoints": { + "description": "TODO docs", + "type": "number" + }, + "thresholds": { + "description": "TODO docs - seems to be an old field from old dashboard alerts?", + "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\nTODO tighter constraint", + "type": "string" + }, + "timeFrom": { + "description": "TODO docs\nTODO tighter constraint", + "type": "string" + }, + "timeShift": { + "description": "TODO docs\nTODO tighter constraint", + "type": "string" + }, + "options": { + "description": "options is specified by the PanelOptions field in panel\nplugin 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\nWhen 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,\nThis will default to `${frame.meta.path}/${field.name}\n\nWhen defined, this value can be used as an identifier within the datasource scope, and\nmay 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\n\nTODO this one corresponds to a complex type with\ngenerics on the typescript side. Ouch. Will\neither need special care, or we'll just need to\naccept a very loosely specified schema. It's very\nunlikely we'll be able to translate cue to\ntypescript generics in the general case, though\nthis 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\nin 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": {} + } + } + } + } + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "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": { + "$ref": "#/components/schemas/dashboard.GridPos" + }, + "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": { + "$ref": "#/components/schemas/dashboard.GridPos" + }, + "links": { + "description": "Panel links.\nTODO 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.\n\"h\" for horizontal, \"v\" for vertical.", + "type": "string", + "enum": [ + "h", + "v" + ], + "default": "h" + }, + "maxDataPoints": { + "description": "TODO docs", + "type": "number" + }, + "thresholds": { + "description": "TODO docs - seems to be an old field from old dashboard alerts?", + "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\nTODO tighter constraint", + "type": "string" + }, + "timeFrom": { + "description": "TODO docs\nTODO tighter constraint", + "type": "string" + }, + "timeShift": { + "description": "TODO docs\nTODO tighter constraint", + "type": "string" + }, + "options": { + "description": "options is specified by the PanelOptions field in panel\nplugin 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\nWhen 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,\nThis will default to `${frame.meta.path}/${field.name}\n\nWhen defined, this value can be used as an identifier within the datasource scope, and\nmay 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\n\nTODO this one corresponds to a complex type with\ngenerics on the typescript side. Ouch. Will\neither need special care, or we'll just need to\naccept a very loosely specified schema. It's very\nunlikely we'll be able to translate cue to\ntypescript generics in the general case, though\nthis 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\nin 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" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.Target": { + "description": "Schema for panel targets is specified by datasource\nplugins. We use a placeholder definition, which the Go\nschema loader either left open/as-is with the Base\nvariant of the Dashboard and Panel families, or filled\nwith types derived from plugins in the Instance variant.\nWhen working directly from CUE, importers can extend this\ntype directly to achieve the same effect.", + "type": "object", + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.Threshold": { + "description": "TODO docs", + "type": "object", + "required": [ + "color" + ], + "properties": { + "value": { + "description": "TODO docs\nFIXME 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\nTODO are the values here enumerable into a disjunction?\nSome seem to be listed in typescript comment", + "type": "string" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "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\nFIXME 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\nTODO are the values here enumerable into a disjunction?\nSome seem to be listed in typescript comment", + "type": "string" + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.ThresholdsMode": { + "type": "string", + "enum": [ + "absolute", + "percentage" + ], + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.Transformation": { + "description": "TODO docs\nFIXME 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" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.VariableModel": { + "description": "FROM: packages/grafana-data/src/types/templateVars.ts\nTODO docs\nTODO what about what's in public/app/features/types.ts?\nTODO 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" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.VariableType": { + "description": "FROM: packages/grafana-data/src/types/templateVars.ts\nTODO docs\nTODO this implies some wider pattern/discriminated union, probably?", + "type": "string", + "enum": [ + "query", + "adhoc", + "constant", + "datasource", + "interval", + "textbox", + "custom", + "system" + ], + "$schema": "http://json-schema.org/draft-04/schema#" + } + } + } +} \ No newline at end of file From 4ce2c86138ad104797cd9943c07eb8ed49c543e3 Mon Sep 17 00:00:00 2001 From: Duologic Date: Mon, 7 Nov 2022 15:59:43 +0100 Subject: [PATCH 2/8] provide both dynamic and static rendering --- grafonnext/Makefile | 3 + grafonnext/bin/mkimport.sh | 2 +- grafonnext/main.libsonnet | 48 ++---- grafonnext/schemas.libsonnet | 2 +- grafonnext/static-v9.2.3.libsonnet | 246 +++++++++++++++++++++++++++++ grafonnext/veneer.libsonnet | 36 +++++ 6 files changed, 296 insertions(+), 41 deletions(-) create mode 100644 grafonnext/static-v9.2.3.libsonnet create mode 100644 grafonnext/veneer.libsonnet diff --git a/grafonnext/Makefile b/grafonnext/Makefile index 3e4dad17..de448b01 100644 --- a/grafonnext/Makefile +++ b/grafonnext/Makefile @@ -5,3 +5,6 @@ schemas/%: schemas.libsonnet: sh bin/mkimport.sh + +static-%.libsonnet: + jsonnet -S -J vendor -A version='$*' -A render='static' main.libsonnet | jsonnetfmt - > static-$*.libsonnet diff --git a/grafonnext/bin/mkimport.sh b/grafonnext/bin/mkimport.sh index 8b1ad2ab..75c41370 100644 --- a/grafonnext/bin/mkimport.sh +++ b/grafonnext/bin/mkimport.sh @@ -4,7 +4,7 @@ IFS=$'\n\t' function gen() { echo "{" - echo "// Generated with make schemas.libsonnet" + echo "// Generated with \`make schemas.libsonnet\`" for VERSION in $(find schemas/* -maxdepth 0 -type d); do V=$(basename $VERSION) echo "'$V': [" diff --git a/grafonnext/main.libsonnet b/grafonnext/main.libsonnet index 0269e828..b93281e2 100644 --- a/grafonnext/main.libsonnet +++ b/grafonnext/main.libsonnet @@ -2,7 +2,7 @@ local crdsonnet = import 'github.com/Duologic/crdsonnet/crdsonnet/main.libsonnet local render = import 'github.com/Duologic/crdsonnet/crdsonnet/render.libsonnet'; local schemas = import 'schemas.libsonnet'; -function(version='v9.2.3') +function(version='v9.2.3', render='dynamic') local schema = { [s.info.title]: s @@ -10,45 +10,15 @@ function(version='v9.2.3') }.dashboard; local component = schema.components.schemas.dashboard; - crdsonnet.fromOpenAPI( + (if render == 'dynamic' + then {} + else '// Generated with `make static-%s.libsonnet`\n' % version) + + crdsonnet.fromOpenAPI( 'dashboard', component, schema, - render='dynamic', + render=render, ) - + { - dashboard+: { - new(title): - self.withTitle(title) - + self.withTimezone('utc') - + self.time.withFrom('now-6h') - + self.time.withTo('now'), - - panels+: { - 'dashboard.GraphPanel'+:: {}, - graphPanel+: self['dashboard.GraphPanel'] { - new(title): - self.withTitle(title) - + self.withType('graph'), - }, - 'dashboard.HeatmapPanel'+:: {}, - heatmapPanel+: self['dashboard.HeatmapPanel'] { - new(title): - self.withTitle(title) - + self.withType('heatmap'), - }, - 'dashboard.Panel'+:: {}, - panel+: self['dashboard.Panel'] { - new(title, type): - self.withTitle(title) - + self.withType(type), - }, - 'dashboard.RowPanel'+:: {}, - rowPanel+: self['dashboard.RowPanel'] { - new(title): - self.withTitle(title) - + self.withType(), - }, - }, - }, - } + + (if render == 'dynamic' + then (import 'veneer.libsonnet') + else "\n+ (import 'veneer.libsonnet')") diff --git a/grafonnext/schemas.libsonnet b/grafonnext/schemas.libsonnet index ad0cf420..85e83d26 100644 --- a/grafonnext/schemas.libsonnet +++ b/grafonnext/schemas.libsonnet @@ -1,5 +1,5 @@ { - // Generated with make schemas.libsonnet + // Generated with `make schemas.libsonnet` 'v9.2.3': [ import 'schemas/v9.2.3/dashboard.json', ], diff --git a/grafonnext/static-v9.2.3.libsonnet b/grafonnext/static-v9.2.3.libsonnet new file mode 100644 index 00000000..7b4b081d --- /dev/null +++ b/grafonnext/static-v9.2.3.libsonnet @@ -0,0 +1,246 @@ +// Generated with make static-v9.2.3.libsonnet +{ + dashboard+: { + withAnnotations(value): { annotations: value }, + withAnnotationsMixin(value): { annotations+: value }, + annotations+: { + withList(value): { annotations+: { list: if std.isArray(value) then value else [value] } }, + withListMixin(value): { annotations+: { list+: if std.isArray(value) then value else [value] } }, + list+: { + withBuiltIn(value=0): { annotations+: { builtIn: value } }, + withDatasource(value): { annotations+: { datasource: value } }, + withDatasourceMixin(value): { annotations+: { datasource+: value } }, + datasource+: { + withType(value): { annotations+: { datasource+: { type: value } } }, + withUid(value): { annotations+: { datasource+: { uid: value } } }, + }, + withEnable(value=true): { annotations+: { enable: value } }, + withHide(value=false): { annotations+: { hide: value } }, + withIconColor(value): { annotations+: { iconColor: value } }, + withName(value): { annotations+: { name: value } }, + withRawQuery(value): { annotations+: { rawQuery: value } }, + withShowIn(value=0): { annotations+: { showIn: value } }, + withTarget(value): { annotations+: { target: value } }, + withTargetMixin(value): { annotations+: { target+: value } }, + withType(value='dashboard'): { annotations+: { type: value } }, + }, + }, + withDescription(value): { description: value }, + withEditable(value=true): { editable: value }, + withFiscalYearStartMonth(value): { fiscalYearStartMonth: value }, + withGnetId(value): { gnetId: value }, + withGraphTooltip(value=0): { graphTooltip: value }, + withId(value): { id: value }, + withLinks(value): { links: if std.isArray(value) then value else [value] }, + withLinksMixin(value): { links+: if std.isArray(value) then value else [value] }, + links+: { + withAsDropdown(value=false): { asDropdown: value }, + withIcon(value): { icon: value }, + withIncludeVars(value=false): { includeVars: value }, + withKeepTime(value=false): { keepTime: value }, + withTags(value): { tags: if std.isArray(value) then value else [value] }, + withTagsMixin(value): { tags+: if std.isArray(value) then value else [value] }, + withTargetBlank(value=false): { targetBlank: value }, + withTitle(value): { title: value }, + withTooltip(value): { tooltip: value }, + withType(value): { type: value }, + withUrl(value): { url: value }, + }, + withLiveNow(value=true): { liveNow: value }, + withPanels(value): { panels: if std.isArray(value) then value else [value] }, + withPanelsMixin(value): { panels+: if std.isArray(value) then value else [value] }, + panels+: { + 'dashboard.Panel'+: { + withDatasource(value): { datasource: value }, + withDatasourceMixin(value): { datasource+: value }, + datasource+: { + withType(value): { datasource+: { type: value } }, + withUid(value): { datasource+: { uid: value } }, + }, + withDescription(value): { description: value }, + withFieldConfig(value): { fieldConfig: value }, + withFieldConfigMixin(value): { fieldConfig+: value }, + fieldConfig+: { + withDefaults(value): { fieldConfig+: { defaults: value } }, + withDefaultsMixin(value): { fieldConfig+: { defaults+: value } }, + defaults+: { + withColor(value): { fieldConfig+: { defaults+: { color: value } } }, + withColorMixin(value): { fieldConfig+: { defaults+: { color+: value } } }, + color+: { + withFixedColor(value): { fieldConfig+: { defaults+: { color+: { fixedColor: value } } } }, + withMode(value): { fieldConfig+: { defaults+: { color+: { mode: value } } } }, + withSeriesBy(value): { fieldConfig+: { defaults+: { color+: { seriesBy: value } } } }, + }, + withCustom(value): { fieldConfig+: { defaults+: { custom: value } } }, + withCustomMixin(value): { fieldConfig+: { defaults+: { custom+: value } } }, + withDecimals(value): { fieldConfig+: { defaults+: { decimals: value } } }, + withDescription(value): { fieldConfig+: { defaults+: { description: value } } }, + withDisplayName(value): { fieldConfig+: { defaults+: { displayName: value } } }, + withDisplayNameFromDS(value): { fieldConfig+: { defaults+: { displayNameFromDS: value } } }, + withFilterable(value=true): { fieldConfig+: { defaults+: { filterable: value } } }, + withLinks(value): { fieldConfig+: { defaults+: { links: if std.isArray(value) then value else [value] } } }, + withLinksMixin(value): { fieldConfig+: { defaults+: { links+: if std.isArray(value) then value else [value] } } }, + withMappings(value): { fieldConfig+: { defaults+: { mappings: if std.isArray(value) then value else [value] } } }, + withMappingsMixin(value): { fieldConfig+: { defaults+: { mappings+: if std.isArray(value) then value else [value] } } }, + withMax(value): { fieldConfig+: { defaults+: { max: value } } }, + withMin(value): { fieldConfig+: { defaults+: { min: value } } }, + withNoValue(value): { fieldConfig+: { defaults+: { noValue: value } } }, + withPath(value): { fieldConfig+: { defaults+: { path: value } } }, + withThresholds(value): { fieldConfig+: { defaults+: { thresholds: value } } }, + withThresholdsMixin(value): { fieldConfig+: { defaults+: { thresholds+: value } } }, + thresholds+: { + withMode(value): { fieldConfig+: { defaults+: { thresholds+: { mode: value } } } }, + withSteps(value): { fieldConfig+: { defaults+: { thresholds+: { steps: if std.isArray(value) then value else [value] } } } }, + withStepsMixin(value): { fieldConfig+: { defaults+: { thresholds+: { steps+: if std.isArray(value) then value else [value] } } } }, + steps+: { + withColor(value): { fieldConfig+: { defaults+: { thresholds+: { color: value } } } }, + withState(value): { fieldConfig+: { defaults+: { thresholds+: { state: value } } } }, + withValue(value): { fieldConfig+: { defaults+: { thresholds+: { value: value } } } }, + }, + }, + withUnit(value): { fieldConfig+: { defaults+: { unit: value } } }, + withWriteable(value=true): { fieldConfig+: { defaults+: { writeable: value } } }, + }, + withOverrides(value): { fieldConfig+: { overrides: if std.isArray(value) then value else [value] } }, + withOverridesMixin(value): { fieldConfig+: { overrides+: if std.isArray(value) then value else [value] } }, + overrides+: { + withMatcher(value): { fieldConfig+: { matcher: value } }, + withMatcherMixin(value): { fieldConfig+: { matcher+: value } }, + matcher+: { + withId(value=''): { fieldConfig+: { matcher+: { id: value } } }, + withOptions(value): { fieldConfig+: { matcher+: { options: value } } }, + }, + withProperties(value): { fieldConfig+: { properties: if std.isArray(value) then value else [value] } }, + withPropertiesMixin(value): { fieldConfig+: { properties+: if std.isArray(value) then value else [value] } }, + properties+: { + withId(value=''): { fieldConfig+: { id: value } }, + withValue(value): { fieldConfig+: { value: value } }, + }, + }, + }, + withGridPos(value): { gridPos: value }, + withGridPosMixin(value): { gridPos+: value }, + gridPos+: { + withH(value=9): { gridPos+: { h: value } }, + withStatic(value=true): { gridPos+: { static: value } }, + withW(value=12): { gridPos+: { w: value } }, + withX(value=0): { gridPos+: { x: value } }, + withY(value=0): { gridPos+: { y: value } }, + }, + withId(value): { id: value }, + withInterval(value): { interval: value }, + withLinks(value): { links: if std.isArray(value) then value else [value] }, + withLinksMixin(value): { links+: if std.isArray(value) then value else [value] }, + links+: { + withAsDropdown(value=false): { asDropdown: value }, + withIcon(value): { icon: value }, + withIncludeVars(value=false): { includeVars: value }, + withKeepTime(value=false): { keepTime: value }, + withTags(value): { tags: if std.isArray(value) then value else [value] }, + withTagsMixin(value): { tags+: if std.isArray(value) then value else [value] }, + withTargetBlank(value=false): { targetBlank: value }, + withTitle(value): { title: value }, + withTooltip(value): { tooltip: value }, + withType(value): { type: value }, + withUrl(value): { url: value }, + }, + withMaxDataPoints(value): { maxDataPoints: value }, + withOptions(value): { options: value }, + withOptionsMixin(value): { options+: value }, + withPluginVersion(value): { pluginVersion: value }, + withRepeat(value): { repeat: value }, + withRepeatDirection(value='h'): { repeatDirection: value }, + withTags(value): { tags: if std.isArray(value) then value else [value] }, + withTagsMixin(value): { tags+: if std.isArray(value) then value else [value] }, + withTargets(value): { targets: if std.isArray(value) then value else [value] }, + withTargetsMixin(value): { targets+: if std.isArray(value) then value else [value] }, + withThresholds(value): { thresholds: if std.isArray(value) then value else [value] }, + withThresholdsMixin(value): { thresholds+: if std.isArray(value) then value else [value] }, + withTimeFrom(value): { timeFrom: value }, + withTimeRegions(value): { timeRegions: if std.isArray(value) then value else [value] }, + withTimeRegionsMixin(value): { timeRegions+: if std.isArray(value) then value else [value] }, + withTimeShift(value): { timeShift: value }, + withTitle(value): { title: value }, + withTransformations(value): { transformations: if std.isArray(value) then value else [value] }, + withTransformationsMixin(value): { transformations+: if std.isArray(value) then value else [value] }, + transformations+: { + withId(value): { id: value }, + withOptions(value): { options: value }, + withOptionsMixin(value): { options+: value }, + }, + withTransparent(value=false): { transparent: value }, + withType(value): { type: value }, + }, + 'dashboard.RowPanel'+: { + withCollapsed(value=false): { collapsed: value }, + withDatasource(value): { datasource: value }, + withDatasourceMixin(value): { datasource+: value }, + datasource+: { + withType(value): { datasource+: { type: value } }, + withUid(value): { datasource+: { uid: value } }, + }, + withGridPos(value): { gridPos: value }, + withGridPosMixin(value): { gridPos+: value }, + gridPos+: { + withH(value=9): { gridPos+: { h: value } }, + withStatic(value=true): { gridPos+: { static: value } }, + withW(value=12): { gridPos+: { w: value } }, + withX(value=0): { gridPos+: { x: value } }, + withY(value=0): { gridPos+: { y: value } }, + }, + withId(value): { id: value }, + withPanels(value): { panels: if std.isArray(value) then value else [value] }, + withPanelsMixin(value): { panels+: if std.isArray(value) then value else [value] }, + withRepeat(value): { repeat: value }, + withTitle(value): { title: value }, + withType(value): { type: value }, + }, + 'dashboard.GraphPanel'+: { + withType(value): { type: value }, + }, + 'dashboard.HeatmapPanel'+: { + withType(value): { type: value }, + }, + }, + withRefresh(value): { refresh: value }, + withRefreshMixin(value): { refresh+: value }, + withSchemaVersion(value=36): { schemaVersion: value }, + withStyle(value='dark'): { style: value }, + withTags(value): { tags: if std.isArray(value) then value else [value] }, + withTagsMixin(value): { tags+: if std.isArray(value) then value else [value] }, + withTemplating(value): { templating: value }, + withTemplatingMixin(value): { templating+: value }, + templating+: { + withList(value): { templating+: { list: if std.isArray(value) then value else [value] } }, + withListMixin(value): { templating+: { list+: if std.isArray(value) then value else [value] } }, + list+: { + withLabel(value): { templating+: { label: value } }, + withName(value): { templating+: { name: value } }, + withType(value): { templating+: { type: value } }, + }, + }, + withTime(value): { time: value }, + withTimeMixin(value): { time+: value }, + time+: { + withFrom(value='now-6h'): { time+: { from: value } }, + withTo(value='now'): { time+: { to: value } }, + }, + withTimepicker(value): { timepicker: value }, + withTimepickerMixin(value): { timepicker+: value }, + timepicker+: { + withCollapse(value=false): { timepicker+: { collapse: value } }, + withEnable(value=true): { timepicker+: { enable: value } }, + withHidden(value=false): { timepicker+: { hidden: value } }, + withRefreshIntervals(value): { timepicker+: { refresh_intervals: if std.isArray(value) then value else [value] } }, + withRefreshIntervalsMixin(value): { timepicker+: { refresh_intervals+: if std.isArray(value) then value else [value] } }, + withTimeOptions(value): { timepicker+: { time_options: if std.isArray(value) then value else [value] } }, + withTimeOptionsMixin(value): { timepicker+: { time_options+: if std.isArray(value) then value else [value] } }, + }, + withTimezone(value='browser'): { timezone: value }, + withTitle(value): { title: value }, + withUid(value): { uid: value }, + withVersion(value): { version: value }, + withWeekStart(value): { weekStart: value }, + }, +} ++ (import 'veneer.libsonnet') diff --git a/grafonnext/veneer.libsonnet b/grafonnext/veneer.libsonnet new file mode 100644 index 00000000..069f1156 --- /dev/null +++ b/grafonnext/veneer.libsonnet @@ -0,0 +1,36 @@ +{ + dashboard+: { + new(title): + self.withTitle(title) + + self.withTimezone('utc') + + self.time.withFrom('now-6h') + + self.time.withTo('now'), + + panels+: { + 'dashboard.GraphPanel'+:: {}, + graphPanel+: self['dashboard.GraphPanel'] { + new(title): + self.withTitle(title) + + self.withType('graph'), + }, + 'dashboard.HeatmapPanel'+:: {}, + heatmapPanel+: self['dashboard.HeatmapPanel'] { + new(title): + self.withTitle(title) + + self.withType('heatmap'), + }, + 'dashboard.Panel'+:: {}, + panel+: self['dashboard.Panel'] { + new(title, type): + self.withTitle(title) + + self.withType(type), + }, + 'dashboard.RowPanel'+:: {}, + rowPanel+: self['dashboard.RowPanel'] { + new(title): + self.withTitle(title) + + self.withType(), + }, + }, + }, +} From 52b698ff175aaa3b2e5a64bbfd23162cefbf80f1 Mon Sep 17 00:00:00 2001 From: Duologic Date: Mon, 7 Nov 2022 16:00:29 +0100 Subject: [PATCH 3/8] use backticks --- grafonnext/static-v9.2.3.libsonnet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grafonnext/static-v9.2.3.libsonnet b/grafonnext/static-v9.2.3.libsonnet index 7b4b081d..05df6cb1 100644 --- a/grafonnext/static-v9.2.3.libsonnet +++ b/grafonnext/static-v9.2.3.libsonnet @@ -1,4 +1,4 @@ -// Generated with make static-v9.2.3.libsonnet +// Generated with `make static-v9.2.3.libsonnet` { dashboard+: { withAnnotations(value): { annotations: value }, From da54d8b963be5a6f9cbecff8f9d10c4051733cc0 Mon Sep 17 00:00:00 2001 From: sam boyer Date: Tue, 8 Nov 2022 04:57:07 -0500 Subject: [PATCH 4/8] poc: Add Go-based generator of JSON Schema --- grafonnext/go.mod | 25 + grafonnext/go.sum | 62 + grafonnext/mkschema.go | 73 + .../latest/composable/panel/annolist.json | 82 + .../latest/composable/panel/dashlist.json | 79 + .../schemas/latest/composable/panel/news.json | 34 + .../schemas/latest/composable/panel/text.json | 106 + grafonnext/schemas/latest/core/dashboard.json | 1917 +++++++++++++++++ grafonnext/schemas/latest/core/playlist.json | 70 + 9 files changed, 2448 insertions(+) create mode 100644 grafonnext/go.mod create mode 100644 grafonnext/go.sum create mode 100644 grafonnext/mkschema.go create mode 100644 grafonnext/schemas/latest/composable/panel/annolist.json create mode 100644 grafonnext/schemas/latest/composable/panel/dashlist.json create mode 100644 grafonnext/schemas/latest/composable/panel/news.json create mode 100644 grafonnext/schemas/latest/composable/panel/text.json create mode 100644 grafonnext/schemas/latest/core/dashboard.json create mode 100644 grafonnext/schemas/latest/core/playlist.json diff --git a/grafonnext/go.mod b/grafonnext/go.mod new file mode 100644 index 00000000..02cb066f --- /dev/null +++ b/grafonnext/go.mod @@ -0,0 +1,25 @@ +module github.com/grafana/grafonnet-lib/grafonnext + +go 1.19 + +require ( + cuelang.org/go v0.4.3 + github.com/grafana/grafana v1.9.2-0.20221107230407-93589c483967 + github.com/grafana/thema v0.0.0-20221107225215-00ad2949c7bc +) + +require ( + github.com/cockroachdb/apd/v2 v2.0.2 // indirect + github.com/emicklei/proto v1.10.0 // indirect + github.com/golang/glog v1.0.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/google/wire v0.5.0 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/protocolbuffers/txtpbfmt v0.0.0-20220428173112-74888fd59c2b // indirect + github.com/yalue/merged_fs v1.2.2 // indirect + golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect + golang.org/x/text v0.3.8 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/grafonnext/go.sum b/grafonnext/go.sum new file mode 100644 index 00000000..c5d1a2c9 --- /dev/null +++ b/grafonnext/go.sum @@ -0,0 +1,62 @@ +cuelang.org/go v0.4.3 h1:W3oBBjDTm7+IZfCKZAmC8uDG0eYfJL4Pp/xbbCMKaVo= +cuelang.org/go v0.4.3/go.mod h1:7805vR9H+VoBNdWFdI7jyDR3QLUPp4+naHfbcgp55HI= +github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= +github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/emicklei/proto v1.10.0 h1:pDGyFRVV5RvV+nkBK9iy3q67FBy9Xa7vwrOTE+g5aGw= +github.com/emicklei/proto v1.10.0/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= +github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= +github.com/grafana/grafana v1.9.2-0.20221107225804-85217355b416 h1:kuVO9kBoK44gUuIW3KtAGK6H6lnfRxDtLxfix3LgIAk= +github.com/grafana/grafana v1.9.2-0.20221107225804-85217355b416/go.mod h1:qD8jQlBap35uu9oteuokbWbIEDrh1CINpxeXcLOg/Hc= +github.com/grafana/grafana v1.9.2-0.20221107230407-93589c483967 h1:xaZRT+bch+reHBaekUzm2BApFBNkt4alBGlleWPpubQ= +github.com/grafana/grafana v1.9.2-0.20221107230407-93589c483967/go.mod h1:qD8jQlBap35uu9oteuokbWbIEDrh1CINpxeXcLOg/Hc= +github.com/grafana/thema v0.0.0-20221107225215-00ad2949c7bc h1:Icv777/PBaqhLmbSBSDaajDl424cbmh5ee77Du2rUFE= +github.com/grafana/thema v0.0.0-20221107225215-00ad2949c7bc/go.mod h1:wnIJykzNiNVANl6g/Z4nkXxoMqaaH1LoG0IPNW++BEk= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de h1:D5x39vF5KCwKQaw+OC9ZPiLVHXz3UFw2+psEX+gYcto= +github.com/mpvl/unique v0.0.0-20150818121801-cbe035fff7de/go.mod h1:kJun4WP5gFuHZgRjZUWWuH1DTxCtxbHDOIJsudS8jzY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/protocolbuffers/txtpbfmt v0.0.0-20220428173112-74888fd59c2b h1:zd/2RNzIRkoGGMjE+YIsZ85CnDIz672JK2F3Zl4vux4= +github.com/protocolbuffers/txtpbfmt v0.0.0-20220428173112-74888fd59c2b/go.mod h1:KjY0wibdYKc4DYkerHSbguaf3JeIPGhNJBp2BNiFH78= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/yalue/merged_fs v1.2.2 h1:vXHTpJBluJryju7BBpytr3PDIkzsPMpiEknxVGPhN/I= +github.com/yalue/merged_fs v1.2.2/go.mod h1:WqqchfVYQyclV2tnR7wtRhBddzBvLVR83Cjw9BKQw0M= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI= +golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/grafonnext/mkschema.go b/grafonnext/mkschema.go new file mode 100644 index 00000000..91bba6ba --- /dev/null +++ b/grafonnext/mkschema.go @@ -0,0 +1,73 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "path/filepath" + "strings" + + "cuelang.org/go/cue/ast" + "github.com/grafana/grafana/pkg/cuectx" + "github.com/grafana/grafana/pkg/plugins/pfs/corelist" + "github.com/grafana/grafana/pkg/registry/corekind" + "github.com/grafana/thema/encoding/jsonschema" +) + +// this is a meaningless hack, we have to work out versioning +var grafanaVersion = "latest" + +var rt = cuectx.GrafanaThemaRuntime() + +func main() { + // All core kinds first + base := filepath.Join("schemas", grafanaVersion, "core") + die(os.MkdirAll(base, 0777)) + + for _, kind := range corekind.NewBase(nil).AllStructured() { + f, err := jsonschema.GenerateSchema(kind.Lineage().Latest()) + if err != nil { + die(fmt.Errorf("%s: %w", kind.Name(), err)) + } + + b := marshalindent(f) + path := filepath.Join(base, kind.MachineName()+".json") + die(os.WriteFile(path, b, 0644)) + } + + // Now, all composable kinds from plugins. (Note that core grafana hasn't been refactored + // to use 'composable kind' naming for its various methods yet) + for _, ptree := range corelist.New(nil) { + for slot, lin := range ptree.RootPlugin().SlotImplementations() { + f, err := jsonschema.GenerateSchema(lin.Latest()) + if err != nil { + // There's a bug in generating openapi from Thema with imports are loaded. + // Normally an edge case in Thema, but needed in Grafana. Commenting this out + // until bug is fixed and just dropping errors instead + // die(fmt.Errorf("%s: %w", ptree.RootPlugin().Meta().Id, err)) + continue + } + + b := marshalindent(f) + basecompo := filepath.Join("schemas", grafanaVersion, "composable", strings.ToLower(slot)) + path := filepath.Join(basecompo, ptree.RootPlugin().Meta().Id+".json") + die(os.MkdirAll(basecompo, 0777)) + die(os.WriteFile(path, b, 0644)) + } + } +} + +func die(err error) { + if err != nil { + fmt.Fprint(os.Stderr, err, "\n") + os.Exit(1) + } +} + +func marshalindent(f *ast.File) []byte { + b, _ := rt.Context().BuildFile(f).MarshalJSON() + nb := new(bytes.Buffer) + die(json.Indent(nb, b, "", " ")) + return nb.Bytes() +} diff --git a/grafonnext/schemas/latest/composable/panel/annolist.json b/grafonnext/schemas/latest/composable/panel/annolist.json new file mode 100644 index 00000000..4d49e435 --- /dev/null +++ b/grafonnext/schemas/latest/composable/panel/annolist.json @@ -0,0 +1,82 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "annolist", + "version": "0.0" + }, + "paths": {}, + "components": { + "schemas": { + "annolist": { + "type": "object", + "required": [ + "PanelOptions" + ], + "properties": { + "PanelOptions": { + "type": "object", + "required": [ + "onlyFromThisDashboard", + "onlyInTimeRange", + "tags", + "limit", + "showUser", + "showTime", + "showTags", + "navigateToPanel", + "navigateBefore", + "navigateAfter" + ], + "properties": { + "onlyFromThisDashboard": { + "type": "boolean", + "default": false + }, + "onlyInTimeRange": { + "type": "boolean", + "default": false + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + }, + "limit": { + "type": "integer", + "minimum": 0, + "maximum": 4294967295, + "default": 10 + }, + "showUser": { + "type": "boolean", + "default": true + }, + "showTime": { + "type": "boolean", + "default": true + }, + "showTags": { + "type": "boolean", + "default": true + }, + "navigateToPanel": { + "type": "boolean", + "default": true + }, + "navigateBefore": { + "type": "string", + "default": "10m" + }, + "navigateAfter": { + "type": "string", + "default": "10m" + } + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + } + } + } +} \ No newline at end of file diff --git a/grafonnext/schemas/latest/composable/panel/dashlist.json b/grafonnext/schemas/latest/composable/panel/dashlist.json new file mode 100644 index 00000000..06528b46 --- /dev/null +++ b/grafonnext/schemas/latest/composable/panel/dashlist.json @@ -0,0 +1,79 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "dashlist", + "version": "0.0" + }, + "paths": {}, + "components": { + "schemas": { + "dashlist": { + "type": "object", + "required": [ + "PanelLayout", + "PanelOptions" + ], + "properties": { + "PanelLayout": { + "type": "string", + "enum": [ + "list", + "previews" + ] + }, + "PanelOptions": { + "type": "object", + "required": [ + "showStarred", + "showRecentlyViewed", + "showSearch", + "showHeadings", + "maxItems", + "query", + "tags" + ], + "properties": { + "layout": { + "$ref": "#/components/schemas/dashlist.PanelLayout" + }, + "showStarred": { + "type": "boolean", + "default": true + }, + "showRecentlyViewed": { + "type": "boolean", + "default": false + }, + "showSearch": { + "type": "boolean", + "default": false + }, + "showHeadings": { + "type": "boolean", + "default": true + }, + "maxItems": { + "type": "integer", + "default": 10 + }, + "query": { + "type": "string", + "default": "" + }, + "folderId": { + "type": "integer" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + } + } + } +} \ No newline at end of file diff --git a/grafonnext/schemas/latest/composable/panel/news.json b/grafonnext/schemas/latest/composable/panel/news.json new file mode 100644 index 00000000..7af0d0ce --- /dev/null +++ b/grafonnext/schemas/latest/composable/panel/news.json @@ -0,0 +1,34 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "news", + "version": "0.0" + }, + "paths": {}, + "components": { + "schemas": { + "news": { + "type": "object", + "required": [ + "PanelOptions" + ], + "properties": { + "PanelOptions": { + "type": "object", + "properties": { + "feedUrl": { + "description": "empty/missing will default to grafana blog", + "type": "string" + }, + "showImage": { + "type": "boolean", + "default": true + } + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + } + } + } +} \ No newline at end of file diff --git a/grafonnext/schemas/latest/composable/panel/text.json b/grafonnext/schemas/latest/composable/panel/text.json new file mode 100644 index 00000000..a9d65894 --- /dev/null +++ b/grafonnext/schemas/latest/composable/panel/text.json @@ -0,0 +1,106 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "text", + "version": "0.0" + }, + "paths": {}, + "components": { + "schemas": { + "text": { + "type": "object", + "required": [ + "TextMode", + "CodeLanguage", + "CodeOptions", + "PanelOptions" + ], + "properties": { + "TextMode": { + "type": "string", + "enum": [ + "html", + "markdown", + "code" + ] + }, + "CodeLanguage": { + "type": "string", + "enum": [ + "plaintext", + "yaml", + "xml", + "typescript", + "sql", + "go", + "markdown", + "html", + "json" + ], + "default": "plaintext" + }, + "CodeOptions": { + "type": "object", + "required": [ + "language", + "showLineNumbers", + "showMiniMap" + ], + "properties": { + "language": { + "description": "The language passed to monaco code editor", + "type": "string", + "enum": [ + "plaintext", + "yaml", + "xml", + "typescript", + "sql", + "go", + "markdown", + "html", + "json" + ], + "default": "plaintext" + }, + "showLineNumbers": { + "type": "boolean", + "default": false + }, + "showMiniMap": { + "type": "boolean", + "default": false + } + } + }, + "PanelOptions": { + "type": "object", + "required": [ + "mode", + "content" + ], + "properties": { + "mode": { + "type": "string", + "enum": [ + "markdown", + "html", + "code" + ], + "default": "markdown" + }, + "code": { + "$ref": "#/components/schemas/text.CodeOptions" + }, + "content": { + "type": "string", + "default": "# Title\n\nFor markdown syntax help: [commonmark.org/help](https://commonmark.org/help/)" + } + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + } + } + } +} \ No newline at end of file diff --git a/grafonnext/schemas/latest/core/dashboard.json b/grafonnext/schemas/latest/core/dashboard.json new file mode 100644 index 00000000..fd7a32f4 --- /dev/null +++ b/grafonnext/schemas/latest/core/dashboard.json @@ -0,0 +1,1917 @@ +{ + "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.\nTODO 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\nTODO 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", + "time_options" + ], + "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" + ] + }, + "time_options": { + "description": "TODO docs", + "type": "array", + "items": { + "type": "string" + }, + "default": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + } + } + }, + "fiscalYearStartMonth": { + "description": "TODO docs", + "type": "integer", + "minimum": 0, + "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\nchanges to said schema.\nTODO 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.RowPanel" + }, + { + "$ref": "#/components/schemas/dashboard.GraphPanel" + }, + { + "$ref": "#/components/schemas/dashboard.HeatmapPanel" + } + ] + } + }, + "templating": { + "type": "object", + "required": [ + "list" + ], + "properties": { + "list": { + "description": "TODO docs", + "type": "array", + "items": { + "$ref": "#/components/schemas/dashboard.VariableModel" + } + } + } + }, + "annotations": { + "type": "object", + "required": [ + "list" + ], + "properties": { + "list": { + "description": "TODO docs", + "type": "array", + "items": { + "$ref": "#/components/schemas/dashboard.AnnotationQuery" + } + } + } + }, + "links": { + "description": "TODO docs", + "type": "array", + "items": { + "$ref": "#/components/schemas/dashboard.DashboardLink" + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.AnnotationQuery": { + "description": "TODO docs\nFROM: 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.AnnotationTarget" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.AnnotationTarget": { + "description": "TODO docs", + "type": "object", + "required": [ + "limit", + "matchAny", + "tags", + "type" + ], + "properties": { + "limit": { + "type": "integer", + "format": "int64" + }, + "matchAny": { + "type": "boolean" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + } + }, + "type": { + "type": "string" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.DashboardCursorSync": { + "description": "0 for no shared crosshair or tooltip (default).\n1 for shared crosshair.\n2 for shared crosshair AND shared tooltip.", + "type": "integer", + "enum": [ + 0, + 1, + 2 + ], + "default": 0, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.DashboardLink": { + "description": "FROM public/app/features/dashboard/state/DashboardModels.ts - ish\nTODO 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 + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.DashboardLinkType": { + "description": "TODO docs", + "type": "string", + "enum": [ + "link", + "dashboards" + ], + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.DynamicConfigValue": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string", + "default": "" + }, + "value": {} + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "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" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.FieldColorModeId": { + "description": "TODO docs", + "type": "string", + "enum": [ + "thresholds", + "palette-classic", + "palette-saturated", + "continuous-GrYlRd", + "fixed" + ], + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.FieldColorSeriesByMode": { + "description": "TODO docs", + "type": "string", + "enum": [ + "min", + "max", + "last" + ], + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.FieldConfig": { + "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\nWhen 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,\nThis will default to `${frame.meta.path}/${field.name}\n\nWhen defined, this value can be used as an identifier within the datasource scope, and\nmay 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", + "type": "array", + "items": { + "$ref": "#/components/schemas/dashboard.ValueMapping" + } + }, + "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\nin panel plugin schemas.", + "type": "object" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.FieldConfigSource": { + "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\nWhen 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,\nThis will default to `${frame.meta.path}/${field.name}\n\nWhen defined, this value can be used as an identifier within the datasource scope, and\nmay 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", + "type": "array", + "items": { + "$ref": "#/components/schemas/dashboard.ValueMapping" + } + }, + "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\nin 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": {} + } + } + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.GraphPanel": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "description": "Support for legacy graph and heatmap panels.", + "type": "string", + "enum": [ + "graph" + ] + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.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" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.HeatmapPanel": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "heatmap" + ] + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.MappingType": { + "description": "TODO docs", + "type": "string", + "enum": [ + "value", + "range", + "regex", + "special" + ], + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.MatcherConfig": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string", + "default": "" + }, + "options": {} + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.Panel": { + "description": "Dashboard panels. Panels are canonically defined inline\nbecause they share a version timeline with the dashboard\nschema; 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": { + "$ref": "#/components/schemas/dashboard.GridPos" + }, + "links": { + "description": "Panel links.\nTODO 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.\n\"h\" for horizontal, \"v\" for vertical.", + "type": "string", + "enum": [ + "h", + "v" + ], + "default": "h" + }, + "maxDataPoints": { + "description": "TODO docs", + "type": "number" + }, + "thresholds": { + "description": "TODO docs - seems to be an old field from old dashboard alerts?", + "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\nTODO tighter constraint", + "type": "string" + }, + "timeFrom": { + "description": "TODO docs\nTODO tighter constraint", + "type": "string" + }, + "timeShift": { + "description": "TODO docs\nTODO tighter constraint", + "type": "string" + }, + "options": { + "description": "options is specified by the PanelOptions field in panel\nplugin 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\nWhen 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,\nThis will default to `${frame.meta.path}/${field.name}\n\nWhen defined, this value can be used as an identifier within the datasource scope, and\nmay 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", + "type": "array", + "items": { + "$ref": "#/components/schemas/dashboard.ValueMapping" + } + }, + "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\nin 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": {} + } + } + } + } + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.RangeMap": { + "description": "TODO docs", + "type": "object", + "required": [ + "type", + "options" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "range" + ] + }, + "options": { + "type": "object", + "required": [ + "from", + "to", + "result" + ], + "properties": { + "from": { + "description": "to and from are `number | null` in current ts, really not sure what to do", + "type": "integer", + "format": "int32" + }, + "to": { + "type": "integer", + "format": "int32" + }, + "result": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "color": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "index": { + "type": "integer", + "format": "int32" + } + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.RegexMap": { + "description": "TODO docs", + "type": "object", + "required": [ + "type", + "options" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "regex" + ] + }, + "options": { + "type": "object", + "required": [ + "pattern", + "result" + ], + "properties": { + "pattern": { + "type": "string" + }, + "result": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "color": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "index": { + "type": "integer", + "format": "int32" + } + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "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": { + "$ref": "#/components/schemas/dashboard.GridPos" + }, + "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": { + "$ref": "#/components/schemas/dashboard.GridPos" + }, + "links": { + "description": "Panel links.\nTODO 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.\n\"h\" for horizontal, \"v\" for vertical.", + "type": "string", + "enum": [ + "h", + "v" + ], + "default": "h" + }, + "maxDataPoints": { + "description": "TODO docs", + "type": "number" + }, + "thresholds": { + "description": "TODO docs - seems to be an old field from old dashboard alerts?", + "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\nTODO tighter constraint", + "type": "string" + }, + "timeFrom": { + "description": "TODO docs\nTODO tighter constraint", + "type": "string" + }, + "timeShift": { + "description": "TODO docs\nTODO tighter constraint", + "type": "string" + }, + "options": { + "description": "options is specified by the PanelOptions field in panel\nplugin 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\nWhen 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,\nThis will default to `${frame.meta.path}/${field.name}\n\nWhen defined, this value can be used as an identifier within the datasource scope, and\nmay 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", + "type": "array", + "items": { + "$ref": "#/components/schemas/dashboard.ValueMapping" + } + }, + "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\nin 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" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.SpecialValueMap": { + "description": "TODO docs", + "type": "object", + "required": [ + "type", + "options" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "special" + ] + }, + "options": { + "type": "object", + "required": [ + "match", + "pattern", + "result" + ], + "properties": { + "match": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "pattern": { + "type": "string" + }, + "result": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "color": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "index": { + "type": "integer", + "format": "int32" + } + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.SpecialValueMatch": { + "description": "TODO docs", + "type": "string", + "enum": [ + "true", + "false", + "null", + "nan", + "null+nan", + "empty" + ], + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.Target": { + "description": "Schema for panel targets is specified by datasource\nplugins. We use a placeholder definition, which the Go\nschema loader either left open/as-is with the Base\nvariant of the Dashboard and Panel families, or filled\nwith types derived from plugins in the Instance variant.\nWhen working directly from CUE, importers can extend this\ntype directly to achieve the same effect.", + "type": "object", + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.Threshold": { + "description": "TODO docs", + "type": "object", + "required": [ + "color" + ], + "properties": { + "value": { + "description": "TODO docs\nFIXME 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\nTODO are the values here enumerable into a disjunction?\nSome seem to be listed in typescript comment", + "type": "string" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "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\nFIXME 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\nTODO are the values here enumerable into a disjunction?\nSome seem to be listed in typescript comment", + "type": "string" + } + } + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.ThresholdsMode": { + "type": "string", + "enum": [ + "absolute", + "percentage" + ], + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.Transformation": { + "description": "TODO docs\nFIXME 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" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.ValueMap": { + "description": "TODO docs", + "type": "object", + "required": [ + "type", + "options" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "value" + ] + }, + "options": { + "type": "object" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.ValueMapping": { + "description": "TODO docs", + "type": "object", + "oneOf": [ + { + "required": [ + "type", + "options" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "value" + ] + }, + "options": { + "type": "object" + } + } + }, + { + "required": [ + "type", + "options" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "range" + ] + }, + "options": { + "type": "object", + "required": [ + "from", + "to", + "result" + ], + "properties": { + "from": { + "description": "to and from are `number | null` in current ts, really not sure what to do", + "type": "integer", + "format": "int32" + }, + "to": { + "type": "integer", + "format": "int32" + }, + "result": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "color": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "index": { + "type": "integer", + "format": "int32" + } + } + } + } + } + } + }, + { + "required": [ + "type", + "options" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "regex" + ] + }, + "options": { + "type": "object", + "required": [ + "pattern", + "result" + ], + "properties": { + "pattern": { + "type": "string" + }, + "result": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "color": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "index": { + "type": "integer", + "format": "int32" + } + } + } + } + } + } + }, + { + "required": [ + "type", + "options" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "special" + ] + }, + "options": { + "type": "object", + "required": [ + "match", + "pattern", + "result" + ], + "properties": { + "match": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "pattern": { + "type": "string" + }, + "result": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "color": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "index": { + "type": "integer", + "format": "int32" + } + } + } + } + } + } + } + ], + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.ValueMappingResult": { + "description": "TODO docs", + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "color": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "index": { + "type": "integer", + "format": "int32" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.VariableModel": { + "description": "FROM: packages/grafana-data/src/types/templateVars.ts\nTODO docs\nTODO what about what's in public/app/features/types.ts?\nTODO 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" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "dashboard.VariableType": { + "description": "FROM: packages/grafana-data/src/types/templateVars.ts\nTODO docs\nTODO this implies some wider pattern/discriminated union, probably?", + "type": "string", + "enum": [ + "query", + "adhoc", + "constant", + "datasource", + "interval", + "textbox", + "custom", + "system" + ], + "$schema": "http://json-schema.org/draft-04/schema#" + } + } + } +} \ No newline at end of file diff --git a/grafonnext/schemas/latest/core/playlist.json b/grafonnext/schemas/latest/core/playlist.json new file mode 100644 index 00000000..28f9dd05 --- /dev/null +++ b/grafonnext/schemas/latest/core/playlist.json @@ -0,0 +1,70 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "playlist", + "version": "0.0" + }, + "paths": {}, + "components": { + "schemas": { + "playlist": { + "type": "object", + "required": [ + "uid", + "name", + "interval" + ], + "properties": { + "uid": { + "description": "Unique playlist identifier. Generated on creation, either by the\ncreator of the playlist of by the application.", + "type": "string" + }, + "name": { + "description": "Name of the playlist.", + "type": "string" + }, + "interval": { + "description": "Interval sets the time between switching views in a playlist.\nFIXME: Is this based on a standardized format or what options are available? Can datemath be used?", + "type": "string", + "default": "5m" + }, + "items": { + "description": "The ordered list of items that the playlist will iterate over.\nFIXME! This should not be optional, but changing it makes the godegen awkward", + "type": "array", + "items": { + "$ref": "#/components/schemas/playlist.PlaylistItem" + } + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + }, + "playlist.PlaylistItem": { + "type": "object", + "required": [ + "type", + "value" + ], + "properties": { + "type": { + "description": "Type of the item.", + "type": "string", + "enum": [ + "dashboard_by_uid", + "dashboard_by_id", + "dashboard_by_tag" + ] + }, + "value": { + "description": "Value depends on type and describes the playlist item.\n\n - dashboard_by_id: The value is an internal numerical identifier set by Grafana. This\n is not portable as the numerical identifier is non-deterministic between different instances.\n Will be replaced by dashboard_by_uid in the future. (deprecated)\n - dashboard_by_tag: The value is a tag which is set on any number of dashboards. All\n dashboards behind the tag will be added to the playlist.\n - dashboard_by_uid: The value is the dashboard UID", + "type": "string" + }, + "title": { + "description": "Title is an unused property -- it will be removed in the future", + "type": "string" + } + }, + "$schema": "http://json-schema.org/draft-04/schema#" + } + } + } +} \ No newline at end of file From 95f721ff190462d1e72930e4aaeb0aefd8894be4 Mon Sep 17 00:00:00 2001 From: Duologic Date: Wed, 9 Nov 2022 21:16:23 +0100 Subject: [PATCH 5/8] refactor: use go version of mkschema - moves go version to separate directory so that jb install will not pull in the go-code. - update main.libsonnet to process the extra schemas --- {grafonnext => grafonnext-go}/go.mod | 2 +- {grafonnext => grafonnext-go}/go.sum | 2 - {grafonnext => grafonnext-go}/mkschema.go | 4 +- grafonnext/Makefile | 3 +- grafonnext/bin/mkimport.sh | 2 +- grafonnext/main.libsonnet | 31 +- grafonnext/schemas.libsonnet | 8 + grafonnext/schemas/v9.2.3/dashboard.json | 1279 ----------------- ....2.3.libsonnet => static-latest.libsonnet} | 86 +- 9 files changed, 118 insertions(+), 1299 deletions(-) rename {grafonnext => grafonnext-go}/go.mod (94%) rename {grafonnext => grafonnext-go}/go.sum (95%) rename {grafonnext => grafonnext-go}/mkschema.go (90%) delete mode 100644 grafonnext/schemas/v9.2.3/dashboard.json rename grafonnext/{static-v9.2.3.libsonnet => static-latest.libsonnet} (76%) diff --git a/grafonnext/go.mod b/grafonnext-go/go.mod similarity index 94% rename from grafonnext/go.mod rename to grafonnext-go/go.mod index 02cb066f..02103d10 100644 --- a/grafonnext/go.mod +++ b/grafonnext-go/go.mod @@ -1,4 +1,4 @@ -module github.com/grafana/grafonnet-lib/grafonnext +module github.com/grafana/grafonnet-lib/grafonnext-go go 1.19 diff --git a/grafonnext/go.sum b/grafonnext-go/go.sum similarity index 95% rename from grafonnext/go.sum rename to grafonnext-go/go.sum index c5d1a2c9..10113f40 100644 --- a/grafonnext/go.sum +++ b/grafonnext-go/go.sum @@ -16,8 +16,6 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= -github.com/grafana/grafana v1.9.2-0.20221107225804-85217355b416 h1:kuVO9kBoK44gUuIW3KtAGK6H6lnfRxDtLxfix3LgIAk= -github.com/grafana/grafana v1.9.2-0.20221107225804-85217355b416/go.mod h1:qD8jQlBap35uu9oteuokbWbIEDrh1CINpxeXcLOg/Hc= github.com/grafana/grafana v1.9.2-0.20221107230407-93589c483967 h1:xaZRT+bch+reHBaekUzm2BApFBNkt4alBGlleWPpubQ= github.com/grafana/grafana v1.9.2-0.20221107230407-93589c483967/go.mod h1:qD8jQlBap35uu9oteuokbWbIEDrh1CINpxeXcLOg/Hc= github.com/grafana/thema v0.0.0-20221107225215-00ad2949c7bc h1:Icv777/PBaqhLmbSBSDaajDl424cbmh5ee77Du2rUFE= diff --git a/grafonnext/mkschema.go b/grafonnext-go/mkschema.go similarity index 90% rename from grafonnext/mkschema.go rename to grafonnext-go/mkschema.go index 91bba6ba..3eb8c77b 100644 --- a/grafonnext/mkschema.go +++ b/grafonnext-go/mkschema.go @@ -22,7 +22,7 @@ var rt = cuectx.GrafanaThemaRuntime() func main() { // All core kinds first - base := filepath.Join("schemas", grafanaVersion, "core") + base := filepath.Join("..", "grafonnext", "schemas", grafanaVersion, "core") die(os.MkdirAll(base, 0777)) for _, kind := range corekind.NewBase(nil).AllStructured() { @@ -50,7 +50,7 @@ func main() { } b := marshalindent(f) - basecompo := filepath.Join("schemas", grafanaVersion, "composable", strings.ToLower(slot)) + basecompo := filepath.Join("..", "grafonnext", "schemas", grafanaVersion, "composable", strings.ToLower(slot)) path := filepath.Join(basecompo, ptree.RootPlugin().Meta().Id+".json") die(os.MkdirAll(basecompo, 0777)) die(os.WriteFile(path, b, 0644)) diff --git a/grafonnext/Makefile b/grafonnext/Makefile index de448b01..ee28dcbf 100644 --- a/grafonnext/Makefile +++ b/grafonnext/Makefile @@ -1,7 +1,8 @@ ROOT:=$PWD schemas/%: - sh bin/mkschema.sh $* $(abspath schemas) + cd ../grafonnext-go && go run . +# sh bin/mkschema.sh $* $(abspath schemas) schemas.libsonnet: sh bin/mkimport.sh diff --git a/grafonnext/bin/mkimport.sh b/grafonnext/bin/mkimport.sh index 75c41370..f2557ef7 100644 --- a/grafonnext/bin/mkimport.sh +++ b/grafonnext/bin/mkimport.sh @@ -8,7 +8,7 @@ function gen() { for VERSION in $(find schemas/* -maxdepth 0 -type d); do V=$(basename $VERSION) echo "'$V': [" - for FILE in $(find $VERSION/* -maxdepth 0 -type f); do + for FILE in $(find $VERSION/* -type f); do echo "import '$FILE'," done echo "]," diff --git a/grafonnext/main.libsonnet b/grafonnext/main.libsonnet index b93281e2..234c581d 100644 --- a/grafonnext/main.libsonnet +++ b/grafonnext/main.libsonnet @@ -1,23 +1,30 @@ local crdsonnet = import 'github.com/Duologic/crdsonnet/crdsonnet/main.libsonnet'; -local render = import 'github.com/Duologic/crdsonnet/crdsonnet/render.libsonnet'; -local schemas = import 'schemas.libsonnet'; +local renderer = import 'github.com/Duologic/crdsonnet/crdsonnet/render.libsonnet'; +local schemasRaw = import 'schemas.libsonnet'; -function(version='v9.2.3', render='dynamic') +function(version='latest', render='static') - local schema = { + local schemas = { [s.info.title]: s - for s in schemas[version] - }.dashboard; - local component = schema.components.schemas.dashboard; + for s in schemasRaw[version] + }; (if render == 'dynamic' then {} else '// Generated with `make static-%s.libsonnet`\n' % version) - + crdsonnet.fromOpenAPI( - 'dashboard', - component, - schema, - render=render, + + std.foldl( + function(acc, k) + local schema = schemas[k]; + local component = schema.components.schemas[k]; + acc + + crdsonnet.fromOpenAPI( + k, + component, + schema, + render=render, + ), + std.objectFields(schemas), + renderer[render].nilvalue ) + (if render == 'dynamic' then (import 'veneer.libsonnet') diff --git a/grafonnext/schemas.libsonnet b/grafonnext/schemas.libsonnet index 85e83d26..0e52521d 100644 --- a/grafonnext/schemas.libsonnet +++ b/grafonnext/schemas.libsonnet @@ -1,5 +1,13 @@ { // Generated with `make schemas.libsonnet` + latest: [ + import 'schemas/latest/composable/panel/annolist.json', + import 'schemas/latest/composable/panel/text.json', + import 'schemas/latest/composable/panel/news.json', + import 'schemas/latest/composable/panel/dashlist.json', + import 'schemas/latest/core/dashboard.json', + import 'schemas/latest/core/playlist.json', + ], 'v9.2.3': [ import 'schemas/v9.2.3/dashboard.json', ], diff --git a/grafonnext/schemas/v9.2.3/dashboard.json b/grafonnext/schemas/v9.2.3/dashboard.json deleted file mode 100644 index 27f7c641..00000000 --- a/grafonnext/schemas/v9.2.3/dashboard.json +++ /dev/null @@ -1,1279 +0,0 @@ -{ - "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.\nTODO 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\nTODO 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", - "time_options" - ], - "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" - ] - }, - "time_options": { - "description": "TODO docs", - "type": "array", - "items": { - "type": "string" - }, - "default": [ - "5m", - "15m", - "1h", - "6h", - "12h", - "24h", - "2d", - "7d", - "30d" - ] - } - } - }, - "fiscalYearStartMonth": { - "description": "TODO docs", - "type": "integer", - "minimum": 0, - "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\nchanges to said schema.\nTODO 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.RowPanel" - }, - { - "$ref": "#/components/schemas/dashboard.GraphPanel" - }, - { - "$ref": "#/components/schemas/dashboard.HeatmapPanel" - } - ] - } - }, - "templating": { - "type": "object", - "required": [ - "list" - ], - "properties": { - "list": { - "description": "TODO docs", - "type": "array", - "items": { - "$ref": "#/components/schemas/dashboard.VariableModel" - } - } - } - }, - "annotations": { - "type": "object", - "required": [ - "list" - ], - "properties": { - "list": { - "description": "TODO docs", - "type": "array", - "items": { - "$ref": "#/components/schemas/dashboard.AnnotationQuery" - } - } - } - }, - "links": { - "description": "TODO docs", - "type": "array", - "items": { - "$ref": "#/components/schemas/dashboard.DashboardLink" - } - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.AnnotationQuery": { - "description": "TODO docs\nFROM: 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" - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.DashboardCursorSync": { - "description": "0 for no shared crosshair or tooltip (default).\n1 for shared crosshair.\n2 for shared crosshair AND shared tooltip.", - "type": "integer", - "enum": [ - 0, - 1, - 2 - ], - "default": 0, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.DashboardLink": { - "description": "FROM public/app/features/dashboard/state/DashboardModels.ts - ish\nTODO 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 - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.DashboardLinkType": { - "description": "TODO docs", - "type": "string", - "enum": [ - "link", - "dashboards" - ], - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "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" - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.FieldColorModeId": { - "description": "TODO docs", - "type": "string", - "enum": [ - "thresholds", - "palette-classic", - "palette-saturated", - "continuous-GrYlRd", - "fixed" - ], - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.FieldColorSeriesByMode": { - "description": "TODO docs", - "type": "string", - "enum": [ - "min", - "max", - "last" - ], - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.GraphPanel": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "description": "Support for legacy graph and heatmap panels.", - "type": "string", - "enum": [ - "graph" - ] - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.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" - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.HeatmapPanel": { - "type": "object", - "required": [ - "type" - ], - "properties": { - "type": { - "type": "string", - "enum": [ - "heatmap" - ] - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.Panel": { - "description": "Dashboard panels. Panels are canonically defined inline\nbecause they share a version timeline with the dashboard\nschema; 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": { - "$ref": "#/components/schemas/dashboard.GridPos" - }, - "links": { - "description": "Panel links.\nTODO 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.\n\"h\" for horizontal, \"v\" for vertical.", - "type": "string", - "enum": [ - "h", - "v" - ], - "default": "h" - }, - "maxDataPoints": { - "description": "TODO docs", - "type": "number" - }, - "thresholds": { - "description": "TODO docs - seems to be an old field from old dashboard alerts?", - "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\nTODO tighter constraint", - "type": "string" - }, - "timeFrom": { - "description": "TODO docs\nTODO tighter constraint", - "type": "string" - }, - "timeShift": { - "description": "TODO docs\nTODO tighter constraint", - "type": "string" - }, - "options": { - "description": "options is specified by the PanelOptions field in panel\nplugin 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\nWhen 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,\nThis will default to `${frame.meta.path}/${field.name}\n\nWhen defined, this value can be used as an identifier within the datasource scope, and\nmay 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\n\nTODO this one corresponds to a complex type with\ngenerics on the typescript side. Ouch. Will\neither need special care, or we'll just need to\naccept a very loosely specified schema. It's very\nunlikely we'll be able to translate cue to\ntypescript generics in the general case, though\nthis 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\nin 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": {} - } - } - } - } - } - } - } - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "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": { - "$ref": "#/components/schemas/dashboard.GridPos" - }, - "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": { - "$ref": "#/components/schemas/dashboard.GridPos" - }, - "links": { - "description": "Panel links.\nTODO 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.\n\"h\" for horizontal, \"v\" for vertical.", - "type": "string", - "enum": [ - "h", - "v" - ], - "default": "h" - }, - "maxDataPoints": { - "description": "TODO docs", - "type": "number" - }, - "thresholds": { - "description": "TODO docs - seems to be an old field from old dashboard alerts?", - "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\nTODO tighter constraint", - "type": "string" - }, - "timeFrom": { - "description": "TODO docs\nTODO tighter constraint", - "type": "string" - }, - "timeShift": { - "description": "TODO docs\nTODO tighter constraint", - "type": "string" - }, - "options": { - "description": "options is specified by the PanelOptions field in panel\nplugin 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\nWhen 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,\nThis will default to `${frame.meta.path}/${field.name}\n\nWhen defined, this value can be used as an identifier within the datasource scope, and\nmay 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\n\nTODO this one corresponds to a complex type with\ngenerics on the typescript side. Ouch. Will\neither need special care, or we'll just need to\naccept a very loosely specified schema. It's very\nunlikely we'll be able to translate cue to\ntypescript generics in the general case, though\nthis 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\nin 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" - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.Target": { - "description": "Schema for panel targets is specified by datasource\nplugins. We use a placeholder definition, which the Go\nschema loader either left open/as-is with the Base\nvariant of the Dashboard and Panel families, or filled\nwith types derived from plugins in the Instance variant.\nWhen working directly from CUE, importers can extend this\ntype directly to achieve the same effect.", - "type": "object", - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.Threshold": { - "description": "TODO docs", - "type": "object", - "required": [ - "color" - ], - "properties": { - "value": { - "description": "TODO docs\nFIXME 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\nTODO are the values here enumerable into a disjunction?\nSome seem to be listed in typescript comment", - "type": "string" - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "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\nFIXME 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\nTODO are the values here enumerable into a disjunction?\nSome seem to be listed in typescript comment", - "type": "string" - } - } - } - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.ThresholdsMode": { - "type": "string", - "enum": [ - "absolute", - "percentage" - ], - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.Transformation": { - "description": "TODO docs\nFIXME 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" - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.VariableModel": { - "description": "FROM: packages/grafana-data/src/types/templateVars.ts\nTODO docs\nTODO what about what's in public/app/features/types.ts?\nTODO 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" - } - }, - "$schema": "http://json-schema.org/draft-04/schema#" - }, - "dashboard.VariableType": { - "description": "FROM: packages/grafana-data/src/types/templateVars.ts\nTODO docs\nTODO this implies some wider pattern/discriminated union, probably?", - "type": "string", - "enum": [ - "query", - "adhoc", - "constant", - "datasource", - "interval", - "textbox", - "custom", - "system" - ], - "$schema": "http://json-schema.org/draft-04/schema#" - } - } - } -} \ No newline at end of file diff --git a/grafonnext/static-v9.2.3.libsonnet b/grafonnext/static-latest.libsonnet similarity index 76% rename from grafonnext/static-v9.2.3.libsonnet rename to grafonnext/static-latest.libsonnet index 05df6cb1..95d84c33 100644 --- a/grafonnext/static-v9.2.3.libsonnet +++ b/grafonnext/static-latest.libsonnet @@ -1,5 +1,23 @@ -// Generated with `make static-v9.2.3.libsonnet` +// Generated with `make static-latest.libsonnet` { + annolist+: { + withPanelOptions(value): { PanelOptions: value }, + withPanelOptionsMixin(value): { PanelOptions+: value }, + PanelOptions+: { + withLimit(value=10): { PanelOptions+: { limit: value } }, + withNavigateAfter(value='10m'): { PanelOptions+: { navigateAfter: value } }, + withNavigateBefore(value='10m'): { PanelOptions+: { navigateBefore: value } }, + withNavigateToPanel(value=true): { PanelOptions+: { navigateToPanel: value } }, + withOnlyFromThisDashboard(value=false): { PanelOptions+: { onlyFromThisDashboard: value } }, + withOnlyInTimeRange(value=false): { PanelOptions+: { onlyInTimeRange: value } }, + withShowTags(value=true): { PanelOptions+: { showTags: value } }, + withShowTime(value=true): { PanelOptions+: { showTime: value } }, + withShowUser(value=true): { PanelOptions+: { showUser: value } }, + withTags(value): { PanelOptions+: { tags: if std.isArray(value) then value else [value] } }, + withTagsMixin(value): { PanelOptions+: { tags+: if std.isArray(value) then value else [value] } }, + }, + }, +} { dashboard+: { withAnnotations(value): { annotations: value }, withAnnotationsMixin(value): { annotations+: value }, @@ -22,6 +40,13 @@ withShowIn(value=0): { annotations+: { showIn: value } }, withTarget(value): { annotations+: { target: value } }, withTargetMixin(value): { annotations+: { target+: value } }, + target+: { + withLimit(value): { annotations+: { target+: { limit: value } } }, + withMatchAny(value=true): { annotations+: { target+: { matchAny: value } } }, + withTags(value): { annotations+: { target+: { tags: if std.isArray(value) then value else [value] } } }, + withTagsMixin(value): { annotations+: { target+: { tags+: if std.isArray(value) then value else [value] } } }, + withType(value): { annotations+: { target+: { type: value } } }, + }, withType(value='dashboard'): { annotations+: { type: value } }, }, }, @@ -242,5 +267,64 @@ withVersion(value): { version: value }, withWeekStart(value): { weekStart: value }, }, +} { + dashlist+: { + withPanelLayout(value): { PanelLayout: value }, + withPanelOptions(value): { PanelOptions: value }, + withPanelOptionsMixin(value): { PanelOptions+: value }, + PanelOptions+: { + withFolderId(value): { PanelOptions+: { folderId: value } }, + withLayout(value): { PanelOptions+: { layout: value } }, + withMaxItems(value=10): { PanelOptions+: { maxItems: value } }, + withQuery(value=''): { PanelOptions+: { query: value } }, + withShowHeadings(value=true): { PanelOptions+: { showHeadings: value } }, + withShowRecentlyViewed(value=false): { PanelOptions+: { showRecentlyViewed: value } }, + withShowSearch(value=false): { PanelOptions+: { showSearch: value } }, + withShowStarred(value=true): { PanelOptions+: { showStarred: value } }, + withTags(value): { PanelOptions+: { tags: if std.isArray(value) then value else [value] } }, + withTagsMixin(value): { PanelOptions+: { tags+: if std.isArray(value) then value else [value] } }, + }, + }, +} { + news+: { + withPanelOptions(value): { PanelOptions: value }, + withPanelOptionsMixin(value): { PanelOptions+: value }, + PanelOptions+: { + withFeedUrl(value): { PanelOptions+: { feedUrl: value } }, + withShowImage(value=true): { PanelOptions+: { showImage: value } }, + }, + }, +} { + playlist+: { + withInterval(value='5m'): { interval: value }, + withItems(value): { items: if std.isArray(value) then value else [value] }, + withItemsMixin(value): { items+: if std.isArray(value) then value else [value] }, + items+: { + withTitle(value): { title: value }, + withType(value): { type: value }, + withValue(value): { value: value }, + }, + withName(value): { name: value }, + withUid(value): { uid: value }, + }, +} { + text+: { + withCodeLanguage(value='plaintext'): { CodeLanguage: value }, + withCodeOptions(value): { CodeOptions: value }, + withCodeOptionsMixin(value): { CodeOptions+: value }, + CodeOptions+: { + withLanguage(value='plaintext'): { CodeOptions+: { language: value } }, + withShowLineNumbers(value=false): { CodeOptions+: { showLineNumbers: value } }, + withShowMiniMap(value=false): { CodeOptions+: { showMiniMap: value } }, + }, + withPanelOptions(value): { PanelOptions: value }, + withPanelOptionsMixin(value): { PanelOptions+: value }, + PanelOptions+: { + withCode(value): { PanelOptions+: { code: value } }, + withContent(value='# Title\n\nFor markdown syntax help: [commonmark.org/help](https://commonmark.org/help/)'): { PanelOptions+: { content: value } }, + withMode(value='markdown'): { PanelOptions+: { mode: value } }, + }, + withTextMode(value): { TextMode: value }, + }, } + (import 'veneer.libsonnet') From 07326957864e226274da89050f383d6cad76620b Mon Sep 17 00:00:00 2001 From: Duologic Date: Wed, 9 Nov 2022 21:23:33 +0100 Subject: [PATCH 6/8] fix example --- grafonnext/example.libsonnet | 2 +- grafonnext/main.libsonnet | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/grafonnext/example.libsonnet b/grafonnext/example.libsonnet index 0283b77c..753778fa 100644 --- a/grafonnext/example.libsonnet +++ b/grafonnext/example.libsonnet @@ -1,4 +1,4 @@ -local grafonnet = (import './main.libsonnet')('v9.2.3'); +local grafonnet = (import './main.libsonnet')('latest'); local dashboard = grafonnet.dashboard; local panel = grafonnet.dashboard.panels.panel; diff --git a/grafonnext/main.libsonnet b/grafonnext/main.libsonnet index 234c581d..2b7a0bff 100644 --- a/grafonnext/main.libsonnet +++ b/grafonnext/main.libsonnet @@ -2,7 +2,7 @@ local crdsonnet = import 'github.com/Duologic/crdsonnet/crdsonnet/main.libsonnet local renderer = import 'github.com/Duologic/crdsonnet/crdsonnet/render.libsonnet'; local schemasRaw = import 'schemas.libsonnet'; -function(version='latest', render='static') +function(version='latest', render='dynamic') local schemas = { [s.info.title]: s From 8b5616bb5e9f35a956ba88ed17556ff22428b60b Mon Sep 17 00:00:00 2001 From: Duologic Date: Wed, 9 Nov 2022 21:24:53 +0100 Subject: [PATCH 7/8] make schemas.libsonnet --- grafonnext/schemas.libsonnet | 3 --- 1 file changed, 3 deletions(-) diff --git a/grafonnext/schemas.libsonnet b/grafonnext/schemas.libsonnet index 0e52521d..b80de1e7 100644 --- a/grafonnext/schemas.libsonnet +++ b/grafonnext/schemas.libsonnet @@ -8,7 +8,4 @@ import 'schemas/latest/core/dashboard.json', import 'schemas/latest/core/playlist.json', ], - 'v9.2.3': [ - import 'schemas/v9.2.3/dashboard.json', - ], } From 72533fb25b3dde037e4d4a6c5b0c3334ce0fcbf1 Mon Sep 17 00:00:00 2001 From: Duologic Date: Wed, 9 Nov 2022 22:08:53 +0100 Subject: [PATCH 8/8] fix: workaround bug in panel schemas --- grafonnext/main.libsonnet | 14 +++++- grafonnext/static-latest.libsonnet | 78 ++++++++++-------------------- 2 files changed, 39 insertions(+), 53 deletions(-) diff --git a/grafonnext/main.libsonnet b/grafonnext/main.libsonnet index 2b7a0bff..9117075b 100644 --- a/grafonnext/main.libsonnet +++ b/grafonnext/main.libsonnet @@ -5,7 +5,19 @@ local schemasRaw = import 'schemas.libsonnet'; function(version='latest', render='dynamic') local schemas = { - [s.info.title]: s + [s.info.title]: + s + + (if 'PanelOptions' in s.components.schemas[s.info.title].properties + then { components+: { schemas+: { + [s.info.title]: { '$ref': '#/components/schemas/PanelOptions' }, + PanelOptions: s.components.schemas[s.info.title].properties.PanelOptions, + } } } + else {}) + + (if 'PanelLayout' in s.components.schemas[s.info.title].properties + then { components+: { schemas+: { + PanelLayout: s.components.schemas[s.info.title].properties.PanelLayout, + } } } + else {}) for s in schemasRaw[version] }; diff --git a/grafonnext/static-latest.libsonnet b/grafonnext/static-latest.libsonnet index 95d84c33..b30a533f 100644 --- a/grafonnext/static-latest.libsonnet +++ b/grafonnext/static-latest.libsonnet @@ -1,21 +1,17 @@ // Generated with `make static-latest.libsonnet` { annolist+: { - withPanelOptions(value): { PanelOptions: value }, - withPanelOptionsMixin(value): { PanelOptions+: value }, - PanelOptions+: { - withLimit(value=10): { PanelOptions+: { limit: value } }, - withNavigateAfter(value='10m'): { PanelOptions+: { navigateAfter: value } }, - withNavigateBefore(value='10m'): { PanelOptions+: { navigateBefore: value } }, - withNavigateToPanel(value=true): { PanelOptions+: { navigateToPanel: value } }, - withOnlyFromThisDashboard(value=false): { PanelOptions+: { onlyFromThisDashboard: value } }, - withOnlyInTimeRange(value=false): { PanelOptions+: { onlyInTimeRange: value } }, - withShowTags(value=true): { PanelOptions+: { showTags: value } }, - withShowTime(value=true): { PanelOptions+: { showTime: value } }, - withShowUser(value=true): { PanelOptions+: { showUser: value } }, - withTags(value): { PanelOptions+: { tags: if std.isArray(value) then value else [value] } }, - withTagsMixin(value): { PanelOptions+: { tags+: if std.isArray(value) then value else [value] } }, - }, + withLimit(value=10): { limit: value }, + withNavigateAfter(value='10m'): { navigateAfter: value }, + withNavigateBefore(value='10m'): { navigateBefore: value }, + withNavigateToPanel(value=true): { navigateToPanel: value }, + withOnlyFromThisDashboard(value=false): { onlyFromThisDashboard: value }, + withOnlyInTimeRange(value=false): { onlyInTimeRange: value }, + withShowTags(value=true): { showTags: value }, + withShowTime(value=true): { showTime: value }, + withShowUser(value=true): { showUser: value }, + withTags(value): { tags: if std.isArray(value) then value else [value] }, + withTagsMixin(value): { tags+: if std.isArray(value) then value else [value] }, }, } { dashboard+: { @@ -269,30 +265,21 @@ }, } { dashlist+: { - withPanelLayout(value): { PanelLayout: value }, - withPanelOptions(value): { PanelOptions: value }, - withPanelOptionsMixin(value): { PanelOptions+: value }, - PanelOptions+: { - withFolderId(value): { PanelOptions+: { folderId: value } }, - withLayout(value): { PanelOptions+: { layout: value } }, - withMaxItems(value=10): { PanelOptions+: { maxItems: value } }, - withQuery(value=''): { PanelOptions+: { query: value } }, - withShowHeadings(value=true): { PanelOptions+: { showHeadings: value } }, - withShowRecentlyViewed(value=false): { PanelOptions+: { showRecentlyViewed: value } }, - withShowSearch(value=false): { PanelOptions+: { showSearch: value } }, - withShowStarred(value=true): { PanelOptions+: { showStarred: value } }, - withTags(value): { PanelOptions+: { tags: if std.isArray(value) then value else [value] } }, - withTagsMixin(value): { PanelOptions+: { tags+: if std.isArray(value) then value else [value] } }, - }, + withFolderId(value): { folderId: value }, + withLayout(value): { layout: value }, + withMaxItems(value=10): { maxItems: value }, + withQuery(value=''): { query: value }, + withShowHeadings(value=true): { showHeadings: value }, + withShowRecentlyViewed(value=false): { showRecentlyViewed: value }, + withShowSearch(value=false): { showSearch: value }, + withShowStarred(value=true): { showStarred: value }, + withTags(value): { tags: if std.isArray(value) then value else [value] }, + withTagsMixin(value): { tags+: if std.isArray(value) then value else [value] }, }, } { news+: { - withPanelOptions(value): { PanelOptions: value }, - withPanelOptionsMixin(value): { PanelOptions+: value }, - PanelOptions+: { - withFeedUrl(value): { PanelOptions+: { feedUrl: value } }, - withShowImage(value=true): { PanelOptions+: { showImage: value } }, - }, + withFeedUrl(value): { feedUrl: value }, + withShowImage(value=true): { showImage: value }, }, } { playlist+: { @@ -309,22 +296,9 @@ }, } { text+: { - withCodeLanguage(value='plaintext'): { CodeLanguage: value }, - withCodeOptions(value): { CodeOptions: value }, - withCodeOptionsMixin(value): { CodeOptions+: value }, - CodeOptions+: { - withLanguage(value='plaintext'): { CodeOptions+: { language: value } }, - withShowLineNumbers(value=false): { CodeOptions+: { showLineNumbers: value } }, - withShowMiniMap(value=false): { CodeOptions+: { showMiniMap: value } }, - }, - withPanelOptions(value): { PanelOptions: value }, - withPanelOptionsMixin(value): { PanelOptions+: value }, - PanelOptions+: { - withCode(value): { PanelOptions+: { code: value } }, - withContent(value='# Title\n\nFor markdown syntax help: [commonmark.org/help](https://commonmark.org/help/)'): { PanelOptions+: { content: value } }, - withMode(value='markdown'): { PanelOptions+: { mode: value } }, - }, - withTextMode(value): { TextMode: value }, + withCode(value): { code: value }, + withContent(value='# Title\n\nFor markdown syntax help: [commonmark.org/help](https://commonmark.org/help/)'): { content: value }, + withMode(value='markdown'): { mode: value }, }, } + (import 'veneer.libsonnet')