self pass 1

This commit is contained in:
Shreyas Goenka 2024-08-27 18:34:33 +02:00
parent 4141f4ea34
commit cb8d6a9f60
No known key found for this signature in database
GPG Key ID: 92A07DF49CCB0622
8 changed files with 26 additions and 44 deletions

View File

@ -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...)

View File

@ -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
} }

View File

@ -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].

View File

@ -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 == ""
} }

View File

@ -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:

View File

@ -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 {

View File

@ -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,
} }

View File

@ -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"