-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathMakefile
More file actions
454 lines (389 loc) · 18.6 KB
/
Makefile
File metadata and controls
454 lines (389 loc) · 18.6 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
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
.PHONY: all build build-klor build-linux build-klor-linux test test-linux test-bpf-helpers e2e e2e-setup e2e-run e2e-cleanup e2e-klor e2e-klor-rooted \
e2e-k3s e2e-k3s-setup e2e-k3s-run e2e-k3s-cleanup \
clean deps docker-build generate-ebpf generate-vmlinux run help \
lima-start lima-stop lima-delete lima-shell lima-exec lima-check \
lima-k3d-ensure lima-k3d-shell lima-k3d-e2e-setup lima-k3d-e2e-run lima-k3d-e2e lima-k3d-stop lima-k3d-delete \
go-tls-fixtures go-tls-discover
# Go parameters
GOCMD=go
GOBUILD=$(GOCMD) build
GOCLEAN=$(GOCMD) clean
GOTEST=$(GOCMD) test
GOMOD=$(GOCMD) mod
GOGENERATE=$(GOCMD) generate
# Binary names
BINARY_NAME=kloak
WEBHOOK_BINARY=kloak-webhook
# Klor — the host-CLI runtime. Separate `main` package at cmd/klor/ so its
# dependency closure shrinks independently (no k8s.io/client-go, no
# controller-runtime). Not part of the controller Docker image.
KLOR_BINARY=klor
# Release tag baked into the binary for `kloak version`. `git describe
# --tags --always --dirty` gives `v0.1.0` exactly on tag, `v0.1.0-3-gabc1234-dirty`
# between tags with uncommitted changes, and falls back to the short
# commit when no tags exist. CI release builds override VERSION explicitly.
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo dev)
LDFLAGS = -ldflags "-X main.version=$(VERSION)"
# Build directories
BUILD_DIR=bin
CMD_DIR=cmd
BPF_DIR=pkg/ebpf
EBPF_PKG=pkg/ebpf
# Source files
GO_SOURCES=$(shell find . -name '*.go' -not -path './vendor/*')
BPF_SOURCES=$(wildcard $(BPF_DIR)/*.c $(BPF_DIR)/*.h)
EBPF_GENERATED=$(EBPF_PKG)/tlsuprobe_bpfel.go $(EBPF_PKG)/tlsuprobe_bpfeb.go
# Docker
DOCKER_IMAGE=kloak
DOCKER_TAG=latest
# Lima VM
LIMA_VM=kloak
LIMA_WORKDIR=$(shell pwd)
LIMA_CONFIG=lima.yaml
# ============================================================================
# Main targets
# ============================================================================
all: build build-klor
# Build depends on Go sources (and generated eBPF on Linux)
build: deps $(BUILD_DIR)/$(BINARY_NAME)
$(BUILD_DIR)/$(BINARY_NAME): $(GO_SOURCES)
@mkdir -p $(BUILD_DIR)
$(GOBUILD) $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME) ./$(CMD_DIR)/kloak
# Build the klor host-CLI binary. Sibling of `build`; lives at cmd/klor/.
build-klor: deps $(BUILD_DIR)/$(KLOR_BINARY)
$(BUILD_DIR)/$(KLOR_BINARY): $(GO_SOURCES)
@mkdir -p $(BUILD_DIR)
$(GOBUILD) $(LDFLAGS) -o $(BUILD_DIR)/$(KLOR_BINARY) ./$(CMD_DIR)/klor
# Build for Linux (cross-compile or via Lima)
build-linux: lima-ensure
@if [ "$$(uname)" = "Linux" ]; then \
GOOS=linux GOARCH=amd64 $(GOBUILD) $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-linux ./$(CMD_DIR)/kloak; \
else \
$(MAKE) lima-exec CMD="cd $(LIMA_WORKDIR) && go build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-linux ./$(CMD_DIR)/kloak"; \
fi
build-klor-linux: lima-ensure
@if [ "$$(uname)" = "Linux" ]; then \
GOOS=linux GOARCH=amd64 $(GOBUILD) $(LDFLAGS) -o $(BUILD_DIR)/$(KLOR_BINARY)-linux ./$(CMD_DIR)/klor; \
else \
$(MAKE) lima-exec CMD="cd $(LIMA_WORKDIR) && go build $(LDFLAGS) -o $(BUILD_DIR)/$(KLOR_BINARY)-linux ./$(CMD_DIR)/klor"; \
fi
test: deps
$(GOTEST) -v ./...
# Run tests in Linux VM (for eBPF tests) - depends on Lima running
test-linux: lima-ensure
$(MAKE) lima-exec CMD="cd $(LIMA_WORKDIR) && go test -v ./..."
# Run eBPF helper unit tests (pure C, no Linux/BPF required)
test-bpf-helpers:
gcc -Wall -Werror -o /tmp/helpers_test pkg/ebpf/bpf/helpers_test.c
/tmp/helpers_test
# Build a tiny Go binary against every supported Go version × arch using
# Docker. Outputs ELF fixtures to pkg/ebpf/testdata/go-tls-fixtures/.
# Used by the table-driven DWARF test in pkg/ebpf/go_tls_offsets_test.go.
# Containers spin once per (version, arch) — never per test invocation.
# Override versions with: GO_VERSIONS="1.23 1.24" make go-tls-fixtures
go-tls-fixtures:
tools/go-tls-offsets/build-fixtures.sh
# Run the existing tools/go-tls-offsets discovery tool against every
# fixture from `make go-tls-fixtures`, writing JSON results to
# tools/go-tls-offsets/results/. The JSONs are the canonical reference
# the in-tree test asserts against. Depends on go-tls-fixtures.
go-tls-discover: go-tls-fixtures
tools/go-tls-offsets/discover-all.sh
# E2E cluster and image configuration
E2E_CLUSTER=kloak-e2e
E2E_IMAGE_TAG=e2e
# Full e2e: setup cluster, run tests, tear down.
e2e: e2e-setup e2e-run e2e-cleanup
# Create k3d cluster with BPF mounts, build and import all images.
e2e-setup:
@which k3d > /dev/null || (echo "Error: k3d not found. Install with: brew install k3d" && exit 1)
@mountpoint -q /sys/kernel/tracing 2>/dev/null || sudo mount -t tracefs tracefs /sys/kernel/tracing 2>/dev/null || true
@echo "==> Creating k3d cluster '$(E2E_CLUSTER)' with BPF mounts..."
@k3d cluster create $(E2E_CLUSTER) --wait --timeout 120s \
--volume /sys/kernel/btf:/sys/kernel/btf:ro@server:0 \
--volume /sys/fs/bpf:/sys/fs/bpf:rw@server:0 \
--volume /sys/kernel/tracing:/sys/kernel/tracing:rw@server:0 \
2>/dev/null || true
@echo "==> Building kloak image..."
@docker build -t $(DOCKER_IMAGE):$(E2E_IMAGE_TAG) .
@echo "==> Building demo images..."
@docker build -t kloak-demo-go:$(E2E_IMAGE_TAG) -t kloak-demo-go:latest ./examples/demo-go/
@docker build -t kloak-demo-python:latest ./examples/demo-python/
@docker build -t kloak-demo-js:latest ./examples/demo-js/
@docker build -t kloak-demo-go-boring:latest ./examples/demo-go-boring/
@docker build -t kloak-demo-gnutls:latest ./examples/demo-gnutls/
@docker build -t kloak-demo-python-raw-tls:latest ./examples/demo-python-raw-tls/
@docker build -t kloak-tls-echo:latest ./test/e2e/tls-echo-server/
@echo "==> Importing images into k3d (via tar to avoid pipe EOF)..."
@mkdir -p /tmp/k3d-images
@for img in $(DOCKER_IMAGE):$(E2E_IMAGE_TAG) kloak-demo-go:latest kloak-demo-python:latest \
kloak-demo-js:latest kloak-demo-go-boring:latest kloak-demo-gnutls:latest \
kloak-demo-python-raw-tls:latest kloak-tls-echo:latest; do \
echo " Importing $$img..."; \
docker save $$img -o /tmp/k3d-images/$$(echo $$img | tr ':/' '__').tar && \
k3d image import /tmp/k3d-images/$$(echo $$img | tr ':/' '__').tar -c $(E2E_CLUSTER); \
done
@rm -rf /tmp/k3d-images
@echo "==> E2E environment ready."
# Run e2e tests (including eBPF) against an existing k3d cluster.
e2e-run:
KUBECONFIG=$$(k3d kubeconfig write $(E2E_CLUSTER)) \
$(GOTEST) -v -timeout 1500s -tags=e2e_ebpf -count=1 ./test/e2e/
# klor e2e — builds the klor binary and exercises its CLI against
# a tempdir cgroup root. No cluster, no root required (Linux-only,
# skips on macOS). Cheap; safe to run as part of unit-test CI.
e2e-klor:
$(GOTEST) -v -timeout 120s -tags=e2e_klor -count=1 ./test/e2e/klor/
# klor rootless e2e — exercises install.sh + cap-on-binary so klor
# runs without sudo. TestMain skips unless running as root (so
# install.sh can setcap); the test itself then drops to a non-root
# uid via setpriv to prove the cap-on-binary path actually delivers
# the privilege drop. CI's ubuntu-latest runs root by default; dev
# hosts use `sudo make e2e-klor-rooted`.
e2e-klor-rooted:
$(GOTEST) -v -timeout 180s -tags=e2e_klor_rooted -count=1 ./test/e2e/klor/
# Run e2e tests against the current kube context.
# Builds images, pushes to ttl.sh (anonymous ephemeral registry, 2h TTL),
# and runs tests with E2E_REGISTRY so images are pulled from there.
# Set E2E_REGISTRY to use a different registry (e.g. localhost:5000).
# WARNING: This will helm install/uninstall kloak in kloak-system and
# create/delete a kloak-e2e namespace.
# Usage: make e2e-local
E2E_TTL_TAG ?= kloak-$(shell date +%s)
E2E_REGISTRY ?= ttl.sh/$(E2E_TTL_TAG)
e2e-local: e2e-local-push e2e-local-run
e2e-local-push:
@echo "==> Building and pushing images to $(E2E_REGISTRY) ..."
@docker build -t $(E2E_REGISTRY)/kloak:e2e .
@docker push $(E2E_REGISTRY)/kloak:e2e
@for demo in demo-go demo-python demo-js demo-go-boring demo-gnutls demo-python-raw-tls; do \
echo " Pushing kloak-$$demo..."; \
docker build -t $(E2E_REGISTRY)/kloak-$$demo:latest ./examples/$$demo/ && \
docker push $(E2E_REGISTRY)/kloak-$$demo:latest; \
done
@docker build -t $(E2E_REGISTRY)/kloak-tls-echo:latest ./test/e2e/tls-echo-server/
@docker push $(E2E_REGISTRY)/kloak-tls-echo:latest
@echo "==> All images pushed."
# E2E_RUN: optional -run filter (e.g. E2E_RUN=TestCipherSuites make e2e-local)
E2E_RUN ?=
e2e-local-run:
E2E_REGISTRY=$(E2E_REGISTRY) E2E_SKIP_INSTALL=$(E2E_SKIP_INSTALL) \
$(GOTEST) -v -timeout 1500s -tags=e2e_ebpf -count=1 $(if $(E2E_RUN),-run $(E2E_RUN)) ./test/e2e/
# Tear down e2e k3d cluster.
e2e-cleanup:
@k3d cluster delete $(E2E_CLUSTER) 2>/dev/null || true
# ============================================================================
# k3s-native e2e targets (for CI / Linux workstations — no Docker nesting)
# ============================================================================
# Full k3s e2e: setup + run + cleanup.
e2e-k3s: e2e-k3s-setup e2e-k3s-run e2e-k3s-cleanup
# Install k3s, build all images, import into k3s containerd.
e2e-k3s-setup:
@echo "==> Installing k3s..."
@curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--write-kubeconfig-mode 644 --disable=traefik" sh -
@echo "==> Waiting for k3s node to register..."
@for i in $$(seq 1 30); do \
sudo k3s kubectl get nodes -o name 2>/dev/null | grep -q . && break; \
echo " Waiting for k3s node ($$i/30)..."; \
sleep 2; \
done
@sudo k3s kubectl wait --for=condition=Ready node --all --timeout=120s
@mkdir -p $(HOME)/.kube
@sudo cp /etc/rancher/k3s/k3s.yaml $(HOME)/.kube/k3s-e2e.yaml
@sudo chown $$(id -u):$$(id -g) $(HOME)/.kube/k3s-e2e.yaml
@chmod 600 $(HOME)/.kube/k3s-e2e.yaml
@echo "==> Building images..."
@docker build --build-arg TARGETARCH=$$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') \
--build-arg COVER=1 -t $(DOCKER_IMAGE):$(E2E_IMAGE_TAG) .
@docker build -t kloak-demo-go:$(E2E_IMAGE_TAG) -t kloak-demo-go:latest ./examples/demo-go/
@docker build -t kloak-demo-python:latest ./examples/demo-python/
@docker build -t kloak-demo-js:latest ./examples/demo-js/
@docker build -t kloak-demo-go-boring:latest ./examples/demo-go-boring/
@docker build -t kloak-demo-gnutls:latest ./examples/demo-gnutls/
@docker build -t kloak-demo-python-raw-tls:latest ./examples/demo-python-raw-tls/
@docker build -t kloak-tls-echo:latest ./test/e2e/tls-echo-server/
@echo "==> Importing images into k3s containerd..."
@docker save $(DOCKER_IMAGE):$(E2E_IMAGE_TAG) kloak-demo-go:latest kloak-demo-python:latest \
kloak-demo-js:latest kloak-demo-go-boring:latest kloak-demo-gnutls:latest \
kloak-demo-python-raw-tls:latest kloak-tls-echo:latest | sudo k3s ctr -n k8s.io images import -
@echo "==> k3s e2e environment ready."
# Run e2e tests against local k3s.
e2e-k3s-run:
KUBECONFIG=$(HOME)/.kube/k3s-e2e.yaml \
$(GOTEST) -v -timeout 1500s -tags=e2e_ebpf -count=1 $(if $(E2E_RUN),-run $(E2E_RUN)) ./test/e2e/
# Tear down k3s.
e2e-k3s-cleanup:
@sudo /usr/local/bin/k3s-killall.sh 2>/dev/null || true
@sudo /usr/local/bin/k3s-uninstall.sh 2>/dev/null || true
@rm -f $(HOME)/.kube/k3s-e2e.yaml
clean:
$(GOCLEAN)
rm -rf $(BUILD_DIR)
rm -f $(EBPF_PKG)/tlsuprobe_bpfel.go $(EBPF_PKG)/tlsuprobe_bpfeb.go
rm -f $(EBPF_PKG)/tlsuprobe_bpfel.o $(EBPF_PKG)/tlsuprobe_bpfeb.o
deps:
$(GOMOD) download
$(GOMOD) tidy
docker-build: build
docker build -t $(DOCKER_IMAGE):$(DOCKER_TAG) .
run: build
./$(BUILD_DIR)/$(BINARY_NAME)
# ============================================================================
# eBPF generation targets
# ============================================================================
# Generate eBPF code - depends on BPF sources and vmlinux.h.
# KLOAK_TARGET_ARCH defaults to arm64 (Lima VM). Set to x86 for amd64 builds.
generate-ebpf: $(BPF_SOURCES) $(BPF_DIR)/vmlinux.h lima-ensure
@echo "Generating eBPF code (arch=$${KLOAK_TARGET_ARCH:-arm64})..."
@if [ "$$(uname)" = "Linux" ]; then \
cd $(EBPF_PKG) && $(GOGENERATE); \
else \
echo "Using Lima VM for eBPF generation..."; \
$(MAKE) lima-exec CMD="cd $(LIMA_WORKDIR)/$(EBPF_PKG) && KLOAK_TARGET_ARCH=$${KLOAK_TARGET_ARCH:-arm64} go generate"; \
fi
@echo "eBPF generation complete."
# Generate vmlinux.h from kernel BTF - depends on Lima
$(BPF_DIR)/vmlinux.h: lima-ensure
@echo "Generating vmlinux.h from kernel BTF..."
@if [ "$$(uname)" = "Linux" ]; then \
bpftool btf dump file /sys/kernel/btf/vmlinux format c > $@; \
else \
$(MAKE) lima-exec CMD="bpftool btf dump file /sys/kernel/btf/vmlinux format c > $(LIMA_WORKDIR)/$@"; \
fi
generate-vmlinux: $(BPF_DIR)/vmlinux.h
# ============================================================================
# Lima VM targets (for eBPF development on macOS)
# ============================================================================
# Check if Lima is installed
lima-check:
@if [ "$$(uname)" = "Linux" ]; then \
exit 0; \
else \
which limactl > /dev/null || (echo "Error: limactl not found. Install with: brew install lima" && exit 1); \
fi
# Ensure Lima VM is running (idempotent)
lima-ensure: lima-check $(LIMA_CONFIG)
@if [ "$$(uname)" = "Linux" ]; then \
exit 0; \
elif ! limactl list 2>/dev/null | grep -q "^$(LIMA_VM)"; then \
echo "Creating Lima VM '$(LIMA_VM)'..."; \
limactl start --name=$(LIMA_VM) $(LIMA_CONFIG); \
elif limactl list | grep "^$(LIMA_VM)" | grep -q "Stopped"; then \
echo "Starting Lima VM '$(LIMA_VM)'..."; \
limactl start $(LIMA_VM); \
fi
# Start Lima VM for eBPF development
lima-start: lima-check $(LIMA_CONFIG)
@if ! limactl list 2>/dev/null | grep -q "^$(LIMA_VM)"; then \
echo "Creating Lima VM '$(LIMA_VM)'..."; \
limactl start --name=$(LIMA_VM) $(LIMA_CONFIG); \
elif limactl list | grep "^$(LIMA_VM)" | grep -q "Stopped"; then \
echo "Starting Lima VM '$(LIMA_VM)'..."; \
limactl start $(LIMA_VM); \
else \
echo "Lima VM '$(LIMA_VM)' is already running"; \
fi
# Stop Lima VM
lima-stop:
@limactl stop $(LIMA_VM) 2>/dev/null || true
# Delete Lima VM
lima-delete: lima-stop
@limactl delete $(LIMA_VM) 2>/dev/null || true
# Shell into Lima VM
lima-shell: lima-ensure
limactl shell $(LIMA_VM)
# Execute command in Lima VM (uses login shell for proper PATH)
lima-exec: lima-ensure
@limactl shell $(LIMA_VM) -- bash -lc '$(CMD)'
# ============================================================================
# Lima k3d targets (for e2e testing on ARM Mac)
# ============================================================================
LIMA_K3D_VM=kloak-k3d
LIMA_K3D_CONFIG=lima-k3d.yaml
# Ensure k3d Lima VM is running
lima-k3d-ensure: lima-check $(LIMA_K3D_CONFIG)
@if ! limactl list 2>/dev/null | grep -q "^$(LIMA_K3D_VM)"; then \
echo "Creating Lima k3d VM '$(LIMA_K3D_VM)'..."; \
limactl start --name=$(LIMA_K3D_VM) $(LIMA_K3D_CONFIG); \
elif limactl list | grep "^$(LIMA_K3D_VM)" | grep -q "Stopped"; then \
echo "Starting Lima k3d VM '$(LIMA_K3D_VM)'..."; \
limactl start $(LIMA_K3D_VM); \
fi
# Shell into k3d Lima VM
lima-k3d-shell: lima-k3d-ensure
limactl shell $(LIMA_K3D_VM)
# Run e2e setup inside k3d Lima VM
lima-k3d-e2e-setup: lima-k3d-ensure
limactl shell $(LIMA_K3D_VM) -- bash -lc 'sg docker -c "cd $(LIMA_WORKDIR) && make e2e-setup"'
# Run e2e tests inside k3d Lima VM
lima-k3d-e2e-run: lima-k3d-ensure
limactl shell $(LIMA_K3D_VM) -- bash -lc 'sg docker -c "cd $(LIMA_WORKDIR) && make e2e-run"'
# Full e2e inside k3d Lima VM
lima-k3d-e2e: lima-k3d-e2e-setup lima-k3d-e2e-run
# Stop k3d Lima VM
lima-k3d-stop:
@limactl stop $(LIMA_K3D_VM) 2>/dev/null || true
# Delete k3d Lima VM
lima-k3d-delete: lima-k3d-stop
@limactl delete $(LIMA_K3D_VM) 2>/dev/null || true
# ============================================================================
# Help
# ============================================================================
help:
@echo "Kloak Makefile - Kubernetes eBPF HTTPS Interceptor"
@echo ""
@echo "Build targets:"
@echo " all - Build both kloak and klor binaries"
@echo " build - Build the kloak binary (native)"
@echo " build-klor - Build the klor host-CLI binary (native)"
@echo " build-linux - Build kloak for Linux (uses Lima on macOS)"
@echo " build-klor-linux - Build klor for Linux (uses Lima on macOS)"
@echo " clean - Clean build artifacts"
@echo " deps - Download and tidy dependencies"
@echo " docker-build - Build Docker image"
@echo " run - Build and run kloak locally"
@echo ""
@echo "Test targets:"
@echo " test - Run unit tests"
@echo " test-linux - Run tests in Lima VM (needed for eBPF tests)"
@echo " test-bpf-helpers - Run eBPF helper C unit tests"
@echo ""
@echo "k3d-based e2e (k8s tests; macOS-friendly via Docker):"
@echo " e2e - Full e2e: setup + run + cleanup"
@echo " e2e-setup - Create k3d cluster with BPF mounts and import images"
@echo " e2e-run - Run e2e tests against the existing k3d cluster"
@echo " e2e-cleanup - Delete e2e k3d cluster"
@echo " e2e-local - Build + push images to ttl.sh and run e2e against current kube context"
@echo " e2e-local-push - Build + push e2e images to ttl.sh (or E2E_REGISTRY)"
@echo " e2e-local-run - Run e2e against existing kube context (assumes images pushed)"
@echo ""
@echo "k3s-native e2e (CI / Linux workstations — no Docker nesting):"
@echo " e2e-k3s - Full e2e: setup + run + cleanup (k3s-native)"
@echo " e2e-k3s-setup - Install k3s, build and import images"
@echo " e2e-k3s-run - Run e2e tests against local k3s"
@echo " e2e-k3s-cleanup - Uninstall k3s"
@echo ""
@echo "klor e2e (no cluster required):"
@echo " e2e-klor - Build klor and exercise its CLI (Linux-only; self-skips on macOS)"
@echo " e2e-klor-rooted - Run install.sh + verify cap-on-binary lets klor run without sudo (needs root)"
@echo ""
@echo "eBPF code generation:"
@echo " generate-ebpf - Generate eBPF Go bindings (uses Lima on macOS)"
@echo " generate-vmlinux - Generate vmlinux.h from kernel BTF"
@echo " go-tls-fixtures - Build / refresh Go TLS offset fixtures"
@echo " go-tls-discover - Discover new Go TLS offsets across versions"
@echo ""
@echo "Lima VM (for eBPF on macOS):"
@echo " lima-start - Start the Lima VM"
@echo " lima-stop - Stop the Lima VM"
@echo " lima-delete - Delete the Lima VM"
@echo " lima-shell - Open shell in Lima VM"
@echo " lima-ensure - Ensure VM is running (idempotent)"
@echo ""
@echo "Lima k3d (for k8s e2e on ARM Mac):"
@echo " lima-k3d-shell - Shell into k3d Lima VM"
@echo " lima-k3d-e2e - Full e2e: setup + run inside Lima k3d VM"
@echo " lima-k3d-e2e-setup - Create k3d cluster inside Lima VM"
@echo " lima-k3d-e2e-run - Run e2e tests inside Lima VM"
@echo " lima-k3d-stop - Stop k3d Lima VM"
@echo " lima-k3d-delete - Delete k3d Lima VM"