mirror of https://github.com/databricks/cli.git
self pass 1
This commit is contained in:
parent
4141f4ea34
commit
cb8d6a9f60
|
@ -40,14 +40,16 @@ func newParser(path string) (*openapiParser, error) {
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function finds any JSON schemas that were defined in the OpenAPI spec
|
// This function checks if the input type:
|
||||||
// that correspond to the given Go SDK type. It looks both at the type itself
|
// 1. Is a Databricks Go SDK type.
|
||||||
// and any embedded types within it.
|
// 2. Has a Databricks Go SDK type embedded in it.
|
||||||
|
//
|
||||||
|
// If the above conditions are met, the function returns the JSON schema
|
||||||
|
// corresponding to the Databricks Go SDK type from the OpenAPI spec.
|
||||||
func (p *openapiParser) findRef(typ reflect.Type) (jsonschema.Schema, bool) {
|
func (p *openapiParser) findRef(typ reflect.Type) (jsonschema.Schema, bool) {
|
||||||
typs := []reflect.Type{typ}
|
typs := []reflect.Type{typ}
|
||||||
|
|
||||||
// If the type is a struct, the corresponding Go SDK struct might be embedded
|
// Check for embedded Databricks Go SDK types.
|
||||||
// in it. We need to check for those as well.
|
|
||||||
if typ.Kind() == reflect.Struct {
|
if typ.Kind() == reflect.Struct {
|
||||||
for i := 0; i < typ.NumField(); i++ {
|
for i := 0; i < typ.NumField(); i++ {
|
||||||
if !typ.Field(i).Anonymous {
|
if !typ.Field(i).Anonymous {
|
||||||
|
@ -94,11 +96,6 @@ func (p *openapiParser) addDescriptions(typ reflect.Type, s jsonschema.Schema) j
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Description = ref.Description
|
s.Description = ref.Description
|
||||||
|
|
||||||
// Iterate over properties to load descriptions. This is not needed for any
|
|
||||||
// OpenAPI spec generated from protobufs, which are guaranteed to be one level
|
|
||||||
// deep.
|
|
||||||
// Needed for any hand-written OpenAPI specs.
|
|
||||||
for k, v := range s.Properties {
|
for k, v := range s.Properties {
|
||||||
if refProp, ok := ref.Properties[k]; ok {
|
if refProp, ok := ref.Properties[k]; ok {
|
||||||
v.Description = refProp.Description
|
v.Description = refProp.Description
|
||||||
|
@ -116,11 +113,6 @@ func (p *openapiParser) addEnums(typ reflect.Type, s jsonschema.Schema) jsonsche
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Enum = append(s.Enum, ref.Enum...)
|
s.Enum = append(s.Enum, ref.Enum...)
|
||||||
|
|
||||||
// Iterate over properties to load enums. This is not needed for any
|
|
||||||
// OpenAPI spec generated from protobufs, which are guaranteed to be one level
|
|
||||||
// deep.
|
|
||||||
// Needed for any hand-written OpenAPI specs.
|
|
||||||
for k, v := range s.Properties {
|
for k, v := range s.Properties {
|
||||||
if refProp, ok := ref.Properties[k]; ok {
|
if refProp, ok := ref.Properties[k]; ok {
|
||||||
v.Enum = append(v.Enum, refProp.Enum...)
|
v.Enum = append(v.Enum, refProp.Enum...)
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed _generated/jsonschema.json
|
//go:embed _generated/jsonschema.json
|
||||||
var b []byte
|
var bundleSchemaBytes []byte
|
||||||
|
|
||||||
func newSchemaCommand() *cobra.Command {
|
func newSchemaCommand() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
|
@ -18,7 +18,7 @@ func newSchemaCommand() *cobra.Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||||
_, err := cmd.OutOrStdout().Write(b)
|
_, err := cmd.OutOrStdout().Write(bundleSchemaBytes)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,7 @@ import (
|
||||||
"github.com/databricks/cli/libs/dyn"
|
"github.com/databricks/cli/libs/dyn"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ReferenceRegex = `\$\{([a-zA-Z]+([-_]?[a-zA-Z0-9]+)*(\.[a-zA-Z]+([-_]?[a-zA-Z0-9]+)*(\[[0-9]+\])*)*(\[[0-9]+\])*)\}`
|
var re = regexp.MustCompile(`\$\{([a-zA-Z]+([-_]?[a-zA-Z0-9]+)*(\.[a-zA-Z]+([-_]?[a-zA-Z0-9]+)*(\[[0-9]+\])*)*(\[[0-9]+\])*)\}`)
|
||||||
|
|
||||||
var re = regexp.MustCompile(ReferenceRegex)
|
|
||||||
|
|
||||||
// ref represents a variable reference.
|
// ref represents a variable reference.
|
||||||
// It is a string [dyn.Value] contained in a larger [dyn.Value].
|
// It is a string [dyn.Value] contained in a larger [dyn.Value].
|
||||||
|
|
|
@ -18,11 +18,11 @@ func (c pathComponent) Index() int {
|
||||||
return c.index
|
return c.index
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c pathComponent) IsKey() bool {
|
func (c pathComponent) isKey() bool {
|
||||||
return c.key != ""
|
return c.key != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c pathComponent) IsIndex() bool {
|
func (c pathComponent) isIndex() bool {
|
||||||
return c.key == ""
|
return c.key == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,9 @@ type cannotTraverseNilError struct {
|
||||||
func (e cannotTraverseNilError) Error() string {
|
func (e cannotTraverseNilError) Error() string {
|
||||||
component := e.p[len(e.p)-1]
|
component := e.p[len(e.p)-1]
|
||||||
switch {
|
switch {
|
||||||
case component.IsKey():
|
case component.isKey():
|
||||||
return fmt.Sprintf("expected a map to index %q, found nil", e.p)
|
return fmt.Sprintf("expected a map to index %q, found nil", e.p)
|
||||||
case component.IsIndex():
|
case component.isIndex():
|
||||||
return fmt.Sprintf("expected a sequence to index %q, found nil", e.p)
|
return fmt.Sprintf("expected a sequence to index %q, found nil", e.p)
|
||||||
default:
|
default:
|
||||||
panic("invalid component")
|
panic("invalid component")
|
||||||
|
@ -90,7 +90,7 @@ func (component pathComponent) visit(v Value, prefix Path, suffix Pattern, opts
|
||||||
path := append(prefix, component)
|
path := append(prefix, component)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case component.IsKey():
|
case component.isKey():
|
||||||
// Expect a map to be set if this is a key.
|
// Expect a map to be set if this is a key.
|
||||||
switch v.Kind() {
|
switch v.Kind() {
|
||||||
case KindMap:
|
case KindMap:
|
||||||
|
@ -129,7 +129,7 @@ func (component pathComponent) visit(v Value, prefix Path, suffix Pattern, opts
|
||||||
l: v.l,
|
l: v.l,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
case component.IsIndex():
|
case component.isIndex():
|
||||||
// Expect a sequence to be set if this is an index.
|
// Expect a sequence to be set if this is an index.
|
||||||
switch v.Kind() {
|
switch v.Kind() {
|
||||||
case KindSequence:
|
case KindSequence:
|
||||||
|
|
|
@ -32,7 +32,7 @@ func SetByPath(v Value, p Path, nv Value) (Value, error) {
|
||||||
path := append(prefix, component)
|
path := append(prefix, component)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case component.IsKey():
|
case component.isKey():
|
||||||
// Expect a map to be set if this is a key.
|
// Expect a map to be set if this is a key.
|
||||||
m, ok := v.AsMap()
|
m, ok := v.AsMap()
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -48,7 +48,7 @@ func SetByPath(v Value, p Path, nv Value) (Value, error) {
|
||||||
l: v.l,
|
l: v.l,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
case component.IsIndex():
|
case component.isIndex():
|
||||||
// Expect a sequence to be set if this is an index.
|
// Expect a sequence to be set if this is an index.
|
||||||
s, ok := v.AsSequence()
|
s, ok := v.AsSequence()
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -19,7 +19,7 @@ const readonlyTag = "readonly"
|
||||||
const internalTag = "internal"
|
const internalTag = "internal"
|
||||||
|
|
||||||
// Annotation for bundle fields that have been deprecated.
|
// Annotation for bundle fields that have been deprecated.
|
||||||
// Fields tagged as "deprecated" are removed/omitted from the generated schema.
|
// Fields tagged as "deprecated" are omitted from the generated schema.
|
||||||
const deprecatedTag = "deprecated"
|
const deprecatedTag = "deprecated"
|
||||||
|
|
||||||
type constructor struct {
|
type constructor struct {
|
||||||
|
@ -36,8 +36,8 @@ type constructor struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The $defs block in a JSON schema cannot contain "/", otherwise it will not be
|
// The $defs block in a JSON schema cannot contain "/", otherwise it will not be
|
||||||
// correctly parsed by a JSON schema validator. So we replace "/" with an additional
|
// correctly parsed by a JSON schema validator (like the Red Hat YAML extension for VSCode).
|
||||||
// level of nesting in the output map.
|
// So we replace "/" with an additional level of nesting in the output map.
|
||||||
//
|
//
|
||||||
// For example:
|
// For example:
|
||||||
// {"a/b/c": "value"} is converted to {"a": {"b": {"c": "value"}}}
|
// {"a/b/c": "value"} is converted to {"a": {"b": {"c": "value"}}}
|
||||||
|
@ -57,11 +57,14 @@ func (c *constructor) Definitions() any {
|
||||||
parts := strings.Split(k, "/")
|
parts := strings.Split(k, "/")
|
||||||
cur := res
|
cur := res
|
||||||
for i, p := range parts {
|
for i, p := range parts {
|
||||||
|
// Set the value for the last part.
|
||||||
if i == len(parts)-1 {
|
if i == len(parts)-1 {
|
||||||
cur[p] = v
|
cur[p] = v
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For all but the last part, create a new map value to add a level
|
||||||
|
// of nesting.
|
||||||
if _, ok := cur[p]; !ok {
|
if _, ok := cur[p]; !ok {
|
||||||
cur[p] = make(map[string]any)
|
cur[p] = make(map[string]any)
|
||||||
}
|
}
|
||||||
|
@ -77,7 +80,7 @@ func (c *constructor) Definitions() any {
|
||||||
// for every Go type and referring them using $ref in the corresponding node in
|
// for every Go type and referring them using $ref in the corresponding node in
|
||||||
// the JSON schema.
|
// the JSON schema.
|
||||||
//
|
//
|
||||||
// fns is a list of transformation functions that will be applied to all $defs
|
// fns is a list of transformation functions that will be applied in order to all $defs
|
||||||
// in the schema.
|
// in the schema.
|
||||||
func FromType(typ reflect.Type, fns []func(typ reflect.Type, s Schema) Schema) (Schema, error) {
|
func FromType(typ reflect.Type, fns []func(typ reflect.Type, s Schema) Schema) (Schema, error) {
|
||||||
c := constructor{
|
c := constructor{
|
||||||
|
@ -156,11 +159,6 @@ func (c *constructor) walk(typ reflect.Type) error {
|
||||||
}
|
}
|
||||||
c.seen[typPath] = typ
|
c.seen[typPath] = typ
|
||||||
|
|
||||||
// Return early directly if it's already been processed.
|
|
||||||
if _, ok := c.definitions[typPath]; ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var s Schema
|
var s Schema
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
@ -315,10 +313,6 @@ func (c *constructor) fromTypeMap(typ reflect.Type) (Schema, error) {
|
||||||
return Schema{}, fmt.Errorf("expected map, got %s", typ.Kind())
|
return Schema{}, fmt.Errorf("expected map, got %s", typ.Kind())
|
||||||
}
|
}
|
||||||
|
|
||||||
if typ.Key().Kind() != reflect.String {
|
|
||||||
return Schema{}, fmt.Errorf("found map with non-string key: %v", typ.Key())
|
|
||||||
}
|
|
||||||
|
|
||||||
res := Schema{
|
res := Schema{
|
||||||
Type: ObjectType,
|
Type: ObjectType,
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ type Schema struct {
|
||||||
// A boolean type with value false. Setting false here validates that all
|
// A boolean type with value false. Setting false here validates that all
|
||||||
// properties in the config have been defined in the json schema as properties
|
// properties in the config have been defined in the json schema as properties
|
||||||
//
|
//
|
||||||
// Its type during runtime will either be Schema or bool
|
// Its type during runtime will either be *Schema or bool
|
||||||
AdditionalProperties any `json:"additionalProperties,omitempty"`
|
AdditionalProperties any `json:"additionalProperties,omitempty"`
|
||||||
|
|
||||||
// Required properties for the object. Any fields missing the "omitempty"
|
// Required properties for the object. Any fields missing the "omitempty"
|
||||||
|
@ -88,8 +88,6 @@ func (s *Schema) ParseString(v string) (any, error) {
|
||||||
type Type string
|
type Type string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Default zero value of a schema. This does not correspond to a type in the
|
|
||||||
// JSON schema spec and is an internal type defined for convenience.
|
|
||||||
InvalidType Type = "invalid"
|
InvalidType Type = "invalid"
|
||||||
BooleanType Type = "boolean"
|
BooleanType Type = "boolean"
|
||||||
StringType Type = "string"
|
StringType Type = "string"
|
||||||
|
|
Loading…
Reference in New Issue