Skip to content

Commit c601764

Browse files
committed
#192: Upgraded Kubegres to Kubebuilder 4.3.1 to be compatible with Kubernetes up to 1.31 . Tested with PostgreSql 17 (#186)
1 parent 6b07ee2 commit c601764

Some content is hidden

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

45 files changed

+4682
-4069
lines changed

.golangci.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
run:
2+
timeout: 5m
3+
allow-parallel-runners: true
4+
5+
issues:
6+
# don't skip warning about doc comments
7+
# don't exclude the default set of lint
8+
exclude-use-default: false
9+
# restore some of the defaults
10+
# (fill in the rest as needed)
11+
exclude-rules:
12+
- path: "api/*"
13+
linters:
14+
- lll
15+
- path: "internal/*"
16+
linters:
17+
- dupl
18+
- lll
19+
linters:
20+
disable-all: true
21+
enable:
22+
- dupl
23+
- errcheck
24+
- copyloopvar
25+
- ginkgolinter
26+
- goconst
27+
- gocyclo
28+
- gofmt
29+
- goimports
30+
- gosimple
31+
- govet
32+
- ineffassign
33+
- lll
34+
- misspell
35+
- nakedret
36+
- prealloc
37+
- revive
38+
- staticcheck
39+
- typecheck
40+
- unconvert
41+
- unparam
42+
- unused
43+
44+
linters-settings:
45+
revive:
46+
rules:
47+
- name: comment-spacings

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.23 as builder
33
ARG TARGETOS
44
ARG TARGETARCH
55

Makefile

Lines changed: 81 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
21
# Image URL to use all building/pushing image targets
3-
LATEST = controller:latest
4-
IMG ?= $(LATEST)
2+
IMG ?= controller:latest
53
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
6-
ENVTEST_K8S_VERSION = 1.27.3
4+
ENVTEST_K8S_VERSION = 1.31.0
75

86
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
97
ifeq (,$(shell go env GOBIN))
@@ -64,7 +62,32 @@ vet: ## Run go vet against code.
6462
.PHONY: test
6563
test: build envtest ## Run tests.
6664
go test $(shell pwd)/internal/test -run $(shell pwd)/internal/test/suite_test.go -v -test.timeout 10000s
67-
#KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test ./... -coverprofile cover.out
65+
#KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out
66+
67+
# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
68+
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
69+
# Prometheus and CertManager are installed by default; skip with:
70+
# - PROMETHEUS_INSTALL_SKIP=true
71+
# - CERT_MANAGER_INSTALL_SKIP=true
72+
.PHONY: test-e2e
73+
test-e2e: manifests generate fmt vet ## Run the e2e tests. Expected an isolated environment using Kind.
74+
@command -v kind >/dev/null 2>&1 || { \
75+
echo "Kind is not installed. Please install Kind manually."; \
76+
exit 1; \
77+
}
78+
@kind get clusters | grep -q 'kind' || { \
79+
echo "No Kind cluster is running. Please start a Kind cluster before running the e2e tests."; \
80+
exit 1; \
81+
}
82+
go test ./test/e2e/ -v -ginkgo.v
83+
84+
.PHONY: lint
85+
lint: golangci-lint ## Run golangci-lint linter
86+
$(GOLANGCI_LINT) run
87+
88+
.PHONY: lint-fix
89+
lint-fix: golangci-lint ## Run golangci-lint linter and perform fixes
90+
$(GOLANGCI_LINT) run --fix
6891

6992
##@ Build
7093

@@ -80,13 +103,13 @@ run: install ## Run a controller from your host.
80103
# If you wish to build the manager image targeting other platforms you can use the --platform flag.
81104
# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it.
82105
# More info: https://docs.docker.com/develop/develop-images/build_enhancements/
83-
#.PHONY: docker-build
84-
#docker-build: ## Build docker image with the manager.
85-
# $(CONTAINER_TOOL) build -t ${IMG} .
106+
.PHONY: docker-build
107+
docker-build: ## Build docker image with the manager.
108+
$(CONTAINER_TOOL) build -t ${IMG} .
86109

