Repository navigation
Expand file tree
/
Copy pathTaskfile.yaml
More file actions
399 lines (399 loc) · 16.9 KB
/
Copy pathTaskfile.yaml
File metadata and controls
399 lines (399 loc) · 16.9 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
version: '3'
vars:
LOCALBIN:
sh: echo "$(pwd)/bin"
GOBIN:
sh: |
gobin=$(go env GOBIN)
[ -n "$gobin" ] && echo "$gobin" || echo "$(go env GOPATH)/bin"
GOLANGCI_LINT: '{{.LOCALBIN}}/golangci-lint'
YAMLFMT: '{{.LOCALBIN}}/yamlfmt'
KUSTOMIZE: '{{.LOCALBIN}}/kustomize'
GO_LICENSES: '{{.LOCALBIN}}/go-licenses'
GOLANGCI_LINT_VERSION: v2.12.2
YAMLFMT_VERSION: v0.21.0
KUSTOMIZE_VERSION: v5.8.1
GO_LICENSES_VERSION: v1.6.0
PROMETHEUS_VERSION: v3.15.0
YQ_VERSION: 4.53.6
XRAY_VERSION: v26.10.21
XRAY_SHA256: 0eec3ed4163c273d8c8bf821f7d219e257921cf584aa3fb970715e458e631978
tasks:
default:
silent: true
cmds:
- task --list
##
## Development
##
fmt:
desc: Format code
run: once
cmds:
- go fmt ./...
vet:
desc: Vet code
run: once
cmds:
- GOOS=linux go vet ./...
ci:
desc: Run the full CI pipeline
cmds:
- task: lint
- task: build
- task: test:unit
- task: test:e2e
test:
desc: Run all tests
cmds:
- task: test:unit
- task: test:e2e
lint:
desc: Lint
deps: [golangci-lint, yamlfmt, yaml-ext, 'build:ebpf']
cmds:
- '{{.GOLANGCI_LINT}} run'
# examples/edge-provider and examples/looking-glass-client are their
# own modules, which the root run skips.
- cd examples/edge-provider && {{.GOLANGCI_LINT}} run --config ../../.golangci.yaml
- cd examples/looking-glass-client && {{.GOLANGCI_LINT}} run --config ../../.golangci.yaml
- '{{.YAMLFMT}} -lint'
lint-fix:
desc: Lint and apply fixes
deps: [golangci-lint, yamlfmt, 'build:ebpf']
cmds:
- '{{.GOLANGCI_LINT}} run --fix'
- '{{.YAMLFMT}}'
notice:
desc: Regenerate NOTICE file
deps: [go-licenses]
cmds:
- '{{.GO_LICENSES}} report ./... --ignore go.datum.net/galactic --template scripts/licenses/notice.tmpl > NOTICE'
##
## Build
##
build:
desc: Build binaries
cmds:
# build:ebpf must run before fmt/vet, not just before build:binaries:
# internal/plumbing/ebpf/prog's usid_bpfel.o/usid_bpfeb.o (go:embed'd)
# aren't committed (see .gitignore), so `go vet ./...` -- and anything
# else that type-checks the whole module -- fails to compile that
# package on a fresh checkout until this has generated them.
- task: build:ebpf
- task: fmt
- task: vet
- task: build:binaries
generate:proto:
desc: Regenerate api/**/*.pb.go from the .proto files (requires buf, protoc-gen-go, protoc-gen-go-grpc)
dir: api
cmds:
- buf lint
- buf generate
build:service-api:
desc: Build the Looking Glass service API release asset and its SHA256SUMS in dist/ (requires buf)
vars:
VERSION: '{{.VERSION | default "dev"}}'
cmds:
- hack/service-api-bundle.sh "{{.VERSION}}" dist
generate:crd:
desc: Regenerate all Galactic API deepcopy code and CRDs (requires controller-gen)
cmds:
- controller-gen object:headerFile=hack/boilerplate.go.txt paths=./internal/fabric/api/...
- controller-gen crd paths=./internal/fabric/api/... output:crd:artifacts:config=config/fabric-api/crd
- controller-gen object:headerFile=hack/boilerplate.go.txt paths=./api/v1alpha1/...
- controller-gen crd paths=./api/v1alpha1/... output:crd:artifacts:config=config/crd
- controller-gen object:headerFile=hack/boilerplate.go.txt paths=./api/cloud/v1alpha1/...
- controller-gen crd paths=./api/cloud/v1alpha1/... output:crd:artifacts:config=config/crd
- controller-gen object:headerFile=hack/boilerplate.go.txt paths=./api/network/v1alpha1/...
- controller-gen crd paths=./api/network/v1alpha1/... output:crd:artifacts:config=config/crd
generate:api-docs:
desc: Regenerate Galactic, cloud, BGP and gateway API references (install hack/docs/requirements.txt first)
cmds:
- python3 hack/docs/generate_api.py
docs:check:
desc: Check documentation links, anchors and API resource coverage (install hack/docs/requirements.txt first)
cmds:
- python3 -m unittest discover -s hack/docs -p 'test_*.py'
- python3 hack/docs/check.py
docs:check-generated:
desc: Check generated API references without changing tracked files (install hack/docs/requirements.txt first)
cmds:
- python3 hack/docs/generate_api.py --check
build:ebpf:
desc: Regenerate the eBPF uSID, edge gateway DSR, NAT egress, and XDP dispatcher datapaths (requires clang)
run: once
deps: [require-clang]
cmds:
- go generate ./internal/plumbing/ebpf/prog/...
- go generate ./internal/plumbing/ebpf/edgeprog/...
- go generate ./internal/plumbing/ebpf/natprog/...
- go generate ./internal/plumbing/ebpf/xdpdispatch/...
require-clang:
internal: true
run: once
cmds:
- |
if ! command -v "${BPF2GO_CC:-clang}" >/dev/null 2>&1; then
echo "ERROR: ${BPF2GO_CC:-clang} not found on PATH." >&2
echo "internal/plumbing/ebpf/prog/usid_bpfel.o/usid_bpfeb.o are" >&2
echo "generated from usid.c via bpf2go, not committed to git (see" >&2
echo "internal/plumbing/ebpf/prog/doc.go) -- clang is required to" >&2
echo "build or test this module at all. Install, e.g.:" >&2
echo " Fedora/RHEL: sudo dnf install clang llvm" >&2
echo " Debian/Ubuntu: sudo apt install clang llvm" >&2
exit 1
fi
build:binaries:
internal: true
vars:
VERSION:
sh: git describe --tags --always --dirty 2>/dev/null || echo "dev"
GIT_COMMIT:
sh: git rev-parse --short HEAD
GIT_TREE_STATE:
sh: git diff --quiet && echo "clean" || echo "dirty"
BUILD_DATE:
sh: date -u +%Y-%m-%dT%H:%M:%SZ
SPDX_LICENSE: AGPL-3.0-or-later
GIT_URL: https://github.com/datum-cloud/galactic
LDFLAGS: >-
-s -w -X go.datum.net/galactic/internal/metadata.Version={{.VERSION}} -X go.datum.net/galactic/internal/metadata.GitCommit={{.GIT_COMMIT}} -X go.datum.net/galactic/internal/metadata.GitTreeState={{.GIT_TREE_STATE}} -X go.datum.net/galactic/internal/metadata.BuildDate={{.BUILD_DATE}} -X go.datum.net/galactic/internal/metadata.SPDXLicense={{.SPDX_LICENSE}} -X go.datum.net/galactic/internal/metadata.GitURL={{.GIT_URL}}
cmds:
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-cni ./cmd/galactic-cni
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-veth ./cmd/galactic-veth
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-tap ./cmd/galactic-tap
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-ipam ./cmd/galactic-ipam
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-bgp ./cmd/galactic-bgp
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-route ./cmd/galactic-route
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-router ./cmd/galactic-router
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-gateway ./cmd/galactic-gateway
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-nat ./cmd/galactic-nat
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-vrf ./cmd/galactic-vrf
- go build -ldflags "{{.LDFLAGS}}" -o bin/fabric-config-agent ./cmd/fabric-config-agent
- go build -ldflags "{{.LDFLAGS}}" -o bin/fabric-api ./cmd/fabric-api
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-controller ./cmd/galactic-controller
- go build -ldflags "{{.LDFLAGS}}" -o bin/galactic-usid ./cmd/galactic-usid
- GOBIN={{.LOCALBIN}} go install github.com/containernetworking/plugins/plugins/main/host-device@v1.9.1
##
## CI
##
test:unit:
desc: Unit tests with race detection and coverage
deps: ['build:ebpf']
cmds:
- bash scripts/ci.sh unittest
- task: test:edge-provider
- task: test:looking-glass-client
test:edge-provider:
desc: Build, vet and unit-test the reference edge provider (examples/edge-provider, its own module)
dir: examples/edge-provider
cmds:
- go build ./...
- go vet ./...
- go test -race ./...
test:looking-glass-client:
desc: Build, vet and unit-test the independent Looking Glass client (examples/looking-glass-client, its own module)
dir: examples/looking-glass-client
cmds:
- go build ./...
- go vet ./...
- go test -race ./...
# The client must build from the published service API alone.
- |
if go list -deps ./... | grep -E '^go\.datum\.net/galactic/' | grep -vxE 'go\.datum\.net/galactic/api/fabric/(service/)?v1'; then
echo "the client imports Galactic packages beyond the published service API" >&2
exit 1
fi
test:unit-root:
desc: Re-run just the requireRoot(t)-gated unit tests, as root
deps: ['build:ebpf']
cmds:
- bash scripts/ci.sh unittest-root
test:fabric-api-load:
desc: Measure fabric-api queries against FRR with full Internet tables (MRT=<rib files, comma-separated>, needs Docker)
# The release gate for enabling AS-path and community searches: bgpd
# CPU and memory, session stability and convergence under query load.
# MRT is an uncompressed TABLE_DUMP_V2 RIB, e.g. a RouteViews
# rib.YYYYMMDD.HHMM; gobgpd/gobgp are built at the module's own version.
requires:
vars: [MRT]
vars:
GOBGP_BIN: '{{.LOCALBIN}}/gobgp-tools'
cmds:
- mkdir -p {{.GOBGP_BIN}}
- CGO_ENABLED=0 GOBIN={{.GOBGP_BIN}} go install github.com/osrg/gobgp/v4/cmd/gobgpd@v4.10.0 github.com/osrg/gobgp/v4/cmd/gobgp@v4.10.0
- go run ./hack/fabric-api-loadtest --mrt {{.MRT}} --gobgp-bin {{.GOBGP_BIN}} {{.CLI_ARGS}}
test:manifests:
desc: Render the opt-in Component fixtures in tests/manifests and check every manifest's log settings
# Every fixture under tests/manifests/fabric-api and
# tests/manifests/masque composes Components the way a cell overlay does
# and must build; every fixture under
# tests/manifests/invalid omits a Component another requires and must
# fail to build.
#
# Those fixtures and every kustomization under config/ and deploy/,
# except Components, are rendered and checked for a LOG_LEVEL or
# --log-level that internal/logging rejects, and for the removed
# LOG_FORMAT and --log-format or the local-only --zap-devel.
# The containerlab overlays under deploy/containerlab/resources build
# only once the lab scripts copy config/ onto a node, so they are not
# rendered here; their source YAML, inline patches included, is checked
# instead.
deps: [kustomize]
cmds:
- go build -o {{.LOCALBIN}}/check-log-settings ./hack/check-log-settings
- |
status=0
for file in $(find config deploy tests/manifests -name kustomization.yaml | sort); do
dir=$(dirname "$file")
case "$dir" in deploy/containerlab/resources/*|tests/manifests/invalid/*) continue ;; esac
grep -q '^kind: Component$' "$file" && continue
if ! out=$({{.KUSTOMIZE}} build "$dir"); then
echo "FAIL: $dir does not build"; status=1; continue
fi
if ! printf '%s\n' "$out" | {{.LOCALBIN}}/check-log-settings -label "$dir" -; then
echo "FAIL: $dir sets an unsupported log setting"; status=1
fi
done
if ! find config deploy tests/manifests -name '*.yaml' -print0 | xargs -0 {{.LOCALBIN}}/check-log-settings; then
echo "FAIL: source YAML sets an unsupported log setting"; status=1
fi
for dir in tests/manifests/invalid/*/; do
if {{.KUSTOMIZE}} build "$dir" > /dev/null 2>&1; then
echo "FAIL: $dir builds, but omits a required Component"; status=1
fi
done
exit $status
test:alerts:
desc: Unit-test the alert rules in config/monitoring/ with promtool
# promtool reads plain rule files, so the PrometheusRule's spec is
# extracted first. Both tools run from pinned images, so nothing needs
# installing. CI runs it in its own job rather than through ci.
vars:
ALERTS_DIR: '{{.LOCALBIN}}/alerts-test'
cmds:
- mkdir -p {{.ALERTS_DIR}}
- docker run --rm -i mikefarah/yq:{{.YQ_VERSION}} '.spec' < config/monitoring/prometheusrule.yaml > {{.ALERTS_DIR}}/rules.yaml
- cp config/monitoring/tests/rules-test.yaml {{.ALERTS_DIR}}/
- docker run --rm -v {{.ALERTS_DIR}}:/t -w /t --entrypoint promtool prom/prometheus:{{.PROMETHEUS_VERSION}} check rules rules.yaml
- docker run --rm -v {{.ALERTS_DIR}}:/t -w /t --entrypoint promtool prom/prometheus:{{.PROMETHEUS_VERSION}} test rules rules-test.yaml
test:connectip-interop:
desc: Prove CONNECT-IP over HTTP/3 and HTTP/2 against the pinned Xray client (linux/amd64, needs sudo and nftables)
# Not part of ci: the suite creates network namespaces and a TUN device
# as root. Results land in bin/connectip-interop (results.json and every
# client's log); see docs/edge/connectip-interop.md.
vars:
XRAY_DIR: '{{.LOCALBIN}}/xray-{{.XRAY_VERSION}}'
ARTIFACTS: '{{.LOCALBIN}}/connectip-interop'
cmds:
- mkdir -p {{.XRAY_DIR}}
- |
if [ ! -x {{.XRAY_DIR}}/xray ]; then
curl -fsSL -o {{.XRAY_DIR}}/xray.zip https://github.com/XTLS/Xray-core/releases/download/{{.XRAY_VERSION}}/Xray-linux-64.zip
echo "{{.XRAY_SHA256}} {{.XRAY_DIR}}/xray.zip" | sha256sum -c -
unzip -o -q {{.XRAY_DIR}}/xray.zip xray -d {{.XRAY_DIR}}
fi
- go test -c -race -o {{.LOCALBIN}}/connectip-interop.test ./tests/connectipinterop/
- rm -rf {{.ARTIFACTS}}
- sudo env CONNECTIP_INTEROP_XRAY={{.XRAY_DIR}}/xray CONNECTIP_INTEROP_ARTIFACTS={{.ARTIFACTS}} {{.LOCALBIN}}/connectip-interop.test -test.v -test.count=1 -test.timeout=10m
test:connectip-load:
desc: Measure CONNECT-IP capacity per transport on loopback (see docs/edge/masque-capacity.md)
# Not part of ci: one run takes about 15 minutes and loads every CPU.
# CONNECTIP_LOAD_DURATION, _WARMUP, _RUNS and _CONNECTORS override the
# defaults. The report lands in bin/connectip-load (report.md and
# report.json).
vars:
ARTIFACTS: '{{.LOCALBIN}}/connectip-load'
env:
CONNECTIP_LOAD: '1'
CONNECTIP_LOAD_RUNS: '{{.CONNECTIP_LOAD_RUNS | default "3"}}'
CONNECTIP_LOAD_REPORT: '{{.ARTIFACTS}}/report.md'
cmds:
- mkdir -p {{.ARTIFACTS}}
- go test ./internal/edge/connectip -run '^TestLoad$' -count=1 -v -timeout 90m
test:fabric-parity:
desc: Compile every fabric frr.conf back through the typed API and diff it with the pinned FRR's frr-reload
# Needs Docker, so it is not part of ci. The synthetic fixtures always
# run; set FABRIC_PARITY_DIR to a <cluster>/<node>.conf tree of rendered
# fabric-router configs to check real routers too.
cmds:
- go test -count=1 -tags frr -run 'TestImportCompileParity' ./internal/fabric/routing/
test:e2e:
desc: E2E tests (Kind cluster, build+load image, lifecycle)
# build:ebpf here is only for the host-side `go test ./tests/e2e/...`
# compile in scripts/ci.sh -- the galactic-cni image built inside
# ci.sh's docker build regenerates its own copy via the Dockerfile.
deps: ['build:ebpf']
cmds:
- bash scripts/ci.sh e2etest
##
## Cleanup
##
clean:
desc: Remove build artifacts
cmds:
- rm -rf bin/
- rm -rf dist/
- rm -f cover.out
##
## Dependencies
##
golangci-lint:
desc: Download golangci-lint if needed
run: once
cmds:
- task: install-tool
vars:
TARGET: '{{.GOLANGCI_LINT}}'
PACKAGE: github.com/golangci/golangci-lint/v2/cmd/golangci-lint
VERSION: '{{.GOLANGCI_LINT_VERSION}}'
kustomize:
desc: Download kustomize if needed
run: once
cmds:
- task: install-tool
vars:
TARGET: '{{.KUSTOMIZE}}'
PACKAGE: sigs.k8s.io/kustomize/kustomize/v5
VERSION: '{{.KUSTOMIZE_VERSION}}'
yamlfmt:
desc: Download yamlfmt if needed
run: once
cmds:
- task: install-tool
vars:
TARGET: '{{.YAMLFMT}}'
PACKAGE: github.com/google/yamlfmt/cmd/yamlfmt
VERSION: '{{.YAMLFMT_VERSION}}'
yaml-ext:
desc: Enforce .yaml extension (no .yml)
run: once
cmds:
- |
if find . -name "*.yml" -not -path "./.git/*" -not -path "./deploy/containerlab/clab-gvpc/*" | grep -q .; then
find . -name "*.yml" -not -path "./.git/*" -not -path "./deploy/containerlab/clab-gvpc/*"
echo "ERROR: .yml files found; rename to .yaml"
exit 1
fi
go-licenses:
internal: true
run: once
cmds:
- task: install-tool
vars:
TARGET: '{{.GO_LICENSES}}'
PACKAGE: github.com/google/go-licenses
VERSION: '{{.GO_LICENSES_VERSION}}'
install-tool:
internal: true
cmds:
- mkdir -p {{.LOCALBIN}}
- |-
if [ ! -f "{{.TARGET}}-{{.VERSION}}" ]; then
echo "Downloading {{.PACKAGE}}@{{.VERSION}}"
rm -f "{{.TARGET}}" || true
GOBIN={{.LOCALBIN}} go install {{.PACKAGE}}@{{.VERSION}}
mv "{{.TARGET}}" "{{.TARGET}}-{{.VERSION}}"
fi
ln -sf "{{.TARGET}}-{{.VERSION}}" "{{.TARGET}}"