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  }