Skip to content

Commit ed1c4c9

Browse files
committed
Add support for AllowDangerousTypes
- This can be used to enable float32/float64 (go type) -> number (json schema) for CRDs. It is off by default because floats are not recommended in CRDs generally.
1 parent 288676b commit ed1c4c9

File tree

4 files changed

+46
-10
lines changed

4 files changed

+46
-10
lines changed

pkg/crd/gen.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,16 @@ type Generator struct {
5353
// It's required to be false for v1 CRDs.
5454
PreserveUnknownFields *bool `marker:",optional"`
5555

56+
// AllowDangerousTypes allows types which are usually omitted from CRD generation
57+
// because they are not recommended.
58+
//
59+
// Currently the following additional types are allowed when this is true:
60+
// float32
61+
// float64
62+
//
63+
// Left unspecified, the default is false
64+
AllowDangerousTypes *bool `marker:",optional"`
65+
5666
// MaxDescLen specifies the maximum description length for fields in CRD's OpenAPI schema.
5767
//
5868
// 0 indicates drop the description for all fields completely.
@@ -78,6 +88,8 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
7888
parser := &Parser{
7989
Collector: ctx.Collector,
8090
Checker: ctx.Checker,
91+
// Perform defaulting here to avoid ambiguity later
92+
AllowDangerousTypes: g.AllowDangerousTypes != nil && *g.AllowDangerousTypes == true,
8193
}
8294

8395
AddKnownTypes(parser)

pkg/crd/parser.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,20 @@ type Parser struct {
7373
packages map[*loader.Package]struct{}
7474

7575
flattener *Flattener
76+
77+
// AllowDangerousTypes controls the handling of non-recommended types such as float. If
78+
// false (the default), these types are not supported.
79+
// There is a continuum here:
80+
// 1. Types that are always supported.
81+
// 2. Types that are allowed by default, but not recommended (warning emitted when they are encountered as per PR #443).
82+
// Possibly they are allowed by default for historical reasons and may even be "on their way out" at some point in the future.
83+
// 3. Types that are not allowed by default, not recommended, but there are some legitimate reasons to need them in certain corner cases.
84+
// Possibly these types should also emit a warning as per PR #443 even when they are "switched on" (an integration point between
85+
// this feature and #443 if desired). This is the category that this flag deals with.
86+
// 4. Types that are not allowed and will not be allowed, possibly because it just "doesn't make sense" or possibly
87+
// because the implementation is too difficult/clunky to promote them to category 3.
88+
// TODO: Should we have a more formal mechanism for putting "type patterns" in each of the above categories?
89+
AllowDangerousTypes bool
7690
}
7791

7892
func (p *Parser) init() {
@@ -162,7 +176,7 @@ func (p *Parser) NeedSchemaFor(typ TypeIdent) {
162176
// avoid tripping recursive schemata, like ManagedFields, by adding an empty WIP schema
163177
p.Schemata[typ] = apiext.JSONSchemaProps{}
164178

165-
schemaCtx := newSchemaContext(typ.Package, p)
179+
schemaCtx := newSchemaContext(typ.Package, p, p.AllowDangerousTypes)
166180
ctxForInfo := schemaCtx.ForInfo(info)
167181

168182
pkgMarkers, err := markers.PackageMarkers(p.Collector, typ.Package)

pkg/crd/schema.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,25 +68,29 @@ type schemaContext struct {
6868

6969
schemaRequester schemaRequester
7070
PackageMarkers markers.MarkerValues
71+
72+
allowDangerousTypes bool
7173
}
7274

7375
// newSchemaContext constructs a new schemaContext for the given package and schema requester.
7476
// It must have type info added before use via ForInfo.
75-
func newSchemaContext(pkg *loader.Package, req schemaRequester) *schemaContext {
77+
func newSchemaContext(pkg *loader.Package, req schemaRequester, allowDangerousTypes bool) *schemaContext {
7678
pkg.NeedTypesInfo()
7779
return &schemaContext{
78-
pkg: pkg,
79-
schemaRequester: req,
80+
pkg: pkg,
81+
schemaRequester: req,
82+
allowDangerousTypes: allowDangerousTypes,
8083
}
8184
}
8285

8386
// ForInfo produces a new schemaContext with containing the same information
8487
// as this one, except with the given type information.
8588
func (c *schemaContext) ForInfo(info *markers.TypeInfo) *schemaContext {
8689
return &schemaContext{
87-
pkg: c.pkg,
88-
info: info,
89-
schemaRequester: c.schemaRequester,
90+
pkg: c.pkg,
91+
info: info,
92+
schemaRequester: c.schemaRequester,
93+
allowDangerousTypes: c.allowDangerousTypes,
9094
}
9195
}
9296

@@ -206,7 +210,7 @@ func localNamedToSchema(ctx *schemaContext, ident *ast.Ident) *apiext.JSONSchema
206210
return &apiext.JSONSchemaProps{}
207211
}
208212
if basicInfo, isBasic := typeInfo.(*types.Basic); isBasic {
209-
typ, fmt, err := builtinToType(basicInfo)
213+
typ, fmt, err := builtinToType(basicInfo, ctx.allowDangerousTypes)
210214
if err != nil {
211215
ctx.pkg.AddError(loader.ErrFromNode(err, ident))
212216
}
@@ -398,8 +402,8 @@ func structToSchema(ctx *schemaContext, structType *ast.StructType) *apiext.JSON
398402

399403
// builtinToType converts builtin basic types to their equivalent JSON schema form.
400404
// It *only* handles types allowed by the kubernetes API standards. Floats are not
401-
// allowed.
402-
func builtinToType(basic *types.Basic) (typ string, format string, err error) {
405+
// allowed unless allowDangerousTypes is true
406+
func builtinToType(basic *types.Basic, allowDangerousTypes bool) (typ string, format string, err error) {
403407
// NB(directxman12): formats from OpenAPI v3 are slightly different than those defined
404408
// in JSONSchema. This'll use the OpenAPI v3 ones, since they're useful for bounding our
405409
// non-string types.
@@ -411,6 +415,8 @@ func builtinToType(basic *types.Basic) (typ string, format string, err error) {
411415
typ = "string"
412416
case basicInfo&types.IsInteger != 0:
413417
typ = "integer"
418+
case basicInfo&types.IsFloat != 0 && allowDangerousTypes:
419+
typ = "number"
414420
default:
415421
// NB(directxman12): floats are *NOT* allowed in kubernetes APIs
416422
return "", "", fmt.Errorf("unsupported type %q", basic.String())

pkg/crd/zz_generated.markerhelp.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)