Commit 9691af83 by Chris Trott Committed by GitHub

DashboardSchemas: OpenAPI Schema Generation (#30242)

* Go program to output openapi

* Fix number type syntax

Resolves error: 'unsupported op for number &'

* Render just the schemas

* Use args as entrypoints and add test

* Update README, tidy go.mod
parent b1debc9c
...@@ -20,7 +20,7 @@ package main ...@@ -20,7 +20,7 @@ package main
// 0 for no shared crosshair or tooltip (default). // 0 for no shared crosshair or tooltip (default).
// 1 for shared crosshair. // 1 for shared crosshair.
// 2 for shared crosshair AND shared tooltip. // 2 for shared crosshair AND shared tooltip.
graphTooltip: int & >=0 & <=2 | *0 graphTooltip: int >= 0 <= 2 | *0
// Time range for dashboard, e.g. last 6 hours, last 7 days, etc // Time range for dashboard, e.g. last 6 hours, last 7 days, etc
time?: { time?: {
from: string | *"now-6h" from: string | *"now-6h"
......
...@@ -63,9 +63,24 @@ be a base schema for panels. `#Gauge` extends `#panel` with the following: ...@@ -63,9 +63,24 @@ be a base schema for panels. `#Gauge` extends `#panel` with the following:
## Exporting OpenAPI ## Exporting OpenAPI
[OpenAPI](https://swagger.io/specification/) schemas can be exported from these CUE sources. Use the `cue` [OpenAPI](https://www.openapis.org/) schemas can be exported from these CUE
command as follows, to generate OpenAPI JSON to stdout: sources.
### Command Line
While you can use `cue export` to output OpenAPI documents, it does not expand
references which makes the output unusable.
```
cue export --out openapi -o - ./...
```
### Using Go
You need to use Go to generate useable OpenAPI schemas. This directory contains
a Go program that will output just the OpenAPI schemas for one or many Cue
packages.
``` ```
cue export --out openapi -o - ./dashboard-schemas/... go run . <entrypoint> ...
``` ```
module github.com/grafana/grafana/dashboard-schemas
go 1.15
require cuelang.org/go v0.2.2
package main
import (
"fmt"
"log"
"os"
"cuelang.org/go/cue"
"cuelang.org/go/cue/load"
"cuelang.org/go/encoding/openapi"
)
func main() {
b, err := openAPISchemas(os.Args[1:])
if err != nil {
log.Fatal(err)
}
fmt.Println(string(b))
}
// openAPISchemas returns OpenAPI schema JSON of the Cue entrypoints passed to
// it. It is not a valid OpenAPI document - just the schemas.
func openAPISchemas(entrypoints []string) ([]byte, error) {
var r cue.Runtime
cfg := openapi.Config{
ExpandReferences: true,
}
bis := load.Instances(entrypoints, nil)
// collect all schemas
var pairs []openapi.KeyValue
for _, bi := range bis {
if bi.Err != nil {
return nil, bi.Err
}
inst, err := r.Build(bi)
if err != nil {
return nil, err
}
om, err := cfg.Schemas(inst)
if err != nil {
return nil, err
}
pairs = append(pairs, om.Pairs()...)
}
// add all schemas to new ordered map
om := openapi.OrderedMap{}
om.SetAll(pairs)
j, err := om.MarshalJSON()
if err != nil {
return nil, err
}
return j, nil
}
package main
import (
"encoding/json"
"testing"
)
func TestOpenAPISchemas(t *testing.T) {
tests := map[string]struct {
entrypoints []string
}{
"All packages": {
entrypoints: []string{"./..."},
},
"One package": {
entrypoints: []string{"./panels"},
},
"Many packags": {
entrypoints: []string{
"./panels",
"./targets",
"./transformations",
"./variables",
},
},
}
for testName, test := range tests {
t.Logf("Running test case %s...", testName)
j, err := openAPISchemas(test.entrypoints)
if err != nil {
t.Fatal(err)
}
// We don't want to validate the JSON content since it's expected to change
// often. Only that it is valid JSON by unmarshalling it.
var iface interface{}
err = json.Unmarshal(j, &iface)
if err != nil {
t.Fatal(err)
}
}
}
...@@ -20,10 +20,10 @@ package panels ...@@ -20,10 +20,10 @@ package panels
overrides: [..._override] overrides: [..._override]
} }
// Amount of color fill for a series. Expects a value between 0 and 1. // Amount of color fill for a series. Expects a value between 0 and 1.
fill: number & >=0 & <=1 | *1 fill: number >= 0 <= 1 | *1
// Degree of gradient on the area fill. 0 is no gradient, 10 is a steep // Degree of gradient on the area fill. 0 is no gradient, 10 is a steep
// gradient. // gradient.
fillGradient: int & >=0 & <=10 | *0 fillGradient: int >= 0 <= 10 | *0
// Hide the series. // Hide the series.
hiddenSeries: bool | *false hiddenSeries: bool | *false
// Lengend options. // Lengend options.
...@@ -133,7 +133,7 @@ package panels ...@@ -133,7 +133,7 @@ package panels
// and in increasing order, with the lowest value at the top of the list. // and in increasing order, with the lowest value at the top of the list.
// * 2 (decreasing) - The series in the hover tooltip are sorted by value // * 2 (decreasing) - The series in the hover tooltip are sorted by value
// and in decreasing order, with the highest value at the top of the list. // and in decreasing order, with the highest value at the top of the list.
sort: int & >=0 & <=2 | *2 sort: int >= 0 <= 2 | *2
// Value type. // Value type.
value_type: string | *"individual" value_type: string | *"individual"
} }
......
...@@ -2,11 +2,11 @@ package panels ...@@ -2,11 +2,11 @@ package panels
_gridPos: { _gridPos: {
// Panel height. // Panel height.
h: int & >0 | *9 h?: int > 0 | *9
// Panel width. // Panel width.
w: int & >0 <= 24 | 12 w?: int > 0 <= 24 | *12
// Panel x position. // Panel x position.
x: int & >0 < 24 x?: int >= 0 < 24 | *0
// Panel y position. // Panel y position.
y: int & >0 y?: int >= 0 | *0
} }
...@@ -20,7 +20,7 @@ package variables ...@@ -20,7 +20,7 @@ package variables
// * 4 - Numerical (desc). // * 4 - Numerical (desc).
// * 5 - Alphabetical (case-insensitive, asc). // * 5 - Alphabetical (case-insensitive, asc).
// * 6 - Alphabetical (case-insensitive, desc). // * 6 - Alphabetical (case-insensitive, desc).
sort: int & >=0 & <=6 | *0 sort: int >= 0 <= 6 | *0
tagValuesQuery?: string tagValuesQuery?: string
tags: [...string] | *[] tags: [...string] | *[]
tagsQuery?: string tagsQuery?: string
......
...@@ -11,7 +11,7 @@ _variable: { ...@@ -11,7 +11,7 @@ _variable: {
// * 0 - Show all. // * 0 - Show all.
// * 1 - Hide label. // * 1 - Hide label.
// * 2 - Hide label and variable. // * 2 - Hide label and variable.
hide: int & >=0 & <=2 | *0 hide: int >= 0 <= 2 | *0
// Enable include all option. // Enable include all option.
includeAll: bool | *false includeAll: bool | *false
// When includeAll is enabled, this sets its value. // When includeAll is enabled, this sets its value.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment