-
Notifications
You must be signed in to change notification settings - Fork 66
/
Makefile
296 lines (245 loc) · 12.1 KB
/
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
SHELL := bash
platform := $(shell uname | tr A-Z a-z)
### Helper functions
### https://stackoverflow.com/questions/10858261/how-to-abort-makefile-if-variable-not-set
check_defined = \
$(strip $(foreach 1,$1, \
$(call __check_defined,$1,$(strip $(value 2)))))
__check_defined = \
$(if $(value $1),, \
$(error Undefined $1$(if $2, ($2))$(if $(value @), \
required by target '$@')))
###
# runs the target list by default
.DEFAULT_GOAL = list
# Insert a comment starting with '##' after a target, and it will be printed by 'make' and 'make list'
list: ## List Makefile targets
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
#############
### Tools ###
#############
# Allows flexibility to use other build kits, like nerdctl
BUILD_KIT ?= docker
define get_mod_code_generator
echo "Only go get & mod k8s.io/code-generator, but do not install it"
echo "⚠️ Keep it at the same version as captured in go.mod, otherwise we may end up with version inconsistencies"
awk '/k8s.io\/code-generator/ { system("go get -d " $$1 "@" $$2) }' go.mod
endef
install-tools: ## Install tooling required to configure and build this repo
go mod download
@echo "Install all tools..."
@awk -F '"' '/_/ && !/k8s.io\/code-generator/ { system("go install " $$2) }' tools/tools.go
@$(get_mod_code_generator)
go install golang.org/x/vuln/cmd/govulncheck@latest
LOCAL_TESTBIN = $(CURDIR)/testbin
ENVTEST_K8S_VERSION = 1.26.1
ARCHITECTURE = $(shell go env GOARCH)
ifeq ($(ARCHITECTURE),aarch64)
ARCHITECTURE=arm64
endif
LOCAL_BIN := $(CURDIR)/bin
$(LOCAL_BIN):
mkdir -p -v $(@)
LOCAL_TMP := $(CURDIR)/tmp
$(LOCAL_TMP):
mkdir -p -v $(@)
# "Control plane binaries (etcd and kube-apiserver) are loaded by default from /usr/local/kubebuilder/bin.
# This can be overridden by setting the KUBEBUILDER_ASSETS environment variable"
# https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/envtest
export KUBEBUILDER_ASSETS = $(LOCAL_TESTBIN)/k8s/$(ENVTEST_K8S_VERSION)-$(platform)-$(ARCHITECTURE)
.PHONY: kubebuilder-assets
kubebuilder-assets: $(KUBEBUILDER_ASSETS)
$(KUBEBUILDER_ASSETS):
setup-envtest --os $(platform) --arch $(ARCHITECTURE) --bin-dir $(LOCAL_TESTBIN) use $(ENVTEST_K8S_VERSION)
# https://github.com/carvel-dev/ytt/releases
YTT_VERSION ?= v0.50.0
YTT = $(LOCAL_BIN)/ytt-$(YTT_VERSION)-$(platform)-$(ARCHITECTURE)
.PHONY: ytt
ytt: | $(YTT)
$(YTT): | $(LOCAL_BIN)
@printf "Downloading and installing Carvel YTT\n"
@curl -sSL -o $(YTT) https://github.com/carvel-dev/ytt/releases/download/$(YTT_VERSION)/ytt-$(platform)-$(ARCHITECTURE)
@chmod +x $(YTT)
@ln -s $(LOCAL_BIN)/ytt-$(YTT_VERSION)-$(platform)-$(ARCHITECTURE) $(LOCAL_BIN)/ytt
@printf "Carvel YTT $(YTT_VERSION) installed locally\n"
##############
#### Tests ###
##############
.PHONY: unit-tests
unit-tests::install-tools ## Run unit tests
unit-tests::$(KUBEBUILDER_ASSETS)
unit-tests::generate
unit-tests::fmt
unit-tests::vet
unit-tests::manifests
unit-tests::just-unit-tests
.PHONY: just-unit-tests
just-unit-tests:
ginkgo -r --randomize-all api/ internal/ rabbitmqclient/
.PHONY: integration-tests
integration-tests::install-tools ## Run integration tests. Use GINKGO_EXTRA="-some-arg" to append arguments to 'ginkgo run'
integration-tests::$(KUBEBUILDER_ASSETS)
integration-tests::generate
integration-tests::fmt
integration-tests::vet
integration-tests::manifests
integration-tests::just-integration-tests
just-integration-tests: $(KUBEBUILDER_ASSETS)
ginkgo --randomize-all -r -p $(GINKGO_EXTRA) controllers/
.PHONY: local-tests
local-tests: unit-tests integration-tests ## Run all local tests (unit & integration)
.PHONY: system-tests
system-tests: ## Run E2E tests using current context in ~/.kube/config. Expects cluster operator and topology operator to be installed in the cluster
NAMESPACE="rabbitmq-system" ginkgo --randomize-all -r $(GINKGO_EXTRA) system_tests/
###################
### Build & Run ###
###################
.PHONY: manager
manager: generate fmt vet vuln
go build -o bin/manager main.go
# Run against the configured Kubernetes cluster in ~/.kube/config
#
# Since this runs outside a cluster and there's a requirement on cluster-level service
# communication, the connection between them needs to be accounted for.
# https://github.com/telepresenceio/telepresence is one way to do this (just run
# `telepresence connect` and services like `test-service.test-namespace.svc.cluster.local`
# will resolve properly).
.PHONY: run
run: generate fmt vet vuln manifests install just-run
.PHONY: just-run
just-run: ## Just runs 'go run main.go' without regenerating any manifests or deploying RBACs
KUBE_CONFIG=${HOME}/.kube/config OPERATOR_NAMESPACE=rabbitmq-system ENABLE_WEBHOOKS=false ENABLE_DEBUG_PPROF=true go run ./main.go -metrics-bind-address 127.0.0.1:8080
.PHONY: install
install: manifests
kustomize build config/crd | kubectl apply -f -
.PHONY: uninstall
uninstall: manifests
kustomize build config/crd | kubectl delete -f -
.PHONY: deploy-manager
deploy-manager: cmctl
$(CMCTL) check api --wait=2m
kustomize build config/default/overlays/cert-manager/ | kubectl apply -f -
# Generate manifests e.g. CRD, RBAC etc.
manifests: install-tools
controller-gen crd rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
# Generate API reference documentation
.PHONY: api-reference
api-reference:
crd-ref-docs \
--source-path ./api \
--config ./docs/api/autogen/config.yaml \
--templates-dir ./docs/api/autogen/templates \
--output-path ./docs/api/rabbitmq.com.ref.asciidoc \
--max-depth 30
## used in CI pipeline to create release artifact
.PHONY: generate-manifests
generate-manifests:
mkdir -p releases
kustomize build config/installation/ > releases/messaging-topology-operator.bak
sed '/CERTIFICATE_NAMESPACE.*CERTIFICATE_NAME/d' releases/messaging-topology-operator.bak > releases/messaging-topology-operator.yaml
kustomize build config/installation/cert-manager/ > releases/messaging-topology-operator-with-certmanager.yaml
# Run go fmt against code
fmt:
go fmt ./...
# Run go vet against code
vet:
go vet ./...
# Run govulncheck
vuln:
govulncheck ./...
# Generate code & docs
generate: install-tools api-reference
controller-gen object:headerFile="hack/NOTICE.go.txt" paths="./..."
.PHONY: generate-client-set
generate-client-set:
$(get_mod_code_generator)
go mod vendor
./hack/update-codegen.sh
GIT_COMMIT=$(shell git rev-parse --short HEAD)-dev
OPERATOR_IMAGE ?= rabbitmqoperator/messaging-topology-operator
.PHONY: docker-build-dev
docker-build-dev:
$(call check_defined, DOCKER_REGISTRY_SERVER, URL of docker registry containing the Operator image (e.g. registry.my-company.com))
$(BUILD_KIT) buildx build --build-arg=GIT_COMMIT=$(GIT_COMMIT) -t $(DOCKER_REGISTRY_SERVER)/$(OPERATOR_IMAGE):$(GIT_COMMIT) .
$(BUILD_KIT) push $(DOCKER_REGISTRY_SERVER)/$(OPERATOR_IMAGE):$(GIT_COMMIT)
# docker-build-local and deploy-local work in local Kubernetes installations where the Kubernetes API
# server runs in the same Docker Context as the build process. This is the case for Rancher Desktop
# and probably for Docker Desktop. These two commands won't have the desired effect if Kubernetes API
# is running remotely e.g. Cloud, or if the build context is not shared with Kubernetes API e.g. containerd
.PHONY: docker-build-local
docker-build-local:
$(BUILD_KIT) buildx build --build-arg=GIT_COMMIT=$(GIT_COMMIT) -t localhost/topology-operator:$(GIT_COMMIT) .
K8S_OPERATOR_NAMESPACE ?= rabbitmq-system
.PHONY: docker-registry-secret
docker-registry-secret:
$(call check_defined, DOCKER_REGISTRY_USERNAME, Username for accessing the docker registry)
$(call check_defined, DOCKER_REGISTRY_PASSWORD. Password for accessing the docker registry)
$(call check_defined, DOCKER_REGISTRY_SECRET, Name of Kubernetes secret in which to store the Docker registry username and password)
$(call check_defined, DOCKER_REGISTRY_SERVER, URL of docker registry containing the Operator image (e.g. registry.my-company.com))
@echo "Creating registry secret and patching default service account"
@kubectl -n $(K8S_OPERATOR_NAMESPACE) create secret docker-registry $(DOCKER_REGISTRY_SECRET) \
--docker-server='$(DOCKER_REGISTRY_SERVER)' \
--docker-username="$$DOCKER_REGISTRY_USERNAME" \
--docker-password="$$DOCKER_REGISTRY_PASSWORD" || true
@kubectl -n $(K8S_OPERATOR_NAMESPACE) patch serviceaccount messaging-topology-operator -p '{"imagePullSecrets": [{"name": "$(DOCKER_REGISTRY_SECRET)"}]}'
#########################
### Deploy & Teardown ###
#########################
.PHONY: deploy
deploy: manifests deploy-rbac deploy-manager ## Deploy latest version of this Operator
.PHONY: destroy
destroy: ## Delete all resources of this Operator
kustomize build config/rbac | kubectl delete --ignore-not-found=true -f -
kustomize build config/default/base | kubectl delete --ignore-not-found=true -f -
# Deploy operator with local changes
.PHONY: deploy-dev
deploy-dev: cmctl docker-build-dev manifests deploy-rbac docker-registry-secret ## Build current code as a Docker image, push the image, and deploy to current Kubernetes context
$(call check_defined, DOCKER_REGISTRY_USERNAME, Username for accessing the docker registry)
$(call check_defined, DOCKER_REGISTRY_PASSWORD. Password for accessing the docker registry)
$(call check_defined, DOCKER_REGISTRY_SECRET, Name of Kubernetes secret in which to store the Docker registry username and password)
$(call check_defined, DOCKER_REGISTRY_SERVER, URL of docker registry containing the Operator image (e.g. registry.my-company.com))
$(CMCTL) check api --wait=2m
kustomize build config/default/overlays/dev | sed 's@((operator_docker_image))@"$(DOCKER_REGISTRY_SERVER)/$(OPERATOR_IMAGE):$(GIT_COMMIT)"@' | kubectl apply -f -
# Load operator image and deploy operator into current KinD cluster
.PHONY: deploy-kind
deploy-kind: manifests cmctl deploy-rbac
$(BUILD_KIT) buildx build --build-arg=GIT_COMMIT=$(GIT_COMMIT) -t $(DOCKER_REGISTRY_SERVER)/$(OPERATOR_IMAGE):$(GIT_COMMIT) .
kind load docker-image $(DOCKER_REGISTRY_SERVER)/$(OPERATOR_IMAGE):$(GIT_COMMIT)
$(CMCTL) check api --wait=2m
kustomize build config/default/overlays/kind | sed 's@((operator_docker_image))@"$(DOCKER_REGISTRY_SERVER)/$(OPERATOR_IMAGE):$(GIT_COMMIT)"@' | kubectl apply -f -
.PHONY: deploy-local
deploy-local: cmctl deploy-rbac $(YTT)
$(CMCTL) check api --wait=2m
kustomize build config/default/overlays/cert-manager | $(YTT) -f- -f config/ytt_overlays/change_deployment_image.yml \
--data-value operator_image="localhost/topology-operator:$(GIT_COMMIT)" \
-f config/ytt_overlays/never_pull.yml | kubectl apply -f-
.PHONY: deploy-rbac
deploy-rbac:
kustomize build config/rbac | kubectl apply -f -
.PHONY: cluster-operator
cluster-operator:
@kubectl apply -f https://github.com/rabbitmq/cluster-operator/releases/latest/download/cluster-operator.yml
.PHONY: destroy-cluster-operator
destroy-cluster-operator:
@kubectl delete -f https://github.com/rabbitmq/cluster-operator/releases/latest/download/cluster-operator.yml --ignore-not-found
################
# Cert Manager #
################
# https://github.com/cert-manager/cmctl/releases
# Cert Manager now publishes CMCTL independently from cert-manager
CMCTL_VERSION ?= v2.1.0
CMCTL = $(LOCAL_BIN)/cmctl
.PHONY: cmctl
cmctl: | $(CMCTL)
$(CMCTL): | $(LOCAL_BIN) $(LOCAL_TMP)
curl -sSL -o $(LOCAL_TMP)/cmctl.tar.gz https://github.com/cert-manager/cmctl/releases/download/$(CMCTL_VERSION)/cmctl_$(platform)_$(shell go env GOARCH).tar.gz
tar -C $(LOCAL_TMP) -xzf $(LOCAL_TMP)/cmctl.tar.gz
mv $(LOCAL_TMP)/cmctl $(CMCTL)
CERT_MANAGER_VERSION ?= v1.15.1
CERT_MANAGER_MANIFEST ?= https://github.com/jetstack/cert-manager/releases/download/$(CERT_MANAGER_VERSION)/cert-manager.yaml
.PHONY: cert-manager
cert-manager: ## Deploys Cert Manager from JetStack repo. Use CERT_MANAGER_VERSION to customise version e.g. v1.2.0
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/$(CERT_MANAGER_VERSION)/cert-manager.yaml
.PHONY: destroy-cert-manager
destroy-cert-manager: ## Deletes Cert Manager deployment created by 'make cert-manager'
kubectl delete -f https://github.com/jetstack/cert-manager/releases/download/$(CERT_MANAGER_VERSION)/cert-manager.yaml