Skip to content

validation on type alias is ignored when GODEBUG=gotypealias=0 (Go < 1.23) #1071

@mtardy

Description

@mtardy

Here is how to repro:

  1. Create a a repro directory mkdir repro and put repro.go inside of it with:

    // +groupName=repro.io
    package repro
    
    import (
    	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    )
    
    type Repro struct {
    	metav1.TypeMeta   `json:",inline"`
    	metav1.ObjectMeta `json:"metadata"`
    
    	Reproducer StringAlias `json:"reproducer"`
    }
    
    // +kubebuilder:validation:MaxLength=12
    type StringAlias = string
  2. Run controller-gen with:

    go run ./cmd/controller-gen/ crd paths=./repro output:stdout

    The output should be similar to

    ---
    apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    metadata:
      annotations:
        controller-gen.kubebuilder.io/version: (devel)
      name: reproes.repro.io
    spec:
      group: repro.io
      names:
        kind: Repro
        listKind: ReproList
        plural: reproes
        singular: repro
      scope: Namespaced
      versions:
      - name: repro
        schema:
          openAPIV3Schema:
            properties:
              apiVersion:
                description: |-
                  APIVersion defines the versioned schema of this representation of an object.
                  Servers should convert recognized schemas to the latest internal value, and
                  may reject unrecognized values.
                  More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
                type: string
              kind:
                description: |-
                  Kind is a string value representing the REST resource this object represents.
                  Servers may infer this from the endpoint the client submits requests to.
                  Cannot be updated.
                  In CamelCase.
                  More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
                type: string
              metadata:
                type: object
              reproducer:
                type: string
            required:
            - metadata
            - reproducer
            type: object
        served: true
        storage: true
    
  3. Now bump the go directive to Go 1.23.0 in go.mod or put godebug gotypesalias=1 in the go.mod with Go 1.22:

    diff --git a/go.mod b/go.mod
    index 790a5a11..c9e19176 100644
    --- a/go.mod
    +++ b/go.mod
    @@ -1,6 +1,6 @@
     module sigs.k8s.io/controller-tools
    
    -go 1.22.0
    + go 1.23.0
  4. Run controller-gen with:

    go run ./cmd/controller-gen/ crd paths=./repro output:stdout

    The output should be similar to

    ---
    apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    metadata:
      annotations:
        controller-gen.kubebuilder.io/version: (devel)
      name: reproes.repro.io
    spec:
      group: repro.io
      names:
        kind: Repro
        listKind: ReproList
        plural: reproes
        singular: repro
      scope: Namespaced
      versions:
      - name: repro
        schema:
          openAPIV3Schema:
            properties:
              apiVersion:
                description: |-
                  APIVersion defines the versioned schema of this representation of an object.
                  Servers should convert recognized schemas to the latest internal value, and
                  may reject unrecognized values.
                  More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
                type: string
              kind:
                description: |-
                  Kind is a string value representing the REST resource this object represents.
                  Servers may infer this from the endpoint the client submits requests to.
                  Cannot be updated.
                  In CamelCase.
                  More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
                type: string
              metadata:
                type: object
              reproducer:
    +           maxLength: 12
                type: string
            required:
            - metadata
            - reproducer
            type: object
        served: true
        storage: true

Explanation: without the type Alias being its own type (Go 1.22), in localNamedToSchema, the link is missing:

if basicInfo, isBasic := typeInfo.(*types.Basic); isBasic {
typ, fmt, err := builtinToType(basicInfo, ctx.allowDangerousTypes)
if err != nil {
ctx.pkg.AddError(loader.ErrFromNode(err, ident))
}
return &apiext.JSONSchemaProps{
Type: typ,
Format: fmt,
}
}

This patch would fix it cilium@d944deb.

When type Alias is its own type, it goes to:

// NB(directxman12): if there are dot imports, this might be an external reference,
// so use typechecking info to get the actual object
typeNameInfo := typeInfo.(interface{ Obj() *types.TypeName }).Obj()
pkg := typeNameInfo.Pkg()
pkgPath := loader.NonVendorPath(pkg.Path())
if pkg == ctx.pkg.Types {
pkgPath = ""
}
ctx.requestSchema(pkgPath, typeNameInfo.Name())
link := TypeRefLink(pkgPath, typeNameInfo.Name())
return &apiext.JSONSchemaProps{
Ref: &link,
}

And then the link is properly made.

Should we have the patch for the version so that type Alias validation works with Go 1.22 or should we just wait for this project to use Go 1.23 and thus gotypesalias=1? Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions