Skip to content

Commit b31d639

Browse files
Merge branch 'main' into update-importas
2 parents 3eaefd4 + cf302a3 commit b31d639

34 files changed

+206
-172
lines changed

.github/workflows/golangci-lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ jobs:
3333
- name: golangci-lint
3434
uses: golangci/golangci-lint-action@e7fa5ac41e1cf5b7d48e45e42232ce7ada589601 # tag=v9.1.0
3535
with:
36-
version: v2.5.0
36+
version: v2.6.0
3737
args: --output.text.print-linter-name=true --output.text.colors=true --timeout 10m
3838
working-directory: ${{matrix.working-directory}}

.golangci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ linters:
3333
- iotamixing
3434
- makezero
3535
- misspell
36+
- modernize
3637
- nakedret
3738
- nilerr
3839
- nolintlint

pkg/applyconfiguration/testdata/cronjob/api/v1/cronjob_types.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"encoding"
2727
"encoding/json"
2828
"fmt"
29+
"maps"
2930
"net/url"
3031
"strconv"
3132
"time"
@@ -412,8 +413,8 @@ type ContainsNestedMap struct {
412413
// +kubebuilder:validation:Type=object
413414
// +kubebuilder:pruning:PreserveUnknownFields
414415
type Preserved struct {
415-
ConcreteField string `json:"concreteField"`
416-
Rest map[string]interface{} `json:"-"`
416+
ConcreteField string `json:"concreteField"`
417+
Rest map[string]any `json:"-"`
417418
}
418419

419420
func (p *Preserved) UnmarshalJSON(data []byte) error {
@@ -434,10 +435,8 @@ func (p *Preserved) UnmarshalJSON(data []byte) error {
434435
}
435436

436437
func (p *Preserved) MarshalJSON() ([]byte, error) {
437-
full := make(map[string]interface{}, len(p.Rest)+1)
438-
for k, v := range p.Rest {
439-
full[k] = v
440-
}
438+
full := make(map[string]any, len(p.Rest)+1)
439+
maps.Copy(full, p.Rest)
441440
full["concreteField"] = p.ConcreteField
442441
return json.Marshal(full)
443442
}

pkg/crd/flatten.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type ErrorRecorder interface {
3838

3939
// isOrNil checks if val is nil if val is of a nillable type, otherwise,
4040
// it compares val to valInt (which should probably be the zero value).
41-
func isOrNil(val reflect.Value, valInt interface{}, zeroInt interface{}) bool {
41+
func isOrNil(val reflect.Value, valInt any, zeroInt any) bool {
4242
switch valKind := val.Kind(); valKind {
4343
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
4444
return val.IsNil()

pkg/crd/gen.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,15 @@ func (Generator) RegisterMarkers(into *markers.Registry) error {
108108
}
109109

110110
// transformRemoveCRDStatus ensures we do not write the CRD status field.
111-
func transformRemoveCRDStatus(obj map[string]interface{}) error {
111+
func transformRemoveCRDStatus(obj map[string]any) error {
112112
delete(obj, "status")
113113
return nil
114114
}
115115

116116
// transformPreserveUnknownFields adds spec.preserveUnknownFields=value.
117-
func transformPreserveUnknownFields(value bool) func(map[string]interface{}) error {
118-
return func(obj map[string]interface{}) error {
119-
if spec, ok := obj["spec"].(map[interface{}]interface{}); ok {
117+
func transformPreserveUnknownFields(value bool) func(map[string]any) error {
118+
return func(obj map[string]any) error {
119+
if spec, ok := obj["spec"].(map[any]any); ok {
120120
spec["preserveUnknownFields"] = value
121121
}
122122
return nil
@@ -185,7 +185,7 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
185185
// Prevent the top level metadata for the CRD to be generate regardless of the intention in the arguments
186186
FixTopLevelMetadata(crdRaw)
187187

188-
versionedCRDs := make([]interface{}, len(crdVersions))
188+
versionedCRDs := make([]any, len(crdVersions))
189189
for i, ver := range crdVersions {
190190
conv, err := AsVersion(crdRaw, schema.GroupVersion{Group: apiextensionsv1.SchemeGroupVersion.Group, Version: ver})
191191
if err != nil {
@@ -202,7 +202,7 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
202202
} else {
203203
fileName = fmt.Sprintf("%s_%s.%s.yaml", crdRaw.Spec.Group, crdRaw.Spec.Names.Plural, crdVersions[i])
204204
}
205-
if err := ctx.WriteYAML(fileName, headerText, []interface{}{crd}, yamlOpts...); err != nil {
205+
if err := ctx.WriteYAML(fileName, headerText, []any{crd}, yamlOpts...); err != nil {
206206
return err
207207
}
208208
}

pkg/crd/known_types.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
package crd
1818

1919
import (
20+
"maps"
21+
2022
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2123
"k8s.io/utils/ptr"
2224
"sigs.k8s.io/controller-tools/pkg/loader"
@@ -156,13 +158,9 @@ func AddKnownTypes(parser *Parser) {
156158
// ensure everything is there before adding to PackageOverrides
157159
// TODO(directxman12): this is a bit of a hack, maybe just use constructors?
158160
parser.init()
159-
for pkgName, override := range KnownPackages {
160-
parser.PackageOverrides[pkgName] = override
161-
}
161+
maps.Copy(parser.PackageOverrides, KnownPackages)
162162
// if we want to generate the embedded ObjectMeta in the CRD we need to add the ObjectMetaPackages
163163
if parser.GenerateEmbeddedObjectMeta {
164-
for pkgName, override := range ObjectMetaPackages {
165-
parser.PackageOverrides[pkgName] = override
166-
}
164+
maps.Copy(parser.PackageOverrides, ObjectMetaPackages)
167165
}
168166
}

pkg/crd/markers/register.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ type hasHelp interface {
7979

8080
// mustMakeAllWithPrefix converts each object into a marker definition using
8181
// the object's type's with the prefix to form the marker name.
82-
func mustMakeAllWithPrefix(prefix string, target markers.TargetType, objs ...interface{}) []*definitionWithHelp {
82+
func mustMakeAllWithPrefix(prefix string, target markers.TargetType, objs ...any) []*definitionWithHelp {
8383
defs := make([]*definitionWithHelp, len(objs))
8484
for i, obj := range objs {
8585
name := prefix + reflect.TypeOf(obj).Name()

pkg/crd/markers/validation.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ type MinProperties int
233233

234234
// Enum specifies that this (scalar) field is restricted to the *exact* values specified here.
235235
// +controllertools:marker:generateHelp:category="CRD validation"
236-
type Enum []interface{}
236+
type Enum []any
237237

238238
// Format specifies additional "complex" formatting for this field.
239239
//
@@ -265,7 +265,7 @@ type Nullable struct{}
265265
// submission of the containing CRD to an apiserver.
266266
// +controllertools:marker:generateHelp:category="CRD validation"
267267
type Default struct {
268-
Value interface{}
268+
Value any
269269
}
270270

271271
// Title sets the title for this field.
@@ -276,7 +276,7 @@ type Default struct {
276276
// important context about what the schema represents.
277277
// +controllertools:marker:generateHelp:category="CRD validation"
278278
type Title struct {
279-
Value interface{}
279+
Value any
280280
}
281281

282282
// KubernetesDefault sets the default value for this field.
@@ -290,7 +290,7 @@ type Title struct {
290290
// submission of the containing CRD to an apiserver.
291291
// +controllertools:marker:generateHelp:category="CRD validation"
292292
type KubernetesDefault struct {
293-
Value interface{}
293+
Value any
294294
}
295295

296296
// Example sets the example value for this field.
@@ -303,7 +303,7 @@ type KubernetesDefault struct {
303303
// submission of the containing CRD to an apiserver.
304304
// +controllertools:marker:generateHelp:category="CRD validation"
305305
type Example struct {
306-
Value interface{}
306+
Value any
307307
}
308308

309309
// XPreserveUnknownFields stops the apiserver from pruning fields which are not specified.

pkg/crd/parser.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,12 +172,7 @@ func (p *Parser) NeedSchemaFor(typ TypeIdent) {
172172
// avoid tripping recursive schemata, like ManagedFields, by adding an empty WIP schema
173173
p.Schemata[typ] = apiextensionsv1.JSONSchemaProps{}
174174

175-
schemaCtx := newSchemaContext(typ.Package, p, func(typ TypeIdent) *apiextensionsv1.JSONSchemaProps {
176-
p.NeedSchemaFor(typ)
177-
178-
props := p.Schemata[typ]
179-
return &props
180-
}, p.AllowDangerousTypes, p.IgnoreUnexportedFields)
175+
schemaCtx := newSchemaContext(typ.Package, p, p.AllowDangerousTypes, p.IgnoreUnexportedFields)
181176
ctxForInfo := schemaCtx.ForInfo(info)
182177

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

pkg/crd/schema.go

Lines changed: 42 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,10 @@ type applyFirstMarker interface {
5757
ApplyFirst()
5858
}
5959

60-
// schemaFetcher is a function that fetches a schema for a given type.
61-
type schemaFetcher func(TypeIdent) *apiextensionsv1.JSONSchemaProps
62-
6360
// schemaRequester knows how to marker that another schema (e.g. via an external reference) is necessary.
6461
type schemaRequester interface {
6562
NeedSchemaFor(typ TypeIdent)
63+
LookupType(pkg *loader.Package, name string) *markers.TypeInfo
6664
}
6765

6866
// schemaContext stores and provides information across a hierarchy of schema generation.
@@ -71,7 +69,6 @@ type schemaContext struct {
7169
info *markers.TypeInfo
7270

7371
schemaRequester schemaRequester
74-
schemaFetcher schemaFetcher
7572
PackageMarkers markers.MarkerValues
7673

7774
allowDangerousTypes bool
@@ -80,12 +77,11 @@ type schemaContext struct {
8077

8178
// newSchemaContext constructs a new schemaContext for the given package and schema requester.
8279
// It must have type info added before use via ForInfo.
83-
func newSchemaContext(pkg *loader.Package, req schemaRequester, fetcher schemaFetcher, allowDangerousTypes, ignoreUnexportedFields bool) *schemaContext {
80+
func newSchemaContext(pkg *loader.Package, req schemaRequester, allowDangerousTypes, ignoreUnexportedFields bool) *schemaContext {
8481
pkg.NeedTypesInfo()
8582
return &schemaContext{
8683
pkg: pkg,
8784
schemaRequester: req,
88-
schemaFetcher: fetcher,
8985
allowDangerousTypes: allowDangerousTypes,
9086
ignoreUnexportedFields: ignoreUnexportedFields,
9187
}
@@ -98,7 +94,6 @@ func (c *schemaContext) ForInfo(info *markers.TypeInfo) *schemaContext {
9894
pkg: c.pkg,
9995
info: info,
10096
schemaRequester: c.schemaRequester,
101-
schemaFetcher: c.schemaFetcher,
10297
allowDangerousTypes: c.allowDangerousTypes,
10398
ignoreUnexportedFields: c.ignoreUnexportedFields,
10499
}
@@ -231,7 +226,7 @@ func typeToSchema(ctx *schemaContext, rawType ast.Expr) *apiextensionsv1.JSONSch
231226
case *ast.MapType:
232227
props = mapToSchema(ctx, expr)
233228
case *ast.StarExpr:
234-
props = typeToSchema(ctx, expr.X)
229+
props = typeToSchema(ctx.ForInfo(&markers.TypeInfo{}), expr.X)
235230
case *ast.StructType:
236231
props = structToSchema(ctx, expr)
237232
default:
@@ -240,9 +235,7 @@ func typeToSchema(ctx *schemaContext, rawType ast.Expr) *apiextensionsv1.JSONSch
240235
return &apiextensionsv1.JSONSchemaProps{}
241236
}
242237

243-
if ctx.info.Doc != "" {
244-
props.Description = ctx.info.Doc
245-
}
238+
props.Description = ctx.info.Doc
246239

247240
applyMarkers(ctx, ctx.info.Markers, props, rawType)
248241

@@ -278,7 +271,6 @@ func localNamedToSchema(ctx *schemaContext, ident *ast.Ident) *apiextensionsv1.J
278271
if aliasInfo, isAlias := typeInfo.(*types.Alias); isAlias {
279272
typeInfo = aliasInfo.Rhs()
280273
}
281-
282274
if basicInfo, isBasic := typeInfo.(*types.Basic); isBasic {
283275
typ, fmt, err := builtinToType(basicInfo, ctx.allowDangerousTypes)
284276
if err != nil {
@@ -290,21 +282,50 @@ func localNamedToSchema(ctx *schemaContext, ident *ast.Ident) *apiextensionsv1.J
290282
// > Otherwise, the alias information is only in the type name, which
291283
// > points directly to the actual (aliased) type.
292284
if basicInfo.Name() != ident.Name {
293-
return ctx.schemaFetcher(TypeIdent{
294-
Package: ctx.pkg,
295-
Name: ident.Name,
296-
})
285+
ctx.requestSchema("", ident.Name)
286+
link := TypeRefLink("", ident.Name)
287+
return &apiext.JSONSchemaProps{
288+
Type: typ,
289+
Format: fmt,
290+
Ref: &link,
291+
}
297292
}
298293
return &apiextensionsv1.JSONSchemaProps{
299294
Type: typ,
300295
Format: fmt,
301296
}
302297
}
298+
// NB(directxman12): if there are dot imports, this might be an external reference,
299+
// so use typechecking info to get the actual object
300+
typeNameInfo := typeInfo.(interface{ Obj() *types.TypeName }).Obj()
301+
pkg := typeNameInfo.Pkg()
302+
pkgPath := loader.NonVendorPath(pkg.Path())
303+
if pkg == ctx.pkg.Types {
304+
pkgPath = ""
305+
}
306+
ctx.requestSchema(pkgPath, typeNameInfo.Name())
307+
link := TypeRefLink(pkgPath, typeNameInfo.Name())
308+
309+
// In cases where we have a named type, apply the type and format from the named schema
310+
// to allow markers that need this information to apply correctly.
311+
var typ, fmt string
312+
if namedInfo, isNamed := typeInfo.(*types.Named); isNamed {
313+
// We don't want/need to do this for structs, maps, or arrays.
314+
// These are already handled in infoToSchema if they have custom marshalling.
315+
if _, isBasic := namedInfo.Underlying().(*types.Basic); isBasic {
316+
namedTypeInfo := ctx.schemaRequester.LookupType(ctx.pkg, namedInfo.Obj().Name())
317+
318+
namedSchema := infoToSchema(ctx.ForInfo(namedTypeInfo))
319+
typ = namedSchema.Type
320+
fmt = namedSchema.Format
321+
}
322+
}
303323

304-
return ctx.schemaFetcher(TypeIdent{
305-
Package: ctx.pkg,
306-
Name: ident.Name,
307-
})
324+
return &apiext.JSONSchemaProps{
325+
Type: typ,
326+
Format: fmt,
327+
Ref: &link,
328+
}
308329
}
309330

310331
// namedSchema creates a schema (ref) for an explicitly external type reference.
@@ -504,9 +525,7 @@ func structToSchema(ctx *schemaContext, structType *ast.StructType) *apiextensio
504525
} else {
505526
propSchema = typeToSchema(ctx.ForInfo(&markers.TypeInfo{}), field.RawField.Type)
506527
}
507-
if field.Doc != "" {
508-
propSchema.Description = field.Doc
509-
}
528+
propSchema.Description = field.Doc
510529

511530
applyMarkers(ctx, field.Markers, propSchema, field.RawField)
512531

0 commit comments

Comments
 (0)