87-
#.PHONY: docker-push
88-
#docker-push: ## Push docker image with the manager.
89-
# $(CONTAINER_TOOL) push ${IMG}
110+
.PHONY: docker-push
111+
docker-push: ## Push docker image with the manager.
112+
$(CONTAINER_TOOL) push ${IMG}
90113

91114
# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple
92115
# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:
@@ -99,12 +122,18 @@ PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
99122
docker-buildx: ## Build and push docker image for the manager for cross-platform support
100123
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
101124
sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
102-
- $(CONTAINER_TOOL) buildx create --name project-v3-builder
103-
- $(CONTAINER_TOOL) buildx use project-v3-builder
125+
- $(CONTAINER_TOOL) buildx create --name kubegres-new-builder
126+
- $(CONTAINER_TOOL) buildx use kubegres-new-builder
104127
- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .
105-
- $(CONTAINER_TOOL) buildx rm project-v3-builder
128+
- $(CONTAINER_TOOL) buildx rm kubegres-new-builder
106129
rm Dockerfile.cross
107130

131+
.PHONY: build-installer
132+
build-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment.
133+
mkdir -p dist
134+
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
135+
$(KUSTOMIZE) build config/default > dist/install.yaml
136+
108137
##@ Deployment
109138

110139
ifndef ignore-not-found
@@ -119,16 +148,18 @@ install: build kustomize ## Install CRDs into the K8s cluster specified in ~/.ku
119148
uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
120149
$(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
121150

151+
LATEST ?= controller:latest
152+
122153
.PHONY: deploy-check
123154
deploy-check:
124155
ifeq ($(IMG),$(LATEST))
125-
@echo "PLEASE PROVIDE THE ARGUMENT 'IMG' WHEN RUNNING 'make deploy'. EXAMPLE OF USAGE: 'make deploy IMG=reactivetechio/kubegres:1.16'"
156+
@echo "PLEASE PROVIDE THE ARGUMENT 'IMG' WHEN RUNNING 'make deploy'. EXAMPLE OF USAGE: 'make deploy IMG=reactivetechio/kubegres:1.19'"
126157
exit 1
127158
endif
128159
@echo "RUNNING THE ACCEPTANCE TESTS AND THEN WILL DEPLOY $(IMG) INTO DOCKER HUB."
129160

130161
## Usage: 'make deploy IMG=reactivetechio/kubegres:[version]'
131-
## eg: 'make deploy IMG=reactivetechio/kubegres:1.16'
162+
## eg: 'make deploy IMG=reactivetechio/kubegres:1.19'
132163
## Run acceptance tests then deploy into Docker Hub the controller as the Docker image provided in arg ${IMG}
133164
## and update the local file "kubegres.yaml" with the image ${IMG}
134165
.PHONY: deploy
@@ -138,10 +169,10 @@ deploy: deploy-check docker-buildx kustomize ## Deploy controller to the K8s clu
138169
@echo "DEPLOYED $(IMG) INTO DOCKER HUB. UPDATED 'kubegres.yaml' WITH '$(IMG)'. YOU CAN COMMIT 'kubegres.yaml' AND CREATE A RELEASE IN GITHUB."
139170

140171
.PHONY: undeploy
141-
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
172+
undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
142173
$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
143174

144-
##@ Build Dependencies
175+
##@ Dependencies
145176

146177
## Location to install dependencies to
147178
LOCALBIN ?= $(shell pwd)/bin
@@ -153,27 +184,46 @@ KUBECTL ?= kubectl
153184
KUSTOMIZE ?= $(LOCALBIN)/kustomize
154185
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
155186
ENVTEST ?= $(LOCALBIN)/setup-envtest
187+
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint
156188

157189
## Tool Versions
158-
KUSTOMIZE_VERSION ?= v5.2.1
159-
CONTROLLER_TOOLS_VERSION ?= v0.13.0
190+
KUSTOMIZE_VERSION ?= v5.5.0
191+
CONTROLLER_TOOLS_VERSION ?= v0.16.4
192+
ENVTEST_VERSION ?= release-0.19
193+
GOLANGCI_LINT_VERSION ?= v1.61.0
160194

161195
.PHONY: kustomize
162-
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. If wrong version is installed, it will be removed before downloading.
196+
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
163197
$(KUSTOMIZE): $(LOCALBIN)
164-
@if test -x $(LOCALBIN)/kustomize && ! $(LOCALBIN)/kustomize version | grep -q $(KUSTOMIZE_VERSION); then \
165-
echo "$(LOCALBIN)/kustomize version is not expected $(KUSTOMIZE_VERSION). Removing it before installing."; \
166-
rm -rf $(LOCALBIN)/kustomize; \
167-
fi
168-
test -s $(LOCALBIN)/kustomize || GOBIN=$(LOCALBIN) GO111MODULE=on go install sigs.k8s.io/kustomize/kustomize/v5@$(KUSTOMIZE_VERSION)
198+
$(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v5,$(KUSTOMIZE_VERSION))
169199

170200
.PHONY: controller-gen
171-
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. If wrong version is installed, it will be overwritten.
201+
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
172202
$(CONTROLLER_GEN): $(LOCALBIN)
173-
test -s $(LOCALBIN)/controller-gen && $(LOCALBIN)/controller-gen --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \
174-
GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)
203+
$(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen,$(CONTROLLER_TOOLS_VERSION))
175204

