github.com/databricks/cli@v0.203.0/bundle/schema/docs.go (about) 1 package schema 2 3 import ( 4 _ "embed" 5 "encoding/json" 6 "fmt" 7 "os" 8 "reflect" 9 10 "github.com/databricks/cli/bundle/config" 11 "github.com/databricks/cli/libs/jsonschema" 12 "github.com/databricks/databricks-sdk-go/openapi" 13 ) 14 15 // A subset of Schema struct 16 type Docs struct { 17 Description string `json:"description"` 18 Properties map[string]*Docs `json:"properties,omitempty"` 19 Items *Docs `json:"items,omitempty"` 20 AdditionalProperties *Docs `json:"additionalproperties,omitempty"` 21 } 22 23 //go:embed docs/bundle_descriptions.json 24 var bundleDocs []byte 25 26 func BundleDocs(openapiSpecPath string) (*Docs, error) { 27 docs, err := initializeBundleDocs() 28 if err != nil { 29 return nil, err 30 } 31 if openapiSpecPath != "" { 32 openapiSpec, err := os.ReadFile(openapiSpecPath) 33 if err != nil { 34 return nil, err 35 } 36 spec := &openapi.Specification{} 37 err = json.Unmarshal(openapiSpec, spec) 38 if err != nil { 39 return nil, err 40 } 41 openapiReader := &OpenapiReader{ 42 OpenapiSpec: spec, 43 Memo: make(map[string]*jsonschema.Schema), 44 } 45 resourcesDocs, err := openapiReader.ResourcesDocs() 46 if err != nil { 47 return nil, err 48 } 49 resourceSchema, err := New(reflect.TypeOf(config.Resources{}), resourcesDocs) 50 if err != nil { 51 return nil, err 52 } 53 docs.Properties["resources"] = schemaToDocs(resourceSchema) 54 } 55 docs.refreshEnvironmentsDocs() 56 return docs, nil 57 } 58 59 func (docs *Docs) refreshEnvironmentsDocs() error { 60 environmentsDocs, ok := docs.Properties["environments"] 61 if !ok || environmentsDocs.AdditionalProperties == nil || 62 environmentsDocs.AdditionalProperties.Properties == nil { 63 return fmt.Errorf("invalid environments descriptions") 64 } 65 environmentProperties := environmentsDocs.AdditionalProperties.Properties 66 propertiesToCopy := []string{"artifacts", "bundle", "resources", "workspace"} 67 for _, p := range propertiesToCopy { 68 environmentProperties[p] = docs.Properties[p] 69 } 70 return nil 71 } 72 73 func initializeBundleDocs() (*Docs, error) { 74 // load embedded descriptions 75 embedded := Docs{} 76 err := json.Unmarshal(bundleDocs, &embedded) 77 if err != nil { 78 return nil, err 79 } 80 // generate schema with the embedded descriptions 81 schema, err := New(reflect.TypeOf(config.Root{}), &embedded) 82 if err != nil { 83 return nil, err 84 } 85 // converting the schema back to docs. This creates empty descriptions 86 // for any properties that were missing in the embedded descriptions 87 docs := schemaToDocs(schema) 88 return docs, nil 89 } 90 91 // *Docs are a subset of *Schema, this function selects that subset 92 func schemaToDocs(jsonSchema *jsonschema.Schema) *Docs { 93 // terminate recursion if schema is nil 94 if jsonSchema == nil { 95 return nil 96 } 97 docs := &Docs{ 98 Description: jsonSchema.Description, 99 } 100 if len(jsonSchema.Properties) > 0 { 101 docs.Properties = make(map[string]*Docs) 102 } 103 for k, v := range jsonSchema.Properties { 104 docs.Properties[k] = schemaToDocs(v) 105 } 106 docs.Items = schemaToDocs(jsonSchema.Items) 107 if additionalProperties, ok := jsonSchema.AdditionalProperties.(*jsonschema.Schema); ok { 108 docs.AdditionalProperties = schemaToDocs(additionalProperties) 109 } 110 return docs 111 }