databricks-cli/bundle/internal/schema/main.go

110 lines
2.9 KiB
Go
Raw Normal View History

2024-08-26 18:16:45 +00:00
package main
import (
"encoding/json"
"fmt"
"log"
"os"
"reflect"
"github.com/databricks/cli/bundle/config"
2024-08-27 11:10:13 +00:00
"github.com/databricks/cli/bundle/config/variable"
2024-08-26 18:16:45 +00:00
"github.com/databricks/cli/libs/jsonschema"
)
func interpolationPattern(s string) string {
2024-09-10 13:27:39 +00:00
return fmt.Sprintf(`\$\{(%s(\.[a-zA-Z]+([-_]?[a-zA-Z0-9]+)*(\[[0-9]+\])*)+)\}`, s)
2024-08-26 18:16:45 +00:00
}
2024-08-27 11:10:13 +00:00
func addInterpolationPatterns(typ reflect.Type, s jsonschema.Schema) jsonschema.Schema {
if typ == reflect.TypeOf(config.Root{}) || typ == reflect.TypeOf(variable.Variable{}) {
return s
}
2024-09-04 14:18:34 +00:00
// The variables block in a target override allows for directly specifying
2024-09-05 11:37:45 +00:00
// the value of the variable.
2024-09-04 15:42:02 +00:00
if typ == reflect.TypeOf(variable.TargetVariable{}) {
2024-09-04 14:18:34 +00:00
return jsonschema.Schema{
2024-09-05 11:37:45 +00:00
AnyOf: []jsonschema.Schema{
// We keep the original schema so that autocomplete suggestions
// continue to work.
s,
// All values are valid for a variable value, be it primitive types
// like string/bool or complex ones like objects/arrays. Thus we override
// the schema to allow all valid JSON values.
{},
2024-09-04 14:18:34 +00:00
},
}
}
2024-08-26 18:16:45 +00:00
switch s.Type {
case jsonschema.ArrayType, jsonschema.ObjectType:
// arrays and objects can have complex variable values specified.
return jsonschema.Schema{
2024-09-06 13:18:31 +00:00
AnyOf: []jsonschema.Schema{
s,
{
Type: jsonschema.StringType,
Pattern: interpolationPattern("var"),
}},
2024-08-26 18:16:45 +00:00
}
case jsonschema.IntegerType, jsonschema.NumberType, jsonschema.BooleanType:
2024-08-26 18:16:45 +00:00
// primitives can have variable values, or references like ${bundle.xyz}
// or ${workspace.xyz}
return jsonschema.Schema{
2024-09-06 13:18:31 +00:00
AnyOf: []jsonschema.Schema{
s,
2024-08-27 11:10:13 +00:00
{Type: jsonschema.StringType, Pattern: interpolationPattern("resources")},
2024-08-26 18:16:45 +00:00
{Type: jsonschema.StringType, Pattern: interpolationPattern("bundle")},
{Type: jsonschema.StringType, Pattern: interpolationPattern("workspace")},
2024-09-05 12:15:08 +00:00
{Type: jsonschema.StringType, Pattern: interpolationPattern("artifacts")},
2024-08-26 18:16:45 +00:00
{Type: jsonschema.StringType, Pattern: interpolationPattern("var")},
},
}
default:
return s
}
}
func main() {
if len(os.Args) != 2 {
fmt.Println("Usage: go run main.go <output-file>")
os.Exit(1)
}
// Output file, where the generated JSON schema will be written to.
outputFile := os.Args[1]
// Input file, the databricks openapi spec.
inputFile := os.Getenv("DATABRICKS_OPENAPI_SPEC")
if inputFile == "" {
log.Fatal("DATABRICKS_OPENAPI_SPEC environment variable not set")
}
p, err := newParser(inputFile)
if err != nil {
log.Fatal(err)
}
// Generate the JSON schema from the bundle Go struct.
s, err := jsonschema.FromType(reflect.TypeOf(config.Root{}), []func(reflect.Type, jsonschema.Schema) jsonschema.Schema{
p.addDescriptions,
p.addEnums,
addInterpolationPatterns,
})
if err != nil {
log.Fatal(err)
}
b, err := json.MarshalIndent(s, "", " ")
if err != nil {
log.Fatal(err)
}
// Write the schema descriptions to the output file.
err = os.WriteFile(outputFile, b, 0644)
if err != nil {
log.Fatal(err)
}
}