-
Notifications
You must be signed in to change notification settings - Fork 25
/
Makefile
466 lines (371 loc) · 18.4 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
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
# Image URL to use all building/pushing image targets.
IMG ?= ${OPERATOR_IMAGE}:${OPERATOR_TAG}
## Name of kind cluster for all kind-* targets
KIND_CLUSTER_NAME ?= ${USER}-yt-kind
export KIND_CLUSTER_NAME
## Path to kind cluster config.
KIND_CLUSTER_CONFIG =
## K8s context for kind cluster
KIND_KUBE_CONTEXT = kind-$(KIND_CLUSTER_NAME)
## K8s namespace for sample cluster.
YTSAURUS_NAMESPACE ?= ytsaurus-dev
## YTsaurus spec for sample cluster.
YTSAURUS_SPEC ?= config/samples/cluster_v1_cri.yaml
## Version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.24.2
## YTsaurus operator image name.
OPERATOR_IMAGE = ytsaurus/k8s-operator
## YTsaurus operator image tag.
OPERATOR_TAG = 0.0.0-alpha
OPERATOR_CHART = ytop-chart
OPERATOR_CHART_NAME = ytop-chart
OPERATOR_CHART_CRDS = $(OPERATOR_CHART)/templates/crds
OPERATOR_INSTANCE = ytsaurus-dev
ifdef RELEASE_SUFFIX
OPERATOR_IMAGE_RELEASE=$(OPERATOR_IMAGE)$(RELEASE_SUFFIX)
OPERATOR_CHART_NAME_RELEASE=$(OPERATOR_CHART_NAME)$(RELEASE_SUFFIX)
else
OPERATOR_IMAGE_RELEASE=$(OPERATOR_IMAGE)
OPERATOR_CHART_NAME_RELEASE=$(OPERATOR_CHART_NAME)
endif
## K8s namespace for YTsaurus operator.
OPERATOR_NAMESPACE = ytsaurus-operator
ifdef RELEASE_VERSION
DOCKER_BUILD_ARGS += --build-arg VERSION="$(RELEASE_VERSION)"
else
DOCKER_BUILD_ARGS += --build-arg VERSION="$(OPERATOR_TAG)"
endif
DOCKER_BUILD_ARGS += --build-arg REVISION="$(shell git rev-parse HEAD)"
DOCKER_BUILD_ARGS += --build-arg BUILD_DATE="$(shell date -Iseconds -u)"
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif
# Setting SHELL to bash allows bash commands to be executed by recipes.
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
SHELL = /usr/bin/env bash -o pipefail
.SHELLFLAGS = -ec
## Enable debug options.
DEBUG =
## Tests parallelism.
GINKGO_PROCS ?= 2
## Filter tests by labels.
GINKGO_LABEL_FILTER =
GINKGO_FLAGS += --vv
GINKGO_FLAGS += --trace
GINKGO_FLAGS += --procs="$(GINKGO_PROCS)"
GINKGO_FLAGS += --timeout=1h
GINKGO_FLAGS += --poll-progress-after=2m
GINKGO_FLAGS += --poll-progress-interval=1m
ifneq ($(GINKGO_LABEL_FILTER),)
GINKGO_FLAGS += --label-filter="$(GINKGO_LABEL_FILTER)"
endif
ifneq ($(DEBUG),)
GINKGO_FLAGS += --fail-fast
endif
##@ General
.PHONY: all
all: lint build helm-chart test ## Default target: make build, run linters and unit tests.
# The help target prints out all targets with their descriptions organized
# beneath their categories. The categories are represented by '##@' and the
# target descriptions by '##'. The awk commands is responsible for reading the
# entire set of makefiles included in this invocation, looking for lines of the
# file as xyz: ## something, and then pretty-format the target and help. Then,
# if there's a line with ##@ something, that gets pretty-printed as a category.
# More info on the usage of ANSI control characters for terminal formatting:
# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters
# More info on the awk command:
# http://linuxcommand.org/lc3_adv_awk.php
.PHONY: help
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
@awk 'BEGIN {FS = " \??= *"; printf "\n\033[1m%s\033[0m\n", "Options:"} /^## .*/ {C=C substr($$0, 4) " "} /^[A-Z0-9_]* \??=.*/ && C { printf " \033[36m%s\033[0m = %*s %s\n", $$1, -50+length($$1), $$2, C} /^[^#]/ { C="" } END { } ' $(MAKEFILE_LIST)
##@ Development
.PHONY: manifests
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) rbac:roleName=manager-role crd:maxDescLen=80 webhook paths="{\"./api/...\" , \"./controllers/...\", \"./pkg/...\"}" output:crd:artifacts:config=config/crd/bases
$(MAKE) docs/api.md
.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="{\"./api/...\" , \"./controllers/...\", \"./pkg/...\"}"
docs/api.md: config/crd-ref-docs/config.yaml $(wildcard api/v1/*_types.go) | crd-ref-docs
$(CRD_REF_DOCS) --config $< --renderer=markdown --source-path=api/v1 --output-path=$@
.PHONY: fmt
fmt: ## Run go fmt against code.
go fmt ./...
.PHONY: vet
vet: ## Run go vet against code.
go vet ./...
.PHONY: test
test: manifests generate fmt vet envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" \
go test -v ./... -coverprofile cover.out -timeout 1800s
.PHONY: test-e2e
test-e2e: manifests generate fmt vet envtest ginkgo ## Run e2e tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" \
YTSAURUS_ENABLE_E2E_TESTS=true \
$(GINKGO) $(GINKGO_FLAGS) ./test/e2e/... -coverprofile cover.out -timeout 1800s
.PHONY: lint
lint: golangci-lint ## Run golangci-lint linter.
$(GOLANGCI_LINT) run
.PHONY: lint-fix
lint-fix: golangci-lint ## Run golangci-lint linter and perform fixes.
$(GOLANGCI_LINT) run --fix
.PHONY: lint-generated
lint-generated: generate helm-chart ## Check that generated files are uptodate and committed.
test -z "$(shell git status --porcelain api docs/api.md config ytop-chart)"
.PHONY: canonize
canonize: manifests generate fmt vet envtest ## Canonize test results.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" \
CANONIZE=y \
go test -v ./... -coverprofile cover.out
##@ K8s operations
KIND_CLUSTER_CREATE_FLAGS = -v 100 --wait 120s --retain
ifneq (${KIND_CLUSTER_CONFIG},)
KIND_CLUSTER_CREATE_FLAGS += --config ${KIND_CLUSTER_CONFIG}
endif
.PHONY: kind-create-cluster
kind-create-cluster: kind ## Create kind kubernetes cluster.
@if ! $(KIND) get clusters | grep -q $(KIND_CLUSTER_NAME); then \
$(KIND) create cluster --name $(KIND_CLUSTER_NAME) $(KIND_CLUSTER_CREATE_FLAGS); \
fi
$(MAKE) k8s-install-cert-manager
.PHONY: kind-create-cluster-with-registry
kind-create-cluster-with-registry:
$(MAKE) kind-create-cluster KIND_CLUSTER_CONFIG=config/kind/kind-with-registry.yaml
.PHONY: kind-use-context
kind-use-context: ## Switch kubectl default context and namespace.
$(KUBECTL) config set-context $(KIND_KUBE_CONTEXT) --namespace $(YTSAURUS_NAMESPACE)
$(KUBECTL) config use-context $(KIND_KUBE_CONTEXT)
.PHONY: kind-delete-cluster
kind-delete-cluster: kind ## Delete kind kubernetes cluster.
@if $(KIND) get clusters | grep -q $(KIND_CLUSTER_NAME); then \
$(KIND) delete cluster --name $(KIND_CLUSTER_NAME); \
fi
# https://github.com/containerd/containerd/blob/main/docs/hosts.md
# https://distribution.github.io/distribution/about/configuration/
# https://kind.sigs.k8s.io/docs/user/local-registry/
REGISTRY_CONFIG_DIR=config/registry
REGISTRY_LOCAL_PORT = 5000
REGISTRY_LOCAL_ADDR = localhost:${REGISTRY_LOCAL_PORT}
REGISTRY_LOCAL_NAME = ${USER}-registry-localhost-${REGISTRY_LOCAL_PORT}
define REGISTRY_LOCAL_CONFIG
server = "http://${REGISTRY_LOCAL_NAME}:5000"
[host."http://${REGISTRY_LOCAL_NAME}:5000"]
capabilities = ["pull", "resolve", "push"]
skip_verify = true
endef
export REGISTRY_LOCAL_CONFIG
kind-create-local-registry: ## Create local docker registry for kind kubernetes cluster.
docker run --name ${REGISTRY_LOCAL_NAME} -d --restart=always \
--mount type=volume,src=${REGISTRY_LOCAL_NAME},dst=/var/lib/registry \
-p "127.0.0.1:${REGISTRY_LOCAL_PORT}:5000" \
registry:2
docker network connect "kind" ${REGISTRY_LOCAL_NAME}
mkdir -p ${REGISTRY_CONFIG_DIR}/${REGISTRY_LOCAL_ADDR}
echo "$$REGISTRY_LOCAL_CONFIG" >${REGISTRY_CONFIG_DIR}/${REGISTRY_LOCAL_ADDR}/hosts.toml
kind-delete-local-registry: ## Delete local docker registry.
docker rm -f ${REGISTRY_LOCAL_NAME}
docker volume rm ${REGISTRY_LOCAL_NAME}
rm -fr "${REGISTRY_CONFIG_DIR}/${REGISTRY_LOCAL_ADDR}"
TEST_IMAGES = \
ghcr.io/ytsaurus/ytsaurus:stable-24.1.0 \
ghcr.io/ytsaurus/ytsaurus:stable-23.2.0 \
ghcr.io/ytsaurus/ytsaurus:stable-23.2.1
.PHONY: kind-load-test-images
kind-load-test-images:
$(foreach img,$(TEST_IMAGES),docker pull -q $(img) && $(KIND) load docker-image --name $(KIND_CLUSTER_NAME) $(img);)
SAMPLE_IMAGES = \
ghcr.io/ytsaurus/ytsaurus:stable-24.1.0-relwithdebinfo
.PHONY: kind-load-sample-images
kind-load-sample-images:
$(foreach img,$(SAMPLE_IMAGES),docker pull -q $(img) && $(KIND) load docker-image --name $(KIND_CLUSTER_NAME) $(img);)
.PHONY: k8s-install-cert-manager
k8s-install-cert-manager:
@if ! $(KUBECTL) get namespace/cert-manager &>/dev/null; then \
$(KUBECTL) apply --server-side -f "https://github.com/cert-manager/cert-manager/releases/download/$(CERT_MANAGER_VERSION)/cert-manager.yaml"; \
$(KUBECTL) -n cert-manager wait --timeout=60s --for=condition=available --all deployment; \
fi
.PHONY: helm-install
helm-install: ## Install helm chart from sources.
$(HELM) upgrade --install --wait $(OPERATOR_INSTANCE) $(OPERATOR_CHART) \
-n $(OPERATOR_NAMESPACE) --create-namespace \
--set controllerManager.manager.image.repository=${OPERATOR_IMAGE} \
--set controllerManager.manager.image.tag=${OPERATOR_TAG}
$(KUBECTL) -n $(OPERATOR_NAMESPACE) rollout restart deployment -l app.kubernetes.io/instance=$(OPERATOR_INSTANCE)
.PHONY: helm-kind-install
helm-kind-install: helm-chart docker-build ## Build docker image, load into kind and install helm chart.
$(KIND) load docker-image --name $(KIND_CLUSTER_NAME) ${OPERATOR_IMAGE}:${OPERATOR_TAG}
$(MAKE) helm-install
.PHONY: helm-minikube-install
helm-minikube-install: helm-chart ## Build docker image in minikube and install helm chart.
eval $$(minikube docker-env) && docker build ${DOCKER_BUILD_ARGS} -t ${OPERATOR_IMAGE}:${OPERATOR_TAG} .
$(MAKE) helm-install
.PHONY: helm-uninstall
helm-uninstall: ## Uninstal helm chart.
$(HELM) uninstall -n $(OPERATOR_NAMESPACE) $(OPERATOR_INSTANCE)
.PHONY: kind-deploy-ytsaurus
kind-deploy-ytsaurus: ## Deploy sample ytsaurus cluster and all requirements.
$(MAKE) kind-create-cluster
$(MAKE) helm-kind-install
-$(KUBECTL) create namespace $(YTSAURUS_NAMESPACE)
$(KUBECTL) apply --server-side -n $(YTSAURUS_NAMESPACE) -f $(YTSAURUS_SPEC)
$(KUBECTL) wait -n $(YTSAURUS_NAMESPACE) --timeout=10m --for=jsonpath='{.status.state}=Running' --all ytsaurus
$(MAKE) kind-yt-info
.PHONY: kind-undeploy-ytsaurus
kind-undeploy-ytsaurus: ## Undeploy sample ytsaurus cluster.
$(KUBECTL) get namespace $(YTSAURUS_NAMESPACE)
-$(KUBECTL) -n $(YTSAURUS_NAMESPACE) delete ytsaurus --all
-$(KUBECTL) -n $(YTSAURUS_NAMESPACE) delete pods --all --force
$(KUBECTL) delete namespace $(YTSAURUS_NAMESPACE)
KIND_NODE_ADDR = $(shell docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(1))
KIND_SERVICE_NODEPORT = $(shell $(KUBECTL) -n $(1) get service $(2) -o jsonpath="{.spec.ports[$(3)].nodePort}")
KIND_YT_ENV += YT_PROXY=http://$(call KIND_NODE_ADDR,${KIND_CLUSTER_NAME}-control-plane):$(call KIND_SERVICE_NODEPORT,${YTSAURUS_NAMESPACE},http-proxies-lb,0)
KIND_YT_ENV += YT_TOKEN=password
KIND_YT_ENV += YT_CONFIG_PATCHES="{ proxy={ enable_proxy_discovery=%false; }; operation_tracker={ always_show_job_stderr=%true; }; }"
kind-yt-env: ## Print yt cli environment for sample ytsaurus cluster.
@printf "export \"%s\"\n" $(KIND_YT_ENV)
kind-yt-info:
@printf "Kind k8s context: $(KIND_KUBE_CONTEXT) namespace: $(YTSAURUS_NAMESPACE)\nto set kubectl default context run: make kind-use-context\n\n"
@printf "YTsaurus UI: http://%s:%s\nlogin/password: admin/password\nto setup env for yt cli run: . <(make kind-yt-env)\n" \
$(call KIND_NODE_ADDR,${KIND_CLUSTER_NAME}-control-plane) \
$(call KIND_SERVICE_NODEPORT,${YTSAURUS_NAMESPACE},ytsaurus-ui,0)
##@ Build
.PHONY: build
build: generate fmt vet ## Build manager binary.
go build -o bin/manager main.go
.PHONY: run
run: manifests generate fmt vet ## Run a controller from your host.
go run ./main.go
.PHONY: docker-build
docker-build: ## Build docker image with the manager.
docker build ${DOCKER_BUILD_ARGS} -t ${IMG} .
.PHONY: docker-push
docker-push: ## Push docker image with the manager.
docker push ${IMG}
.PHONY: helm-chart
helm-chart: manifests kustomize envsubst kubectl-slice ## Generate helm chart.
$(KUSTOMIZE) build config/helm | name="$(OPERATOR_CHART)" $(ENVSUBST) | $(KUBECTL_SLICE) -q -o $(OPERATOR_CHART_CRDS) -t "{{.metadata.name}}.yaml" --prune
name="$(OPERATOR_CHART_NAME_RELEASE)" version="$(RELEASE_VERSION)" $(ENVSUBST) < config/helm/Chart.yaml > $(OPERATOR_CHART)/Chart.yaml
##@ Deployment
ifndef ignore-not-found
ignore-not-found = false
endif
.PHONY: install
install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
$(KUSTOMIZE) build config/crd | $(KUBECTL) create -f -
.PHONY: update
update: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
$(KUSTOMIZE) build config/crd | $(KUBECTL) replace -f -
.PHONY: uninstall
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.
$(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
.PHONY: reinstall
reinstall: uninstall install ## Reinstall CRDs from the K8s cluster specified in ~/.kube/config.
.PHONY: deploy
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default | $(KUBECTL) create -f -
.PHONY: undeploy
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.
$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
release: kustomize yq ## Release operator docker image and helm chart.
docker build ${DOCKER_BUILD_ARGS} -t $(OPERATOR_IMAGE_RELEASE):${RELEASE_VERSION} .
docker push $(OPERATOR_IMAGE_RELEASE):${RELEASE_VERSION}
docker tag $(OPERATOR_IMAGE_RELEASE):${RELEASE_VERSION} ghcr.io/$(OPERATOR_IMAGE_RELEASE):${RELEASE_VERSION}
docker push ghcr.io/$(OPERATOR_IMAGE_RELEASE):${RELEASE_VERSION}
cd config/manager && $(KUSTOMIZE) edit set image controller=$(OPERATOR_IMAGE_RELEASE):${RELEASE_VERSION}
$(MAKE) helm-chart
$(YQ) -i -P '.controllerManager.manager.image.repository = "$(OPERATOR_IMAGE_RELEASE)"' ytop-chart/values.yaml
helm package $(OPERATOR_CHART)
helm push $(OPERATOR_CHART_NAME_RELEASE)-${RELEASE_VERSION}.tgz oci://registry-1.docker.io/ytsaurus
helm push $(OPERATOR_CHART_NAME_RELEASE)-${RELEASE_VERSION}.tgz oci://ghcr.io/ytsaurus
##@ Build Dependencies
## Location to install dependencies to.
LOCALBIN ?= $(shell pwd)/bin
$(LOCALBIN):
mkdir -p $(LOCALBIN)
# Tool Binaries
KUBECTL ?= kubectl --context $(KIND_KUBE_CONTEXT)
HELM ?= helm --kube-context $(KIND_KUBE_CONTEXT)
KUSTOMIZE ?= $(LOCALBIN)/kustomize-$(KUSTOMIZE_VERSION)
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen-$(CONTROLLER_GEN_VERSION)
ENVTEST ?= $(LOCALBIN)/setup-envtest-$(ENVTEST_VERSION)
GOLANGCI_LINT ?= $(LOCALBIN)/golangci-lint-$(GOLANGCI_LINT_VERSION)
GINKGO ?= $(LOCALBIN)/ginkgo-$(GINKGO_VERSION)
CRD_REF_DOCS ?= $(LOCALBIN)/crd-ref-docs-$(CRD_REF_DOCS_VERSION)
KIND ?= $(LOCALBIN)/kind-$(KIND_VERSION)
ENVSUBST ?= $(LOCALBIN)/envsubst-$(ENVSUBST_VERSION)
KUBECTL_SLICE ?= $(LOCALBIN)/kubectl-slice-$(KUBECTL_SLICE_VERSION)
YQ ?= $(LOCALBIN)/yq-$(YQ_VERSION)
# Tool Versions
KUSTOMIZE_VERSION ?= v5.3.0
CONTROLLER_GEN_VERSION ?= v0.14.0
ENVTEST_VERSION ?= latest
## golangci-lint version.
GOLANGCI_LINT_VERSION ?= v1.61.0
GINKGO_VERSION ?= $(call go-get-version,github.com/onsi/ginkgo/v2)
CRD_REF_DOCS_VERSION ?= v0.1.0
## kind version.
KIND_VERSION ?= v0.22.0
CERT_MANAGER_VERSION ?= v1.14.4
ENVSUBST_VERSION ?= v1.4.2
KUBECTL_SLICE_VERSION ?= v1.3.1
YQ_VERSION ?= v4.44.3
.PHONY: kustomize
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
$(KUSTOMIZE): $(LOCALBIN)
$(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v5,$(KUSTOMIZE_VERSION))
.PHONY: controller-gen
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
$(CONTROLLER_GEN): $(LOCALBIN)
$(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen,$(CONTROLLER_GEN_VERSION))
.PHONY: envtest
envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.
$(ENVTEST): $(LOCALBIN)
$(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest,$(ENVTEST_VERSION))
.PHONY: golangci-lint
golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
$(GOLANGCI_LINT): $(LOCALBIN)
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,${GOLANGCI_LINT_VERSION})
.PHONY: ginkgo
ginkgo: $(GINKGO) ## Download ginkgo locally if necessary.
$(GINKGO): $(LOCALBIN)
$(call go-install-tool,$(GINKGO),github.com/onsi/ginkgo/v2/ginkgo,$(GINKGO_VERSION))
.PHONY: crd-ref-docs
crd-ref-docs: $(CRD_REF_DOCS) ## Download crd-ref-docs locally if necessary.
$(CRD_REF_DOCS): $(LOCALBIN)
$(call go-install-tool,$(CRD_REF_DOCS),github.com/elastic/crd-ref-docs,$(CRD_REF_DOCS_VERSION))
.PHONY: kind
kind: $(KIND) ## Download kind locally if necessary.
$(KIND): $(LOCALBIN)
$(call go-install-tool,$(KIND),sigs.k8s.io/kind,$(KIND_VERSION))
.PHONY: envsubst
envsubst: $(ENVSUBST) ## Download envsubst locally if necessary.
$(ENVSUBST): $(LOCALBIN)
$(call go-install-tool,$(ENVSUBST),github.com/a8m/envsubst/cmd/envsubst,$(ENVSUBST_VERSION))
.PHONY: kubectl-slice
kubectl-slice: $(KUBECTL_SLICE) ## Download kubectl-slice locally if necessary.
$(KUBECTL_SLICE): $(LOCALBIN)
$(call go-install-tool,$(KUBECTL_SLICE),github.com/patrickdappollonio/kubectl-slice,$(KUBECTL_SLICE_VERSION))
.PHONY: yq
yq: $(YQ)
$(YQ): $(LOCALBIN)
$(call go-install-tool,$(YQ),github.com/mikefarah/yq/v4,$(YQ_VERSION))
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
# $1 - target path with name of binary (ideally with version)
# $2 - package url which can be installed
# $3 - specific version of package
define go-install-tool
@[ -f $(1) ] || { \
set -e; \
package=$(2)@$(3) ;\
echo "Downloading $${package}" ;\
GOBIN=$(LOCALBIN) go install $${package} ;\
mv "$$(echo "$(1)" | sed "s/-$(3)$$//")" $(1) ;\
}
endef
# go-get-version will retrieve version of module $1 from go.mod
go-get-version = $(shell go list -m $1 | awk '{print $$2}')