45
vendor/sigs.k8s.io/controller-tools/pkg/crd/schema.go
generated
vendored
45
vendor/sigs.k8s.io/controller-tools/pkg/crd/schema.go
generated
vendored
@@ -19,6 +19,7 @@ package crd
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"strings"
|
||||
|
||||
@@ -67,15 +68,18 @@ type schemaContext struct {
|
||||
|
||||
schemaRequester schemaRequester
|
||||
PackageMarkers markers.MarkerValues
|
||||
|
||||
allowDangerousTypes bool
|
||||
}
|
||||
|
||||
// newSchemaContext constructs a new schemaContext for the given package and schema requester.
|
||||
// It must have type info added before use via ForInfo.
|
||||
func newSchemaContext(pkg *loader.Package, req schemaRequester) *schemaContext {
|
||||
func newSchemaContext(pkg *loader.Package, req schemaRequester, allowDangerousTypes bool) *schemaContext {
|
||||
pkg.NeedTypesInfo()
|
||||
return &schemaContext{
|
||||
pkg: pkg,
|
||||
schemaRequester: req,
|
||||
pkg: pkg,
|
||||
schemaRequester: req,
|
||||
allowDangerousTypes: allowDangerousTypes,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,9 +87,10 @@ func newSchemaContext(pkg *loader.Package, req schemaRequester) *schemaContext {
|
||||
// as this one, except with the given type information.
|
||||
func (c *schemaContext) ForInfo(info *markers.TypeInfo) *schemaContext {
|
||||
return &schemaContext{
|
||||
pkg: c.pkg,
|
||||
info: info,
|
||||
schemaRequester: c.schemaRequester,
|
||||
pkg: c.pkg,
|
||||
info: info,
|
||||
schemaRequester: c.schemaRequester,
|
||||
allowDangerousTypes: c.allowDangerousTypes,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +109,11 @@ func (c *schemaContext) requestSchema(pkgPath, typeName string) {
|
||||
|
||||
// infoToSchema creates a schema for the type in the given set of type information.
|
||||
func infoToSchema(ctx *schemaContext) *apiext.JSONSchemaProps {
|
||||
if obj := ctx.pkg.Types.Scope().Lookup(ctx.info.Name); obj != nil && implementsJSONMarshaler(obj.Type()) {
|
||||
schema := &apiext.JSONSchemaProps{Type: "Any"}
|
||||
applyMarkers(ctx, ctx.info.Markers, schema, ctx.info.RawSpec.Type)
|
||||
return schema
|
||||
}
|
||||
return typeToSchema(ctx, ctx.info.RawSpec.Type)
|
||||
}
|
||||
|
||||
@@ -200,7 +210,7 @@ func localNamedToSchema(ctx *schemaContext, ident *ast.Ident) *apiext.JSONSchema
|
||||
return &apiext.JSONSchemaProps{}
|
||||
}
|
||||
if basicInfo, isBasic := typeInfo.(*types.Basic); isBasic {
|
||||
typ, fmt, err := builtinToType(basicInfo)
|
||||
typ, fmt, err := builtinToType(basicInfo, ctx.allowDangerousTypes)
|
||||
if err != nil {
|
||||
ctx.pkg.AddError(loader.ErrFromNode(err, ident))
|
||||
}
|
||||
@@ -297,6 +307,8 @@ func mapToSchema(ctx *schemaContext, mapType *ast.MapType) *apiext.JSONSchemaPro
|
||||
ctx.pkg.AddError(loader.ErrFromNode(fmt.Errorf("map values must be a named type, not %T", mapType.Value), mapType.Value))
|
||||
return &apiext.JSONSchemaProps{}
|
||||
}
|
||||
case *ast.StarExpr:
|
||||
valSchema = typeToSchema(ctx.ForInfo(&markers.TypeInfo{}), val)
|
||||
default:
|
||||
ctx.pkg.AddError(loader.ErrFromNode(fmt.Errorf("map values must be a named type, not %T", mapType.Value), mapType.Value))
|
||||
return &apiext.JSONSchemaProps{}
|
||||
@@ -390,8 +402,8 @@ func structToSchema(ctx *schemaContext, structType *ast.StructType) *apiext.JSON
|
||||
|
||||
// builtinToType converts builtin basic types to their equivalent JSON schema form.
|
||||
// It *only* handles types allowed by the kubernetes API standards. Floats are not
|
||||
// allowed.
|
||||
func builtinToType(basic *types.Basic) (typ string, format string, err error) {
|
||||
// allowed unless allowDangerousTypes is true
|
||||
func builtinToType(basic *types.Basic, allowDangerousTypes bool) (typ string, format string, err error) {
|
||||
// NB(directxman12): formats from OpenAPI v3 are slightly different than those defined
|
||||
// in JSONSchema. This'll use the OpenAPI v3 ones, since they're useful for bounding our
|
||||
// non-string types.
|
||||
@@ -403,6 +415,8 @@ func builtinToType(basic *types.Basic) (typ string, format string, err error) {
|
||||
typ = "string"
|
||||
case basicInfo&types.IsInteger != 0:
|
||||
typ = "integer"
|
||||
case basicInfo&types.IsFloat != 0 && allowDangerousTypes:
|
||||
typ = "number"
|
||||
default:
|
||||
// NB(directxman12): floats are *NOT* allowed in kubernetes APIs
|
||||
return "", "", fmt.Errorf("unsupported type %q", basic.String())
|
||||
@@ -417,3 +431,16 @@ func builtinToType(basic *types.Basic) (typ string, format string, err error) {
|
||||
|
||||
return typ, format, nil
|
||||
}
|
||||
|
||||
// Open coded go/types representation of encoding/json.Marshaller
|
||||
var jsonMarshaler = types.NewInterfaceType([]*types.Func{
|
||||
types.NewFunc(token.NoPos, nil, "MarshalJSON",
|
||||
types.NewSignature(nil, nil,
|
||||
types.NewTuple(
|
||||
types.NewVar(token.NoPos, nil, "", types.NewSlice(types.Universe.Lookup("byte").Type())),
|
||||
types.NewVar(token.NoPos, nil, "", types.Universe.Lookup("error").Type())), false)),
|
||||
}, nil).Complete()
|
||||
|
||||
func implementsJSONMarshaler(typ types.Type) bool {
|
||||
return types.Implements(typ, jsonMarshaler) || types.Implements(types.NewPointer(typ), jsonMarshaler)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user