operator-sdk: CustomResourceDefinition is invalid at kubernetes 1.18

Bug Report

What did you do?

create a new operator and add it api into it:

operator-sdk new test-operator --repo=test
operator-sdk add api --api-version=app.example.com/v1alpha1 --kind=AppService

Add init containers to pkg/apis/v1alpha1/appservice_types.go

// AppServiceSpec defines the desired state of AppService
type AppServiceSpec struct {
 // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
 // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
 // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html
 InitContainers []v1.Container `json:"initContainers"`
}

generate new crd and apply it:

 operator-sdk generate crds
 kubectl apply -f deploy/crds/app.example.com_appservices_crd.yaml 

get error:

The CustomResourceDefinition "appservices.app.example.com" is invalid: spec.validation.openAPIV3Schema.properties[spec].properties[initContainers].items.properties[ports].items.properties[protocol].default: Required value: this property is in x-kubernetes-list-map-keys, so it must have a default or be a required property

What did you expect to see?

add CRD without an error

What did you see instead? Under which circumstances? error:

The CustomResourceDefinition "appservices.app.example.com" is invalid: spec.validation.openAPIV3Schema.properties[spec].properties[initContainers].items.properties[ports].items.properties[protocol].default: Required value: this property is in x-kubernetes-list-map-keys, so it must have a default or be a required property

Environment

  • operator-sdk version:

1.18.1

  • go version:

1.13.4

  • Kubernetes version information:

1.18.2

  • Kubernetes cluster kind:

  • Are you writing your operator in ansible, helm, or go?

Possible Solution

  1. Add a default value to CRD
  2. replace []Container description at CRD with type: Array, type Object

Additional context

This problem is related to new 1.18 validations:

https://github.com/kubernetes-sigs/kubebuilder/issues/1544

protocol - must have default value TCP:

default: TCP

                    ports:
                      description: List of ports to expose from the container. Exposing
                        a port here gives the system additional information about
                        the network connections a container uses, but is primarily
                        informational. Not specifying a port here DOES NOT prevent
                        that port from being exposed. Any port which is listening
                        on the default "0.0.0.0" address inside a container will be
                        accessible from the network. Cannot be updated.
                      items:
                        description: ContainerPort represents a network port in a
                          single container.
                        properties:
                          containerPort:
                            description: Number of port to expose on the pod's IP
                              address. This must be a valid port number, 0 < x < 65536.
                            format: int32
                            type: integer
                          hostIP:
                            description: What host IP to bind the external port to.
                            type: string
                          hostPort:
                            description: Number of port to expose on the host. If
                              specified, this must be a valid port number, 0 < x <
                              65536. If HostNetwork is specified, this must match
                              ContainerPort. Most containers do not need this.
                            format: int32
                            type: integer
                          name:
                            description: If specified, this must be an IANA_SVC_NAME
                              and unique within the pod. Each named port in a pod
                              must have a unique name. Name for the port that can
                              be referred to by services.
                            type: string
                          protocol:
                            description: Protocol for port. Must be UDP, TCP, or SCTP.
                              Defaults to "TCP".
                            type: string
                        required:
                        - containerPort
                        type: object
                      type: array
                      x-kubernetes-list-map-keys:
                      - containerPort
                      - protocol
                      x-kubernetes-list-type: map

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 8
  • Comments: 21 (11 by maintainers)

Commits related to this issue

Most upvoted comments

Workaround for post-v1.0 projects:

# Set CRD version so v1beta1 versions are generated
sed -i 's/\(CRD_OPTIONS ?= "crd:\)/\1crdVersions={v1beta1},/g' Makefile
# If you have any webhooks:
sed -i 's/\(+kubebuilder:webhook:\)/\1webhookVersions={v1beta1},admissionReviewVersions={v1beta1},/g' api/<version>/<kind>_webhook.go
# Then install the controller-gen binary containing the fix
rm -f $(command -v controller-gen)
mkdir tmp && pushd tmp && go mod init tmp
go get sigs.k8s.io/controller-tools/cmd/controller-gen@6fa696de4772fb44595d25355946254885a202df
popd tmp && rm -rf tmp
make manifests

We fixed this in Kubernetes 1.19. Let me know if I can help.

This is still an upstream issue, see https://github.com/kubernetes-sigs/controller-tools/issues/529.

I’m moving this to the backlog until this is resolved in controller-gen once and for all, and a patched v0.3 version is created for go/v2 projects.

@Gmtstephane I linked the wrong commit in the instructions, try 6fa696de4772fb44595d25355946254885a202df (updated above).