176205
.PHONY: envtest
177-
envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.
206+
envtest: $(ENVTEST) ## Download setup-envtest locally if necessary.
178207
$(ENVTEST): $(LOCALBIN)
179-
test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
208+
$(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest,$(ENVTEST_VERSION))
209+
210+
.PHONY: golangci-lint
211+
golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
212+
$(GOLANGCI_LINT): $(LOCALBIN)
213+
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))
214+
215+
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
216+
# $1 - target path with name of binary
217+
# $2 - package url which can be installed
218+
# $3 - specific version of package
219+
define go-install-tool
220+
@[ -f "$(1)-$(3)" ] || { \
221+
set -e; \
222+
package=$(2)@$(3) ;\
223+
echo "Downloading $${package}" ;\
224+
rm -f $(1) || true ;\
225+
GOBIN=$(LOCALBIN) go install $${package} ;\
226+
mv $(1) $(1)-$(3) ;\
227+
} ;\
228+
ln -sf $(1)-$(3) $(1)
229+
endef

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ stateful-set's life-cycle and data replication could be with Kubernetes.
1717

1818
* It provides a very simple YAML with properties specialised for PostgreSql.
1919

20-
* It is resilient, has over [93 automatized tests](https://github.com/reactive-tech/kubegres/tree/main/internal/test) cases and
20+
* It is resilient, has over [99 automatized tests](https://github.com/reactive-tech/kubegres/tree/main/internal/test) cases and
2121
has been running in production.
2222

2323

cmd/main.go

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright 2023.
2+
Copyright 2025.
33
44
Licensed under the Apache License, Version 2.0 (the "License");
55
you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ limitations under the License.
1717
package main
1818

1919
import (
20+
"crypto/tls"
2021
"flag"
2122
"os"
2223
"reactive-tech.io/kubegres/internal/controller"
@@ -32,10 +33,12 @@ import (
3233
ctrl "sigs.k8s.io/controller-runtime"
3334
"sigs.k8s.io/controller-runtime/pkg/healthz"
3435
"sigs.k8s.io/controller-runtime/pkg/log/zap"
36+
"sigs.k8s.io/controller-runtime/pkg/metrics/filters"
3537
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
38+
"sigs.k8s.io/controller-runtime/pkg/webhook"
3639

3740
kubegresv1 "reactive-tech.io/kubegres/api/v1"
38-
//+kubebuilder:scaffold:imports
41+
// +kubebuilder:scaffold:imports
3942
)
4043

4144
//go:generate go run yamlcopy/WriteYamlTemplatesInGoFile.go
@@ -49,18 +52,26 @@ func init() {
4952
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
5053

5154
utilruntime.Must(kubegresv1.AddToScheme(scheme))
52-
//+kubebuilder:scaffold:scheme
55+
// +kubebuilder:scaffold:scheme
5356
}
5457

5558
func main() {
5659
var metricsAddr string
5760
var enableLeaderElection bool
5861
var probeAddr string
59-
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
62+
var secureMetrics bool
63+
var enableHTTP2 bool
64+
var tlsOpts []func(*tls.Config)
65+
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metrics endpoint binds to. "+
66+
"Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.")
6067
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
6168
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
6269
"Enable leader election for controller manager. "+
6370
"Enabling this will ensure there is only one active controller manager.")
71+
flag.BoolVar(&secureMetrics, "metrics-secure", false,
72+
"If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.")
73+
flag.BoolVar(&enableHTTP2, "enable-http2", false,
74+
"If set, HTTP/2 will be enabled for the metrics and webhook servers")
6475
opts := zap.Options{
6576
Development: true,
6677
}
@@ -69,9 +80,51 @@ func main() {
6980

7081
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
7182

83+
// if the enable-http2 flag is false (the default), http/2 should be disabled
84+
// due to its vulnerabilities. More specifically, disabling http/2 will
85+
// prevent from being vulnerable to the HTTP/2 Stream Cancellation and
86+
// Rapid Reset CVEs. For more information see:
87+
// - https://github.com/advisories/GHSA-qppj-fm5r-hxr3
88+
// - https://github.com/advisories/GHSA-4374-p667-p6c8
89+
disableHTTP2 := func(c *tls.Config) {
90+
setupLog.Info("disabling http/2")
91+
c.NextProtos = []string{"http/1.1"}
92+
}
93+
94+
if !enableHTTP2 {
95+
tlsOpts = append(tlsOpts, disableHTTP2)
96+
}
97+
98+
webhookServer := webhook.NewServer(webhook.Options{
99+
TLSOpts: tlsOpts,
100+
})
101+
102+
// Metrics endpoint is enabled in 'config/default/kustomization.yaml'. The Metrics options configure the server.
103+
// More info:
104+
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/metrics/server
105+
// - https://book.kubebuilder.io/reference/metrics.html
106+
metricsServerOptions := metricsserver.Options{
107+
BindAddress: metricsAddr,
108+
SecureServing: secureMetrics,
109+
TLSOpts: tlsOpts,
110+
}
111+
112+
if secureMetrics {
113+
// FilterProvider is used to protect the metrics endpoint with authn/authz.
114+
// These configurations ensure that only authorized users and service accounts
115+
// can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info:
116+
// https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/metrics/filters#WithAuthenticationAndAuthorization
117+
metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization
118+
119+
// TODO(user): If CertDir, CertName, and KeyName are not specified, controller-runtime will automatically
120+
// generate self-signed certificates for the metrics server. While convenient for development and testing,
121+
// this setup is not recommended for production.
122+
}
123+
72124
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
73125
Scheme: scheme,
74-
Metrics: metricsserver.Options{BindAddress: metricsAddr},
126+
Metrics: metricsServerOptions,
127+
WebhookServer: webhookServer,
75128
HealthProbeBindAddress: probeAddr,
76129
LeaderElection: enableLeaderElection,
77130
LeaderElectionID: "d5ccd92e.reactive-tech.io",
@@ -101,7 +154,7 @@ func main() {
101154
setupLog.Error(err, "unable to create controller", "controller", ctx2.KindKubegres)
102155
os.Exit(1)
103156
}
104-
//+kubebuilder:scaffold:builder
157+
// +kubebuilder:scaffold:builder
105158

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

0 commit comments

Comments
 (0)