Skip to content
This repository was archived by the owner on Jan 22, 2026. It is now read-only.

Commit 6ea91c5

Browse files
authored
feat: kubebuilder 4.2.0 upgrade (#50)
* feat: update operator-v1 * feat: update operator-v2 * chore: nit * feat: update operator-v2-with-tests * chore: update tests * docs: small update to contributing docs * docs: update main README * ci: bump to go 1.22 * fix: lint
1 parent 2e78e34 commit 6ea91c5

File tree

84 files changed

+1185
-640
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+1185
-640
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ concurrency:
1010
cancel-in-progress: true
1111

1212
env:
13-
GO_VERSION: "1.21"
13+
GO_VERSION: "1.22"
1414

1515
jobs:
1616
prep-matrix:

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 🛠️ Build a Kubernetes Operator in 10 minutes
22

3-
> **👋 The source code has been updated in May 2024 to use the latest version of kubebuilder ([v3.15.0](https://github.com/kubernetes-sigs/kubebuilder/releases/tag/v3.15.0)). Expect the code to be kept up to date with the latest kubebuilder releases!**
3+
> **👋 The source code has been updated in October 2024 to use the latest version of kubebuilder ([v4.2.0](https://github.com/kubernetes-sigs/kubebuilder/releases/tag/v4.2.0)). Expect the code to be kept up to date with the latest kubebuilder releases!**
44
55
## Table of Contents
66

@@ -336,9 +336,10 @@ Note: this is an example with `operator-v1`. Repeat the same steps for all the o
336336
./scripts/bump.sh operator-v2
337337
./scripts/bump.sh operator-v2-with-tests
338338

339-
340-
# 2) Test that the new version works.
339+
# 2) Test that the new version works (for each folder: operator-v1, operator-v2 and operator-v2-with-tests).
341340
# Note: for this step, you will need a running Kubernetes cluster.
341+
make test
342+
342343
kind create cluster
343344
kubectl cluster-info --context kind-kind
344345
kubectl get nodes

operator-v1/.golangci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ linters:
2222
- dupl
2323
- errcheck
2424
- exportloopref
25+
- ginkgolinter
2526
- goconst
2627
- gocyclo
2728
- gofmt
@@ -33,8 +34,14 @@ linters:
3334
- misspell
3435
- nakedret
3536
- prealloc
37+
- revive
3638
- staticcheck
3739
- typecheck
3840
- unconvert
3941
- unparam
4042
- unused
43+
44+
linters-settings:
45+
revive:
46+
rules:
47+
- name: comment-spacings

operator-v1/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Build the manager binary
2-
FROM golang:1.21 AS builder
2+
FROM golang:1.22 AS builder
33
ARG TARGETOS
44
ARG TARGETARCH
55

operator-v1/Makefile

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Image URL to use all building/pushing image targets
22
IMG ?= controller:latest
33
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
4-
ENVTEST_K8S_VERSION = 1.29.0
4+
ENVTEST_K8S_VERSION = 1.31.0
55

66
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
77
ifeq (,$(shell go env GOBIN))
@@ -69,7 +69,7 @@ test-e2e:
6969
go test ./test/e2e/ -v -ginkgo.v
7070

7171
.PHONY: lint
72-
lint: golangci-lint ## Run golangci-lint linter & yamllint
72+
lint: golangci-lint ## Run golangci-lint linter
7373
$(GOLANGCI_LINT) run
7474

7575
.PHONY: lint-fix
@@ -108,10 +108,10 @@ PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
108108
docker-buildx: ## Build and push docker image for the manager for cross-platform support
109109
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
110110
sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
111-
- $(CONTAINER_TOOL) buildx create --name project-v3-builder
112-
$(CONTAINER_TOOL) buildx use project-v3-builder
111+
- $(CONTAINER_TOOL) buildx create --name operator-v1-builder
112+
$(CONTAINER_TOOL) buildx use operator-v1-builder
113113
- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .
114-
- $(CONTAINER_TOOL) buildx rm project-v3-builder
114+
- $(CONTAINER_TOOL) buildx rm operator-v1-builder
115115
rm Dockerfile.cross
116116

117117
.PHONY: build-installer
@@ -152,16 +152,16 @@ $(LOCALBIN):
152152

153153
## Tool Binaries
154154
KUBECTL ?= kubectl
155-
KUSTOMIZE ?= $(LOCALBIN)/kustomize-$(KUSTOMIZE_VERSION)
156-
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen-$(CONTROLLER_TOOLS_VERSION)
157-
ENVTEST ?= $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION)
158-
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint-$(GOLANGCI_LINT_VERSION)
155+
KUSTOMIZE ?= $(LOCALBIN)/kustomize
156+
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
157+
ENVTEST ?= $(LOCALBIN)/setup-envtest
158+
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint
159159

160160
## Tool Versions
161-
KUSTOMIZE_VERSION ?= v5.3.0
162-
CONTROLLER_TOOLS_VERSION ?= v0.14.0
163-
ENVTEST_VERSION ?= release-0.17
164-
GOLANGCI_LINT_VERSION ?= v1.57.2
161+
KUSTOMIZE_VERSION ?= v5.4.3
162+
CONTROLLER_TOOLS_VERSION ?= v0.16.1
163+
ENVTEST_VERSION ?= release-0.19
164+
GOLANGCI_LINT_VERSION ?= v1.59.1
165165

166166
.PHONY: kustomize
167167
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
@@ -181,18 +181,20 @@ $(ENVTEST): $(LOCALBIN)
181181
.PHONY: golangci-lint
182182
golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
183183
$(GOLANGCI_LINT): $(LOCALBIN)
184-
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,${GOLANGCI_LINT_VERSION})
184+
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))
185185

186186
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
187-
# $1 - target path with name of binary (ideally with version)
187+
# $1 - target path with name of binary
188188
# $2 - package url which can be installed
189189
# $3 - specific version of package
190190
define go-install-tool
191-
@[ -f $(1) ] || { \
191+
@[ -f "$(1)-$(3)" ] || { \
192192
set -e; \
193193
package=$(2)@$(3) ;\
194194
echo "Downloading $${package}" ;\
195+
rm -f $(1) || true ;\
195196
GOBIN=$(LOCALBIN) go install $${package} ;\
196-
mv "$$(echo "$(1)" | sed "s/-$(3)$$//")" $(1) ;\
197-
}
197+
mv $(1) $(1)-$(3) ;\
198+
} ;\
199+
ln -sf $(1)-$(3) $(1)
198200
endef

operator-v1/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
## Getting Started
88

99
### Prerequisites
10-
- go version v1.21.0+
10+
- go version v1.22.0+
1111
- docker version 17.03+.
1212
- kubectl version v1.11.3+.
1313
- Access to a Kubernetes v1.11.3+ cluster.

operator-v1/api/v1/foo_types.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ type FooStatus struct {
3333
Happy bool `json:"happy,omitempty"`
3434
}
3535

36-
//+kubebuilder:object:root=true
37-
//+kubebuilder:subresource:status
36+
// +kubebuilder:object:root=true
37+
// +kubebuilder:subresource:status
3838

3939
// Foo is the Schema for the foos API
4040
type Foo struct {
@@ -45,7 +45,7 @@ type Foo struct {
4545
Status FooStatus `json:"status,omitempty"`
4646
}
4747

48-
//+kubebuilder:object:root=true
48+
// +kubebuilder:object:root=true
4949

5050
// FooList contains a list of Foo
5151
type FooList struct {

operator-v1/cmd/main.go

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,13 @@ import (
3131
ctrl "sigs.k8s.io/controller-runtime"
3232
"sigs.k8s.io/controller-runtime/pkg/healthz"
3333
"sigs.k8s.io/controller-runtime/pkg/log/zap"
34+
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
3435
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
3536
"sigs.k8s.io/controller-runtime/pkg/webhook"
3637

3738
tutorialv1 "my.domain/tutorial/api/v1"
3839
"my.domain/tutorial/internal/controller"
39-
//+kubebuilder:scaffold:imports
40+
// +kubebuilder:scaffold:imports
4041
)
4142

4243
var (
@@ -48,7 +49,7 @@ func init() {
4849
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
4950

5051
utilruntime.Must(tutorialv1.AddToScheme(scheme))
51-
//+kubebuilder:scaffold:scheme
52+
// +kubebuilder:scaffold:scheme
5253
}
5354

5455
func main() {
@@ -57,13 +58,15 @@ func main() {
5758
var probeAddr string
5859
var secureMetrics bool
5960
var enableHTTP2 bool
60-
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
61+
var tlsOpts []func(*tls.Config)
62+
flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+
63+
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
6164
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
6265
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
6366
"Enable leader election for controller manager. "+
6467
"Enabling this will ensure there is only one active controller manager.")
65-
flag.BoolVar(&secureMetrics, "metrics-secure", false,
66-
"If set the metrics endpoint is served securely")
68+
flag.BoolVar(&secureMetrics, "metrics-secure", true,
69+
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
6770
flag.BoolVar(&enableHTTP2, "enable-http2", false,
6871
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
6972
opts := zap.Options{
@@ -85,7 +88,6 @@ func main() {
8588
c.NextProtos = []string{"http/1.1"}
8689
}
8790

88-
tlsOpts := []func(*tls.Config){}
8991
if !enableHTTP2 {
9092
tlsOpts = append(tlsOpts, disableHTTP2)
9193
}
@@ -94,13 +96,33 @@ func main() {
9496
TLSOpts: tlsOpts,
9597
})
9698

99+
// Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.
100+
// More info:
101+
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.0/pkg/metrics/server
102+
// - https://book.kubebuilder.io/reference/metrics.html
103+
metricsServerOptions := metricsserver.Options{
104+
BindAddress: metricsAddr,
105+
SecureServing: secureMetrics,
106+
// TODO(user): TLSOpts is used to allow configuring the TLS config used for the server. If certificates are
107+
// not provided, self-signed certificates will be generated by default. This option is not recommended for
108+
// production environments as self-signed certificates do not offer the same level of trust and security
109+
// as certificates issued by a trusted Certificate Authority (CA). The primary risk is potentially allowing
110+
// unauthorized access to sensitive metrics data. Consider replacing with CertDir, CertName, and KeyName
111+
// to provide certificates, ensuring the server communicates using trusted and secure certificates.
112+
TLSOpts: tlsOpts,
113+
}
114+
115+
if secureMetrics {
116+
// FilterProvider is used to protect the metrics endpoint with authn/authz.
117+
// These configurations ensure that only authorized users and service accounts
118+
// can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:
119+
// https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.0/pkg/metrics/filters#WithAuthenticationAndAuthorization
120+
metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization
121+
}
122+
97123
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
98-
Scheme: scheme,
99-
Metrics: metricsserver.Options{
100-
BindAddress: metricsAddr,
101-
SecureServing: secureMetrics,
102-
TLSOpts: tlsOpts,
103-
},
124+
Scheme: scheme,
125+
Metrics: metricsServerOptions,
104126
WebhookServer: webhookServer,
105127
HealthProbeBindAddress: probeAddr,
106128
LeaderElection: enableLeaderElection,
@@ -129,7 +151,7 @@ func main() {
129151
setupLog.Error(err, "unable to create controller", "controller", "Foo")
130152
os.Exit(1)
131153
}
132-
//+kubebuilder:scaffold:builder
154+
// +kubebuilder:scaffold:builder
133155

134156
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
135157
setupLog.Error(err, "unable to set up health check")

operator-v1/config/crd/bases/tutorial.my.domain_foos.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
33
kind: CustomResourceDefinition
44
metadata:
55
annotations:
6-
controller-gen.kubebuilder.io/version: v0.14.0
6+
controller-gen.kubebuilder.io/version: v0.16.1
77
name: foos.tutorial.my.domain
88
spec:
99
group: tutorial.my.domain

operator-v1/config/crd/kustomization.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33
# It should be run by config/default
44
resources:
55
- bases/tutorial.my.domain_foos.yaml
6-
#+kubebuilder:scaffold:crdkustomizeresource
6+
# +kubebuilder:scaffold:crdkustomizeresource
77

88
patches:
99
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
1010
# patches here are for enabling the conversion webhook for each CRD
11-
#+kubebuilder:scaffold:crdkustomizewebhookpatch
11+
# +kubebuilder:scaffold:crdkustomizewebhookpatch
1212

1313
# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
1414
# patches here are for enabling the CA injection for each CRD
1515
#- path: patches/cainjection_in_foos.yaml
16-
#+kubebuilder:scaffold:crdkustomizecainjectionpatch
16+
# +kubebuilder:scaffold:crdkustomizecainjectionpatch
1717

1818
# [WEBHOOK] To enable webhook, uncomment the following section
1919
# the following config is for teaching kustomize how to do kustomization for CRDs.

0 commit comments

Comments
 (0)