Skip to content

Commit

Permalink
pkg/schema: make type cache local to each schema generation
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmdm committed Jan 22, 2025
1 parent 3f69266 commit bf630dd
Showing 1 changed file with 13 additions and 8 deletions.
21 changes: 13 additions & 8 deletions pkg/openapi/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ import (
"k8s.io/utils/ptr"
)

var cache = map[reflect.Type]*apiext.JSONSchemaProps{}
// typeCache is used to break type recursions for the generated openapi schema.
// Since kubernetes does not support schema refs and nil unions, when we generate a schema,
// if we see a type we've already encountered (that is not a base type like string or int)
// we can opt out of recursively generating the schema, and simply put an any with a Description
// to the property type.
type typeCache = map[reflect.Type]*apiext.JSONSchemaProps

// SchemaFrom builds an openapi schema for a given type as described by the kubernetes apiextensions server.
// These schema's are used to translate Go types to openapi to be consumed by CustomResourceDefinitions.
Expand All @@ -25,10 +30,10 @@ var cache = map[reflect.Type]*apiext.JSONSchemaProps{}
//
// JSON Tags with an improper value (Say a string where an int is expected for example: `MaxLenghth:"hello"`) will cause a panic.
func SchemaFrom(typ reflect.Type) *apiext.JSONSchemaProps {
return generateSchema(typ, true)
return generateSchema(typ, true, make(typeCache))
}

func generateSchema(typ reflect.Type, top bool) *apiext.JSONSchemaProps {
func generateSchema(typ reflect.Type, top bool, cache typeCache) *apiext.JSONSchemaProps {
type OpenAPISchemer interface {
OpenAPISchema() *apiext.JSONSchemaProps
}
Expand Down Expand Up @@ -61,7 +66,7 @@ func generateSchema(typ reflect.Type, top bool) *apiext.JSONSchemaProps {
Description: fmt.Sprintf("%s:%s", typ.Elem().PkgPath(), typ.Elem().Name()),
}
}
return generateSchema(typ.Elem(), false)
return generateSchema(typ.Elem(), false, cache)
}(),
},
}
Expand All @@ -77,7 +82,7 @@ func generateSchema(typ reflect.Type, top bool) *apiext.JSONSchemaProps {
Description: fmt.Sprintf("%s:%s", typ.Elem().PkgPath(), typ.Elem().Name()),
}
}
return generateSchema(typ.Elem(), false)
return generateSchema(typ.Elem(), false, cache)
}(),
},
}
Expand Down Expand Up @@ -106,15 +111,15 @@ func generateSchema(typ reflect.Type, top bool) *apiext.JSONSchemaProps {
}

if f.Anonymous && jTag == "" {
maps.Copy(schema.Properties, generateSchema(f.Type, false).Properties)
maps.Copy(schema.Properties, generateSchema(f.Type, false, cache).Properties)
continue
}

if !strings.HasSuffix(jTag, ",omitempty") && f.Type.Kind() != reflect.Pointer {
schema.Required = append(schema.Required, key)
}

fieldSchema := generateSchema(f.Type, false)
fieldSchema := generateSchema(f.Type, false, cache)

if enum, ok := f.Tag.Lookup("Enum"); ok {
elems := strings.Split(enum, ",")
Expand Down Expand Up @@ -213,7 +218,7 @@ func generateSchema(typ reflect.Type, top bool) *apiext.JSONSchemaProps {
Description: fmt.Sprintf("%s:%s", typ.Elem().PkgPath(), typ.Elem().Name()),
}
}
return generateSchema(typ.Elem(), false)
return generateSchema(typ.Elem(), false, cache)
}

panic("unreachable: " + typ.Kind().String())
Expand Down

0 comments on commit bf630dd

Please sign in to comment.