-
Notifications
You must be signed in to change notification settings - Fork 17
/
Makefile
531 lines (481 loc) · 16.8 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
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
ORG = hawtio
NAMESPACE ?= hawtio
PROJECT = operator
DEFAULT_IMAGE := quay.io/${ORG}/${PROJECT}
IMAGE ?= $(DEFAULT_IMAGE)
VERSION ?= 1.2.0
HAWTIO_ONLINE_VERSION ?= 2.2.0
HAWTIO_ONLINE_IMAGE_NAME ?= quay.io/${ORG}/online
HAWTIO_ONLINE_GATEWAY_IMAGE_NAME ?= quay.io/${ORG}/online-gateway
DEBUG ?= false
LAST_RELEASED_IMAGE_NAME := hawtio-operator
LAST_RELEASED_VERSION ?= 1.1.1
BUNDLE_IMAGE_NAME ?= $(IMAGE)-bundle
# Is this build part of an automated CI pipeline
CI_BUILD ?= false
# Drop suffix for use with bundle and CSV
OPERATOR_VERSION := $(subst -SNAPSHOT,,$(VERSION))
# Replace SNAPSHOT with the timestamp for the tag
DATETIMESTAMP=$(shell date -u '+%Y%m%d-%H%M%S')
VERSION := $(subst -SNAPSHOT,-$(DATETIMESTAMP),$(VERSION))
#
# Versions of tools and binaries
#
CONTROLLER_GEN_VERSION := v0.6.2
KUSTOMIZE_VERSION := v4.5.4
OPERATOR_SDK_VERSION := v1.28.0
OPM_VERSION := v1.24.0
CRD_OPTIONS ?= crd:crdVersions=v1,preserveUnknownFields=false
INSTALL_ROOT := deploy
GEN_SUFFIX := gen.yaml
#
# Allows for resources to be loaded from outside the root location of
# the kustomize config file. Ensures that resource don't need to be
# copied around the file system.
#
# See https://kubectl.docs.kubernetes.io/faq/kustomize
#
KOPTIONS := --load-restrictor LoadRestrictionsNone
# 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
GOFLAGS = -ldflags "$(GOLDFLAGS)" -trimpath
ifeq ($(DEBUG),true)
GOFLAGS += -gcflags="all=-N -l"
endif
.PHONY: image publish-image build compile go-generate test manifests k8s-generate install deploy bundle controller-gen kubectl kustomize check-admin setup operator app
#
# Function for editing kustomize parameters
# Takes single parameter representing the directory
# containing the kustomization to be edited
#
define set-kvars
cd $(1) && \
$(KUSTOMIZE) edit set namespace $(NAMESPACE) && \
$(KUSTOMIZE) edit set image $(DEFAULT_IMAGE)=$(IMAGE):$(VERSION)
endef
#---
#
#@ image
#
#== Compile the operator as a docker image
#
#* PARAMETERS:
#** IMAGE: Set a custom image for the container image
#** VERSION: Set a custom version for the container image tag
#** HAWTIO_ONLINE_IMAGE_NAME Set the operator's target hawtio-online image name
#** HAWTIO_ONLINE_GATEWAY_IMAGE_NAME Set the operator's target hawtio-online-gateway image name
#** HAWTIO_ONLINE_VERSION Set the operator's target hawtio-online image version
#
#---
image:
docker build -t $(IMAGE):$(VERSION) \
--build-arg HAWTIO_ONLINE_IMAGE_NAME=$(HAWTIO_ONLINE_IMAGE_NAME) \
--build-arg HAWTIO_ONLINE_GATEWAY_IMAGE_NAME=$(HAWTIO_ONLINE_GATEWAY_IMAGE_NAME) \
--build-arg HAWTIO_ONLINE_VERSION=$(HAWTIO_ONLINE_VERSION) \
.
#---
#
#@ publish-image
#
#== Compile the operator as a docker image then push the image to the repository
#
#* PARAMETERS:
#** IMAGE: Set a custom image for the container image
#** VERSION: Set a custom version for the container image tag
#** HAWTIO_ONLINE_IMAGE_NAME Set the operator's target hawtio-online image name
#** HAWTIO_ONLINE_GATEWAY_IMAGE_NAME Set the operator's target hawtio-online-gateway image name
#** HAWTIO_ONLINE_VERSION Set the operator's target hawtio-online image version
#
#---
publish-image: image
docker push $(IMAGE):$(VERSION)
#---
#
#@ build
#== Build and test the operator binary
#
#* PARAMETERS:
#** GOLDFLAGS: Add any go-lang ldflags, eg. -X main.ImageVersion=2.0.0-202312061128 will compile in the operand version
#
#---
build: generate compile test
compile:
CGO_ENABLED=0 go build $(GOFLAGS) -o hawtio-operator ./cmd/manager/main.go
# Generate Go code
go-generate:
go generate ./...
# Only use gotestfmt if building / testing locally
test:
ifeq ($(CI_BUILD), false)
ifeq (, $(shell command -v gotestfmt 2> /dev/null))
go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
endif
CGO_ENABLED=0 go test -count=1 ./... -json 2>&1 | gotestfmt
else
CGO_ENABLED=0 go test -count=1 ./... -json 2>&1
endif
# Only instigate re-generation of manifests in non-production builds
manifests: controller-gen
ifeq ($(CI_BUILD), false)
$(CONTROLLER_GEN) $(CRD_OPTIONS) paths="./..." output:crd:artifacts:config=$(INSTALL_ROOT)/crd
endif
# Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations
k8s-generate: controller-gen
ifeq ($(CI_BUILD), false)
$(CONTROLLER_GEN) paths="./..." object
endif
generate: k8s-generate go-generate manifests
get-image:
@echo $(IMAGE)
get-version:
@echo $(VERSION)
#---
#
#@ deploy-crd
#
#== Deploys only the CRD
#
#=== Can only be executed as a cluster-admin
#
#* PARAMETERS:
#** DEBUG: Print the resources to be applied instead of applying them [ true | false ]
#
#---
deploy-crd: kubectl
ifeq ($(DEBUG), false)
$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT)/crd | kubectl apply -f -
else
$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT)/crd
endif
#---
#
#@ deploy
#
#== Deploy all the resources of the operator to the current cluster
#
#=== Can only be executed as a cluster-admin
#
#* PARAMETERS:
#** IMAGE: Set a custom image for the deployment
#** VERSION: Set a custom version for the deployment
#** NAMESPACE: Set the namespace for the resources
#** DEBUG: Print the resources to be applied instead of applying them [ true | false ]
#
#---
deploy: kubectl kustomize install
$(call set-kvars,$(INSTALL_ROOT))
ifeq ($(DEBUG), false)
$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT) | kubectl apply -f -
else
$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT)
endif
# Generate bundle manifests and metadata
DEFAULT_CHANNEL ?= $(shell echo "stable-v$(word 1,$(subst ., ,$(lastword $(OPERATOR_VERSION))))")
CHANNELS ?= $(DEFAULT_CHANNEL),latest
PACKAGE := hawtio-operator
MANIFESTS := bundle
CSV_VERSION := $(OPERATOR_VERSION)
CSV_NAME := $(PACKAGE).v$(CSV_VERSION)
CSV_DISPLAY_NAME := Hawtio Operator
CSV_FILENAME := $(PACKAGE).clusterserviceversion.yaml
CSV_PATH := $(MANIFESTS)/bases/$(CSV_FILENAME)
# Not required for first version to be deployed to Operator Hub
CSV_REPLACES := $(LAST_RELEASED_IMAGE_NAME).v$(LAST_RELEASED_VERSION)
# Hides the 1.0.0 & 1.0.1 releases with the CRD that removes the 'version' property
CSV_SKIP_RANGE := >=1.0.0 <1.0.2
IMAGE_NAME ?= $(DEFAULT_IMAGE)
# Test Bundle Index
BUNDLE_INDEX := quay.io/operatorhubio/catalog:latest
INDEX_DIR := index
OPM := opm
# Options for 'bundle-build'
ifneq ($(origin CHANNELS), undefined)
BUNDLE_CHANNELS := --channels=$(CHANNELS)
endif
ifneq ($(origin DEFAULT_CHANNEL), undefined)
BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL)
endif
ifneq ($(origin PACKAGE), undefined)
BUNDLE_PACKAGE := --package=$(PACKAGE)
endif
BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) $(BUNDLE_PACKAGE)
#
# Tailor the manifest according to default values for this project
# Note. to successfully make the bundle the name must match that specified in the PROJECT file
#
pre-bundle:
# bundle name must match that which appears in PROJECT file
@sed -i 's/projectName: .*/projectName: $(PACKAGE)/' PROJECT
@sed -i 's~^ containerImage: .*~ containerImage: $(IMAGE):$(VERSION)~' $(CSV_PATH)
@sed -i 's/^ name: .*.\(v.*\)/ name: $(CSV_NAME)/' $(CSV_PATH)
@sed -i 's/^ displayName: .*/ displayName: $(CSV_DISPLAY_NAME)/' $(CSV_PATH)
@sed -i 's/^ version: .*/ version: $(CSV_VERSION)/' $(CSV_PATH)
# If there is a replaces version then insert/update it
@if grep -q replaces $(CSV_PATH); \
then sed -i "s/^ replaces: .*/ replaces: $(CSV_REPLACES)/" $(CSV_PATH); \
else sed -i "/ version: ${CSV_VERSION}/a \ \ replaces: $(CSV_REPLACES)" $(CSV_PATH); \
fi
# If there is a skipRange version range then insert/update it
ifneq ($(CSV_SKIP_RANGE), "")
@if grep -q olm.skipRange $(CSV_PATH); \
then sed -i "s/olm.skipRange: .*/olm.skipRange: '$(CSV_SKIP_RANGE)'/" $(CSV_PATH); \
else sed -i "/ annotations:/a \ \ \ \ olm.skipRange: '$(CSV_SKIP_RANGE)'" $(CSV_PATH); \
fi
endif
#---
#
#@ bundle
#
#== Create the manifest bundle artifacts
#
#* PARAMETERS:
#** IMAGE: Set a custom image for the deployment
#** VERSION: Set a custom version for the deployment
#** NAMESPACE: Set the namespace for the resources
#** DEBUG: Print the resources to be applied instead of applying them [ true | false ]
#
#---
bundle: kustomize operator-sdk pre-bundle
@# Display BUNDLE_METADATA_OPTS for debugging
$(info BUNDLE_METADATA_OPTS=$(BUNDLE_METADATA_OPTS))
@# Sets the operator image to the preferred image:tag
@cd bundle && $(KUSTOMIZE) edit set image $(IMAGE_NAME)=$(IMAGE):$(VERSION)
@# Build kustomize manifests
$(KUSTOMIZE) build bundle | $(OPERATOR_SDK) generate bundle \
--kustomize-dir bundle \
--version $(OPERATOR_VERSION) -q --overwrite \
$(BUNDLE_METADATA_OPTS)
#---
#
#@ validate-bundle
#
#== Validate the manifest bundle artifacts generated in bundle directory
#
#---
validate-bundle: operator-sdk
$(OPERATOR_SDK) bundle validate ./bundle --select-optional suite=operatorframework
#---
#
#@ bundle-build
#
#== Build the bundle image.
#
#* PARAMETERS:
#** IMAGE: Set the custom image name (suffixed with '-bundle')
#** VERSION: Set the custom version for the bundle image
#
#---
bundle-build: bundle
docker build -f bundle.Dockerfile -t $(BUNDLE_IMAGE_NAME):$(VERSION) .
#---
#
#@ bundle-index
#
#== Builds a test catalog index for installing the operator via an OLM
#
#* PARAMETERS:
#** IMAGE: Set the custom image name (will be suffixed with '-bundle')
#** VERSION: Set the custom version for the bundle image
#
#---
bundle-index: opm yq
BUNDLE_INDEX=$(BUNDLE_INDEX) INDEX_DIR=$(INDEX_DIR) PACKAGE=$(PACKAGE) YQ=$(YQ) \
OPM=$(OPM) BUNDLE_IMAGE=$(BUNDLE_IMAGE_NAME):$(VERSION) CSV_NAME=$(CSV_NAME) \
CSV_SKIPS="$(CSV_SKIP_RANGE)" CSV_REPLACES=$(CSV_REPLACES) CHANNELS="$(CHANNELS)" \
./script/build_bundle_index.sh
#
# Checks if the cluster user has the necessary privileges to be a cluster-admin
# In this case if the user can list the CRDs then probably a cluster-admin
#
check-admin: kubectl
@output=$$(kubectl get crd 2>&1) || (echo "****" && echo "**** ERROR: Cannot continue as user is not a Cluster-Admin ****" && echo "****"; exit 1)
# find or download controller-gen
# download controller-gen if necessary
#
# Only install in non-production builds
#
controller-gen:
ifeq ($(CI_BUILD), false)
ifeq (, $(shell command -v controller-gen 2> /dev/null))
go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_GEN_VERSION)
CONTROLLER_GEN=$(GOBIN)/controller-gen
else
CONTROLLER_GEN=$(shell command -v controller-gen 2> /dev/null)
endif
else
CONTROLLER_GEN=controller-gen-not-used-in-ci-build
endif
kubectl:
ifeq (, $(shell command -v kubectl 2> /dev/null))
$(error "No kubectl found in PATH. Please install and re-run")
endif
kustomize:
ifeq (, $(shell command -v kustomize 2> /dev/null))
go install sigs.k8s.io/kustomize/kustomize/v4@$(KUSTOMIZE_VERSION)
KUSTOMIZE=$(GOBIN)/kustomize
else
KUSTOMIZE=$(shell command -v kustomize 2> /dev/null)
endif
detect-os:
ifeq '$(findstring ;,$(PATH))' ';'
OS := Windows
OS_LOWER := windows
else
OS := $(shell echo $$(uname 2>/dev/null) || echo Unknown)
OS := $(patsubst CYGWIN%,Cygwin,$(OS))
OS := $(patsubst MSYS%,MSYS,$(OS))
OS := $(patsubst MINGW%,MSYS,$(OS))
OS_LOWER := $(shell echo $(OS) | tr '[:upper:]' '[:lower:]')
endif
operator-sdk: detect-os
@echo "####### Installing operator-sdk version $(OPERATOR_SDK_VERSION)..."
@curl \
-s -L https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION)/operator-sdk_$(OS_LOWER)_amd64 \
-o operator-sdk ; \
chmod +x operator-sdk ;\
mkdir -p $(GOBIN) ;\
mv operator-sdk $(GOBIN)/ ;
OPERATOR_SDK=$(GOBIN)/operator-sdk
opm: detect-os
ifeq (, $(shell command -v opm 2> /dev/null))
@{ \
set -e ;\
curl \
-L https://github.com/operator-framework/operator-registry/releases/download/$(OPM_VERSION)/$(OS_LOWER)-amd64-opm \
-o opm; \
chmod +x opm;\
mkdir -p $(GOBIN) ;\
mv opm $(GOBIN)/ ;\
}
OPM=$(GOBIN)/opm
else
@{ \
echo -n "opm already installed: "; \
opm version | sed -n 's/.*"v\([^"]*\)".*/\1/p'; \
echo " If this is less than $(OPM_VERSION) then please consider moving it aside and allowing the approved version to be downloaded."; \
}
OPM=$(shell command -v opm 2> /dev/null)
endif
yq:
ifeq (, $(shell command -v yq 2> /dev/null))
@GO111MODULE=on go install github.com/mikefarah/yq/v3
YQ=$(GOBIN)/yq
else
YQ=$(shell command -v yq 2> /dev/null)
endif
#---
#
#@ setup
#
#== Setup the installation by installing crds, roles and granting privileges for the installing user.
#
#=== Calls check-admin
#
#* PARAMETERS:
#** IMAGE: Set a custom image for the deployment
#** VERSION: Set a custom version for the deployment
#** NAMESPACE: Set the namespace for the resources
#** DEBUG: Print the resources to be applied instead of applying them [ true | false ]
setup: kubectl kustomize check-admin
#@ Must be invoked by a user with cluster-admin privileges
$(call set-kvars,$(INSTALL_ROOT)/setup)
ifeq ($(DEBUG), false)
$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT)/setup | kubectl apply -f -
else
$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT)/setup
endif
#---
#
#@ operator
#
#== Install just the operator as a normal user
#
#=== (must be granted the privileges by the Cluster-Admin executed `setup` procedure)
#
#* PARAMETERS:
#** IMAGE: Set a custom image for the deployment
#** VERSION: Set a custom version for the deployment
#** NAMESPACE: Set the namespace for the resources
#** DEBUG: Print the resources to be applied instead of applying them [ true | false ]
#
#---
operator: kubectl kustomize
#@ Can be invoked by a user with namespace privileges (rather than a cluster-admin)
$(call set-kvars,$(INSTALL_ROOT)/operator)
ifeq ($(DEBUG), false)
$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT)/operator | kubectl apply -f -
else
$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT)/operator
endif
#---
#
#@ cr
#
#== Install the app CR only
#
#* PARAMETERS:
#** NAMESPACE: Set the namespace for the resources
#** DEBUG: Print the resources to be applied instead of applying them [ true | false ]
#
#---
cr: kubectl kustomize
#@ Can be invoked by a user with namespace privileges (rather than a cluster-admin)
$(call set-kvars,$(INSTALL_ROOT)/app)
ifeq ($(DEBUG), false)
$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT)/app | kubectl apply -f -
else
$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT)/app
endif
#---
#
#@ app
#
#== Install the app CR and deploy the operator as a normal user
#
#=== (must be granted the privileges by the Cluster-Admin executed `setup` procedure)
#
#* PARAMETERS:
#** IMAGE: Set a custom image for the deployment
#** VERSION: Set a custom version for the deployment
#** NAMESPACE: Set the namespace for the resources
#** DEBUG: Print the resources to be applied instead of applying them [ true | false ]
#
#---
app: kubectl kustomize operator
#@ Can be invoked by a user with namespace privileges (rather than a cluster-admin)
$(call set-kvars,$(INSTALL_ROOT)/app)
ifeq ($(DEBUG), false)
$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT)/app | kubectl apply -f -
else
$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT)/app
endif
UNINSTALLS = .uninstall-app .uninstall-operator .uninstall-setup
$(UNINSTALLS): kubectl kustomize
@$(call set-kvars,$(INSTALL_ROOT)/$(subst .uninstall-,,$@))
ifeq ($(DEBUG), false)
@$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT)/$(subst .uninstall-,,$@) | kubectl delete --ignore-not-found=true -f -
else
@$(KUSTOMIZE) build $(KOPTIONS) $(INSTALL_ROOT)/$(subst .uninstall-,,$@) | kubectl delete --dry-run=client -f -
endif
#---
#
#@ uninstall
#
#== Uninstalls the app CR, operator and setup resources
#
#=== Calls check-admin
#
#* PARAMETERS:
#** NAMESPACE: Set the namespace for the resources
#** DEBUG: Print the resources to be deleted instead of deleting them [ true | false ]
#
#---
uninstall: kubectl kustomize check-admin $(UNINSTALLS)
.DEFAULT_GOAL := help
.PHONY: help
help: ## Show this help screen.
@awk 'BEGIN { printf "\nUsage: make \033[31m<PARAM1=val1 PARAM2=val2>\033[0m \033[36m<target>\033[0m\n"; printf "\nAvailable targets are:\n" } /^#@/ { printf "\033[36m%-15s\033[0m", $$2; subdesc=0; next } /^#===/ { printf "%-14s \033[32m%s\033[0m\n", " ", substr($$0, 5); subdesc=1; next } /^#==/ { printf "\033[0m%s\033[0m\n\n", substr($$0, 4); next } /^#\*\*/ { printf "%-14s \033[31m%s\033[0m\n", " ", substr($$0, 4); next } /^#\*/ && (subdesc == 1) { printf "\n"; next } /^#\-\-\-/ { printf "\n"; next }' $(MAKEFILE_LIST)