forked from eclipse-iofog/iofog-operator
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
339 lines (277 loc) · 13.7 KB
/
Copy pathMakefile
File metadata and controls
339 lines (277 loc) · 13.7 KB
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
OS = $(shell uname -s | tr '[:upper:]' '[:lower:]')
GOBIN ?= $(shell go env GOBIN)
ifeq ($(GOBIN),)
GOBIN := $(shell go env GOPATH)/bin
endif
export PATH := $(GOBIN):$(PATH)
# golangci-lint - pinned version; override with GOLANGCI_LINT_VERSION=vX.Y.Z
GOLANGCI_LINT_VERSION ?= v2.12.2
GOLANGCI_LINT := $(GOBIN)/golangci-lint
# Security tooling - gosec runs outside golangci-lint (edgelet / go-sdk pattern)
GOVULNCHECK_VERSION ?= v1.1.4
GOSEC_VERSION ?= v2.22.2
GOSEC_SCOPE := ./...
VERSION = $(shell grep "^version:" PROJECT | head -1 | sed 's/^version: *//' | tr -d '"' | tr -d ' ')
PREFIX = github.com/eclipse-iofog/iofog-operator/v3/internal/util
# Canonical CRD group in Go source (see apis/*/v3/groupversion_info.go).
SOURCE_CRD_GROUP = datasance.com
# Dual-mirror flavor (override in CI - see RFC R6–R12)
OPERATOR_CRD_GROUP ?= iofog.org
OPERATOR_COMPONENT_LABEL_DOMAIN ?= iofog.org
IMAGE_REGISTRY ?= ghcr.io/eclipse-iofog
# Default component image tags (RFC R10: ghcr.io/eclipse-iofog/*:3.8.0)
CONTROLLER_IMAGE_TAG ?= 3.8.0
ROUTER_IMAGE_TAG ?= 3.8.0
NATS_IMAGE_TAG ?= 3.8.0
LDFLAGS += -X $(PREFIX).routerTag=$(ROUTER_IMAGE_TAG)
LDFLAGS += -X $(PREFIX).controllerTag=$(CONTROLLER_IMAGE_TAG)
LDFLAGS += -X $(PREFIX).natsTag=$(NATS_IMAGE_TAG)
LDFLAGS += -X $(PREFIX).repo=$(IMAGE_REGISTRY)
LDFLAGS += -X $(PREFIX).componentLabelDomain=$(OPERATOR_COMPONENT_LABEL_DOMAIN)
export CGO_ENABLED ?= 0
ifeq (${DEBUG},)
else
GOARGS=-gcflags="all=-N -l"
endif
# Image URL to use all building/pushing image targets
VERSION_TAG ?= 3.8.0
IMG ?= $(IMAGE_REGISTRY)/operator:$(VERSION_TAG)
BUNDLE_IMG ?= $(IMAGE_REGISTRY)/operator-bundle:$(VERSION_TAG)
BUNDLE_PACKAGE ?= iofog-operator
BUNDLE_CHANNEL ?= stable
# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
CRD_OPTIONS ?= "crd:crdVersions=v1,allowDangerousTypes=true"
# Local testing (no image build) - see hack/local/README.md
KUBECONFIG ?= $(HOME)/.kube/config
TEST_NAMESPACE ?= iofog-test
CR_PATH ?= config/cr/
LOCAL_CR_PATH ?= config/cr/local
POSTGRES_PATH ?= config/local/postgres
LOCAL_SCRIPTS ?= hack/local
KUBECTL ?= kubectl
export KUBECONFIG
export TEST_NAMESPACE
all: build
.PHONY: build
build: GOARGS += -ldflags "$(LDFLAGS)"
build: fmt gen ## Build operator binary
GOARCH=$(GOARCH) GOOS=$(GOOS) go build $(GOARGS) -o bin/iofog-operator main.go
install: manifests kustomize ## Install CRDs into a cluster
$(KUSTOMIZE) build config/crd | $(KUBECTL) apply -f -
uninstall: manifests kustomize ## Uninstall CRDs from a cluster
$(KUSTOMIZE) build config/crd | $(KUBECTL) delete -f -
deploy: manifests kustomize ## Deploy controller in the configured Kubernetes cluster in ~/.kube/config
cd config/operator && $(KUSTOMIZE) edit set image ghcr.io/datasance/operator=$(IMG)
$(KUSTOMIZE) build config/default | $(KUBECTL) apply -f -
.PHONY: local-prep
local-prep: install build ## Install CRDs and build operator for local testing (uses KUBECONFIG)
.PHONY: create-namespace
create-namespace: ## Create TEST_NAMESPACE if it does not exist (uses KUBECONFIG)
$(KUBECTL) get namespace $(TEST_NAMESPACE) >/dev/null 2>&1 || $(KUBECTL) create namespace $(TEST_NAMESPACE)
.PHONY: deploy-cr
deploy-cr: create-namespace kustomize ## Deploy CR(s) from CR_PATH into TEST_NAMESPACE (uses KUBECONFIG)
$(KUSTOMIZE) build $(CR_PATH) | $(KUBECTL) apply -f - -n $(TEST_NAMESPACE)
.PHONY: local-cluster-up
local-cluster-up: kustomize ## Create TEST_NAMESPACE and deploy Postgres (OrbStack/k3s local E2E)
bash $(LOCAL_SCRIPTS)/cluster-up.sh
.PHONY: local-cluster-down
local-cluster-down: ## Delete TEST_NAMESPACE and all local E2E resources
bash $(LOCAL_SCRIPTS)/cluster-down.sh
.PHONY: local-deploy-cr
local-deploy-cr: create-namespace kustomize ## Deploy local ControlPlane CR (config/cr/local)
$(KUSTOMIZE) build $(LOCAL_CR_PATH) | $(KUBECTL) apply -f - -n $(TEST_NAMESPACE)
.PHONY: local-wait-baseline
local-wait-baseline: ## Wait until operator created Service, Ingress, Deployment, auth secret
bash $(LOCAL_SCRIPTS)/wait-baseline.sh
.PHONY: local-scenario-a
local-scenario-a: ## E2E scenario A - service patch (controller + router)
bash $(LOCAL_SCRIPTS)/scenario-service-patch.sh
.PHONY: local-scenario-b
local-scenario-b: ## E2E scenario B - ingress patch (host, class, TLS, annotations)
bash $(LOCAL_SCRIPTS)/scenario-ingress-patch.sh
.PHONY: local-scenario-c
local-scenario-c: ## E2E scenario C - auth password patch + secret update
bash $(LOCAL_SCRIPTS)/scenario-auth-patch.sh
.PHONY: local-scenarios
local-scenarios: ## Run E2E scenarios A, B, C in order (operator must be running)
bash $(LOCAL_SCRIPTS)/run-scenarios.sh
.PHONY: local-deploy-operator
local-deploy-operator: kustomize create-namespace ## Deploy published operator image (IMG) into TEST_NAMESPACE
@test -n "$(IMG)" || (echo "IMG is required, e.g. IMG=ghcr.io/datasance/operator:3.8.0-beta.1" && exit 1)
bash $(LOCAL_SCRIPTS)/deploy-operator.sh
.PHONY: local-e2e-setup
local-e2e-setup: local-cluster-up local-prep local-deploy-cr ## Cluster + CRDs + build + Postgres + ControlPlane CR
@echo ""
@echo "Setup complete. In another terminal run: make run"
@echo "Then wait for baseline: make local-wait-baseline"
@echo "Run reconcile E2E tests: make local-scenarios"
@echo "Full guide: hack/local/README.md"
.PHONY: local-e2e-setup-image
local-e2e-setup-image: local-cluster-up local-deploy-operator install local-deploy-cr ## Local E2E with published operator image (IMG=...)
@echo ""
@echo "Setup complete. Wait for baseline: make local-wait-baseline"
@echo "Run reconcile E2E tests: make local-scenarios"
@echo "Operator image: $(IMG)"
@echo "Full guide: hack/local/README.md"
.PHONY: run
run: build ## Run operator locally (uses KUBECONFIG, WATCH_NAMESPACE=TEST_NAMESPACE)
WATCH_NAMESPACE=$(TEST_NAMESPACE) ./bin/iofog-operator
.PHONY: test-local
test-local: local-e2e-setup ## Alias for local-e2e-setup; then run operator and scenarios (see hack/local/README.md)
manifests: gen controller-gen rbac-manifests ## Generate manifests (optional FLAVOR=datasance|iofog; default both CRD sets)
ifdef FLAVOR
$(MAKE) manifests-flavor FLAVOR=$(FLAVOR)
else
$(MAKE) manifests-all
endif
.PHONY: manifests-all manifests-flavor gen-check rbac-manifests
manifests-all: ## Generate CRD manifests for both mirror flavors
$(MAKE) manifests-flavor FLAVOR=datasance
$(MAKE) manifests-flavor FLAVOR=iofog
manifests-flavor: controller-gen ## Generate CRD manifests for one flavor (FLAVOR=datasance|iofog)
@test -n "$(FLAVOR)" || (echo "FLAVOR is required (datasance|iofog)" && exit 1)
@case "$(FLAVOR)" in datasance|iofog) ;; *) echo "FLAVOR must be datasance or iofog" && exit 1 ;; esac
@hack/gen-crds.sh $(FLAVOR)
rbac-manifests: controller-gen ## Generate RBAC and webhook manifests
$(CONTROLLER_GEN) rbac:roleName=manager-role webhook paths="./..."
gen-check: gen manifests-all ## Verify committed CRDs match dual-flavor CRD output
@git diff --exit-code -- config/crd/bases/ \
|| (echo "ERROR: CRD drift - run 'make manifests' and commit" && exit 1)
@echo "config/crd/bases/ is up to date"
fmt: ## Run gofmt against code
@gofmt -s -w .
$(GOLANGCI_LINT):
@echo "⬇️ Installing golangci-lint $(GOLANGCI_LINT_VERSION) → $(GOBIN)..."
@curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh \
| sh -s -- -b $(GOBIN) $(GOLANGCI_LINT_VERSION)
@echo "✓ golangci-lint $(GOLANGCI_LINT_VERSION) installed"
.PHONY: install-lint
install-lint: $(GOLANGCI_LINT) ## Install golangci-lint (pinned to GOLANGCI_LINT_VERSION)
@$(GOLANGCI_LINT) version
lint: $(GOLANGCI_LINT) ## Run linters (auto-installs golangci-lint if needed)
@echo "Running golangci-lint $(GOLANGCI_LINT_VERSION)..."
@$(GOLANGCI_LINT) run --config .golangci.yaml ./...
.PHONY: security-code vulncheck quality
security-code: ## Static Go security analysis (gosec; not in golangci-lint)
@echo "🔍 Running Go static security analysis..."
@if ! command -v gosec >/dev/null 2>&1; then \
echo "⬇️ Installing gosec $(GOSEC_VERSION)..."; \
go install github.com/securego/gosec/v2/cmd/gosec@$(GOSEC_VERSION); \
fi
@gosec -exclude=G101 -exclude-generated $(GOSEC_SCOPE)
vulncheck: ## Dependency vulnerability scan (govulncheck + go mod verify)
@echo "🔐 Running govulncheck..."
@if ! command -v govulncheck >/dev/null 2>&1; then \
echo "⬇️ Installing govulncheck $(GOVULNCHECK_VERSION)..."; \
go install golang.org/x/vuln/cmd/govulncheck@$(GOVULNCHECK_VERSION); \
fi
@govulncheck ./...
@echo "🔍 Verifying module integrity..."
@go mod verify
quality: lint security-code vulncheck ## Full quality gate (lint + gosec + govulncheck)
gen: controller-gen ## Generate code using controller-gen
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
docker:
docker build -t $(IMG) .
unit: ## Run unit tests
set -o pipefail; go list ./... | xargs -n1 go test $(GOARGS) -v -parallel 1 2>&1 | tee test.txt
feature: bats kubectl kustomize ## Run feature tests
test/run.bash
bats: ## Install bats
ifeq (, $(shell which bats))
@{ \
set -e ;\
BATS_TMP_DIR=$$(mktemp -d) ;\
cd $$BATS_TMP_DIR ;\
git clone https://github.com/bats-core/bats-core.git ;\
cd bats-core ;\
git checkout tags/v1.1.0 ;\
./install.sh /usr/local ;\
rm -rf $$BATS_TMP_DIR ;\
}
endif
kubectl: ## Install kubectl
ifeq (, $(shell which kubectl))
@{ \
set -e ;\
KCTL_TMP_DIR=$$(mktemp -d) ;\
cd $$KCTL_TMP_DIR ;\
curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v1.25.2/bin/"$(OS)"/amd64/kubectl ;\
chmod +x kubectl ;\
mv kubectl /usr/local/bin/ ;\
rm -rf $$KCTL_TMP_DIR ;\
}
endif
controller-gen: ## Install controller-gen
ifeq (, $(shell which controller-gen))
@{ \
set -e ;\
go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.17.3 ;\
}
CONTROLLER_GEN=$(GOBIN)/controller-gen
else
CONTROLLER_GEN=$(shell which controller-gen)
endif
kustomize: ## Install kustomize
ifeq (, $(shell which kustomize))
@{ \
set -e ;\
go install sigs.k8s.io/kustomize/kustomize/v5@v5.5.0 ;\
}
KUSTOMIZE=$(GOBIN)/kustomize
else
KUSTOMIZE=$(shell which kustomize)
endif
.PHONY: release-manifests release-manifests-all
release-manifests-all: kustomize ## Build manifest tarballs for both flavors (VERSION_TAG required)
@test -n "$(VERSION_TAG)" || (echo "VERSION_TAG is required" && exit 1)
@chmod +x hack/release-manifests.sh
@IMAGE_REGISTRY=$(IMAGE_REGISTRY) hack/release-manifests.sh datasance $(VERSION_TAG)
@IMAGE_REGISTRY=$(IMAGE_REGISTRY) hack/release-manifests.sh iofog $(VERSION_TAG)
release-manifests: kustomize ## Build manifest tarball for one flavor (FLAVOR + VERSION_TAG required)
@test -n "$(FLAVOR)" || (echo "FLAVOR is required (datasance|iofog)" && exit 1)
@test -n "$(VERSION_TAG)" || (echo "VERSION_TAG is required" && exit 1)
@chmod +x hack/release-manifests.sh
@IMAGE_REGISTRY=$(IMAGE_REGISTRY) hack/release-manifests.sh $(FLAVOR) $(VERSION_TAG)
.PHONY: package-helm package-helm-all
package-helm-all: ## Build Helm chart tarballs for both flavors (VERSION_TAG required)
@test -n "$(VERSION_TAG)" || (echo "VERSION_TAG is required" && exit 1)
@chmod +x hack/package-helm.sh
@IMAGE_REGISTRY=ghcr.io/datasance OPERATOR_CRD_GROUP=datasance.com hack/package-helm.sh datasance $(VERSION_TAG)
@IMAGE_REGISTRY=ghcr.io/eclipse-iofog OPERATOR_CRD_GROUP=iofog.org hack/package-helm.sh iofog $(VERSION_TAG)
package-helm: ## Build Helm chart tarball for one flavor (FLAVOR + VERSION_TAG required)
@test -n "$(FLAVOR)" || (echo "FLAVOR is required (datasance|iofog)" && exit 1)
@test -n "$(VERSION_TAG)" || (echo "VERSION_TAG is required" && exit 1)
@chmod +x hack/package-helm.sh
@IMAGE_REGISTRY=$(IMAGE_REGISTRY) OPERATOR_CRD_GROUP=$(OPERATOR_CRD_GROUP) hack/package-helm.sh $(FLAVOR) $(VERSION_TAG)
.PHONY: render-helm-docs
render-helm-docs: ## Render flavor-stamped gh-pages landing HTML (FLAVOR + VERSION_TAG + OUTPUT_DIR required)
@test -n "$(FLAVOR)" || (echo "FLAVOR is required (datasance|iofog)" && exit 1)
@test -n "$(VERSION_TAG)" || (echo "VERSION_TAG is required" && exit 1)
@test -n "$(OUTPUT_DIR)" || (echo "OUTPUT_DIR is required" && exit 1)
@chmod +x hack/render-helm-docs.sh
@HELM_REPO_BASE_URL=$(HELM_REPO_BASE_URL) OCI_SOURCE_REPO=$(OCI_SOURCE_REPO) \
IMAGE_REGISTRY=$(IMAGE_REGISTRY) OPERATOR_CRD_GROUP=$(OPERATOR_CRD_GROUP) \
hack/render-helm-docs.sh $(FLAVOR) $(VERSION_TAG) $(OUTPUT_DIR)
.PHONY: bundle
bundle: kustomize ## Generate flavor-specific OLM bundle (FLAVOR=datasance|iofog required)
@test -n "$(FLAVOR)" || (echo "FLAVOR is required (datasance|iofog)" && exit 1)
@case "$(FLAVOR)" in datasance|iofog) ;; *) echo "FLAVOR must be datasance or iofog" && exit 1 ;; esac
@test -n "$(VERSION_TAG)" || (echo "VERSION_TAG is required" && exit 1)
@chmod +x hack/gen-bundle.sh
@IMAGE_REGISTRY=$(IMAGE_REGISTRY) BUNDLE_PACKAGE=$(BUNDLE_PACKAGE) BUNDLE_CHANNEL=$(BUNDLE_CHANNEL) \
hack/gen-bundle.sh $(FLAVOR) $(VERSION_TAG)
.PHONY: bundle-build
bundle-build: ## Build the bundle image.
docker buildx build --platform=linux/amd64 -f bundle.Dockerfile -t $(BUNDLE_IMG) .
help: ## Show targets and flavor variables
@echo "Flavor variables (override at build time):"
@printf " \033[33m%-35s\033[0m %s\n" OPERATOR_CRD_GROUP $(OPERATOR_CRD_GROUP)
@printf " \033[33m%-35s\033[0m %s\n" OPERATOR_COMPONENT_LABEL_DOMAIN $(OPERATOR_COMPONENT_LABEL_DOMAIN)
@printf " \033[33m%-35s\033[0m %s\n" IMAGE_REGISTRY $(IMAGE_REGISTRY)
@printf " \033[33m%-35s\033[0m %s\n" CONTROLLER_IMAGE_TAG $(CONTROLLER_IMAGE_TAG)
@printf " \033[33m%-35s\033[0m %s\n" ROUTER_IMAGE_TAG $(ROUTER_IMAGE_TAG)
@printf " \033[33m%-35s\033[0m %s\n" NATS_IMAGE_TAG $(NATS_IMAGE_TAG)
@printf " \033[33m%-35s\033[0m %s\n" VERSION_TAG $(VERSION_TAG)
@echo ""
@grep -h -E '^[a-zA-Z_.-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'