cli/bpmetadata/schema/generate.go (47 lines of code) (raw):
package main
import (
"encoding/json"
"os"
"path"
"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/cli/bpmetadata"
"github.com/invopop/jsonschema"
)
const schemaFileName = "gcp-blueprint-metadata.json"
// generateSchema creates a JSON Schema based on the types
// defined in the type BlueprintMetadata and it's recursive
// children. The generated schema will be used to validate
// all metadata files for consistency and will be uploaded
// to https://www.schemastore.org/ to provide IntelliSense
// VSCode for authors manually authoring the metadata.
func generateSchemaFile(o, wdPath string) error {
sData, err := GenerateSchema()
if err != nil {
return err
}
sData = append(sData, []byte("\n")...)
// check if the provided output path is relative
if !path.IsAbs(o) {
o = path.Join(wdPath, o)
}
err = os.WriteFile(path.Join(o, schemaFileName), sData, 0644)
if err != nil {
return err
}
Log.Info("generated JSON schema for BlueprintMetadata", "path", path.Join(o, schemaFileName))
return nil
}
func GenerateSchema() ([]byte, error) {
r := &jsonschema.Reflector{}
s := r.Reflect(&bpmetadata.BlueprintMetadata{})
s.Version = "http://json-schema.org/draft-07/schema#"
// defaultValue was defined as interface{} and has changed to
// Value type with proto definitions. To keep backwards
// compatibility for schema validation, this is being set to
// true i.e. it's presence is validated regardless of type.
vDef, defExists := s.Definitions["BlueprintVariable"]
if defExists {
vDef.Properties.Set("defaultValue", jsonschema.TrueSchema)
}
// JSON schema seems to infer google.protobuf.Value as object type
// so we use the same workaround as above.
oDef, defExists := s.Definitions["BlueprintOutput"]
if defExists {
oDef.Properties.Set("type", jsonschema.TrueSchema)
}
altDefaultDef, defExists := s.Definitions["DisplayVariable_AlternateDefault"]
if defExists {
altDefaultDef.Properties.Set("value", jsonschema.TrueSchema)
}
sData, err := json.MarshalIndent(s, "", " ")
if err != nil {
return nil, err
}
return sData, nil
}