Skip to content

Commit 9926ca9

Browse files
Reach release candidate readiness
1 parent e44a417 commit 9926ca9

40 files changed

Lines changed: 2729 additions & 607 deletions
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
kind: Cluster
2+
apiVersion: kind.x-k8s.io/v1alpha4
3+
nodes:
4+
- role: control-plane
5+
extraMounts:
6+
- hostPath: /dev/kvm
7+
containerPath: /dev/kvm
8+
- hostPath: /tmp/smolvm-kind-control-plane-var-lib
9+
containerPath: /var/lib/smolvm
10+
- hostPath: /tmp/smolvm-kind-control-plane-var-run
11+
containerPath: /var/run/smolvm
12+
- role: worker
13+
extraMounts:
14+
- hostPath: /dev/kvm
15+
containerPath: /dev/kvm
16+
- hostPath: /tmp/smolvm-kind-worker-var-lib
17+
containerPath: /var/lib/smolvm
18+
- hostPath: /tmp/smolvm-kind-worker-var-run
19+
containerPath: /var/run/smolvm
20+
- role: worker
21+
extraMounts:
22+
- hostPath: /dev/kvm
23+
containerPath: /dev/kvm
24+
- hostPath: /tmp/smolvm-kind-worker2-var-lib
25+
containerPath: /var/lib/smolvm
26+
- hostPath: /tmp/smolvm-kind-worker2-var-run
27+
containerPath: /var/run/smolvm

.github/kind-runtime-config.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
kind: Cluster
2+
apiVersion: kind.x-k8s.io/v1alpha4
3+
nodes:
4+
- role: control-plane
5+
extraMounts:
6+
- hostPath: /dev/kvm
7+
containerPath: /dev/kvm
8+
- hostPath: /tmp/smolvm-kind-var-lib
9+
containerPath: /var/lib/smolvm
10+
- hostPath: /tmp/smolvm-kind-var-run
11+
containerPath: /var/run/smolvm

.github/workflows/ci.yml

Lines changed: 177 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -6,128 +6,224 @@ on:
66
pull_request:
77
workflow_dispatch:
88

9+
permissions:
10+
contents: read
11+
packages: write
12+
913
jobs:
14+
lint:
15+
name: lint
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
- uses: actions/setup-go@v5
20+
with:
21+
go-version-file: go.mod
22+
cache: true
23+
- name: Run linters
24+
run: make lint
25+
26+
container-images:
27+
name: immutable container images
28+
runs-on: ubuntu-latest
29+
if: github.event_name != 'pull_request'
30+
steps:
31+
- uses: actions/checkout@v4
32+
- uses: docker/login-action@v3
33+
with:
34+
registry: ghcr.io
35+
username: ${{ github.actor }}
36+
password: ${{ secrets.GITHUB_TOKEN }}
37+
- name: Build and publish immutable images
38+
run: |
39+
docker build -t ghcr.io/${{ github.repository }}/smolvm-operator:${{ github.sha }} .
40+
docker build -f Dockerfile.runtime --build-arg SMOLVM_VERSION=0.8.1 -t ghcr.io/${{ github.repository }}/smolvm-runtime:${{ github.sha }} .
41+
docker push ghcr.io/${{ github.repository }}/smolvm-operator:${{ github.sha }}
42+
docker push ghcr.io/${{ github.repository }}/smolvm-runtime:${{ github.sha }}
43+
44+
release-artifact:
45+
name: install artifact dry run
46+
runs-on: ubuntu-latest
47+
steps:
48+
- uses: actions/checkout@v4
49+
- uses: actions/setup-go@v5
50+
with:
51+
go-version-file: go.mod
52+
cache: true
53+
- name: Build reproducible install artifact
54+
run: make rc-artifacts VERSION=ci IMG=ghcr.io/${{ github.repository }}/smolvm-operator:${{ github.sha }} RUNTIME_IMG=ghcr.io/${{ github.repository }}/smolvm-runtime:${{ github.sha }}
55+
- name: Upload install artifact
56+
uses: actions/upload-artifact@v4
57+
with:
58+
name: install-artifact
59+
path: dist/
60+
1061
envtest:
1162
name: envtest controller
1263
runs-on: ubuntu-latest
64+
needs: [lint]
1365
steps:
1466
- uses: actions/checkout@v4
1567
- uses: actions/setup-go@v5
1668
with:
1769
go-version-file: go.mod
1870
cache: true
1971
- name: Run controller-runtime envtest
20-
run: make test
72+
run: make test-report
73+
- name: Upload test reports
74+
if: always()
75+
uses: actions/upload-artifact@v4
76+
with:
77+
name: envtest-reports
78+
path: reports/
2179

2280
kind-e2e:
23-
name: kind e2e
81+
name: kind topology e2e
2482
runs-on: ubuntu-latest
83+
needs: [envtest, release-artifact]
2584
steps:
2685
- uses: actions/checkout@v4
2786
- uses: actions/setup-go@v5
2887
with:
2988
go-version-file: go.mod
3089
cache: true
90+
- name: Prepare KVM-backed multi-node kind mounts
91+
run: |
92+
set -euxo pipefail
93+
test -e /dev/kvm
94+
sudo chmod 666 /dev/kvm
95+
for node in control-plane worker worker2; do
96+
sudo mkdir -p "/tmp/smolvm-kind-${node}-var-lib" "/tmp/smolvm-kind-${node}-var-run"
97+
sudo chmod 777 "/tmp/smolvm-kind-${node}-var-lib" "/tmp/smolvm-kind-${node}-var-run"
98+
done
99+
- name: Build e2e images and manifest
100+
run: |
101+
docker build -t smolvm-operator:e2e .
102+
docker build -f Dockerfile.runtime --build-arg SMOLVM_VERSION=0.8.1 -t smolvm-runtime:e2e .
103+
make build-installer IMG=smolvm-operator:e2e RUNTIME_IMG=smolvm-runtime:e2e
31104
- uses: helm/kind-action@v1
32105
with:
33106
cluster_name: kind
34-
- name: Run one deployment e2e test
107+
config: .github/kind-kvm-multinode-config.yaml
108+
- name: Load e2e images
109+
run: |
110+
kind load docker-image smolvm-operator:e2e --name kind
111+
kind load docker-image smolvm-runtime:e2e --name kind
112+
- name: Run deployed topology e2e test
35113
env:
36114
RUN_E2E: "true"
115+
E2E_INSTALL_MANIFEST: dist/install.yaml
37116
KIND_CLUSTER: kind
38-
run: make test-e2e
117+
run: make test-e2e-report
118+
- name: Upload e2e reports
119+
if: always()
120+
uses: actions/upload-artifact@v4
121+
with:
122+
name: e2e-reports
123+
path: reports/
39124

40-
smolvm-runtime-smoke:
41-
name: smolvm runtime smoke
125+
smolvm-runtime-e2e:
126+
name: smolvm runtime lifecycle e2e
42127
runs-on: ubuntu-latest
43-
timeout-minutes: 20
128+
needs: [envtest, release-artifact]
129+
timeout-minutes: 45
44130
steps:
45131
- uses: actions/checkout@v4
46132
- uses: actions/setup-go@v5
47133
with:
48134
go-version-file: go.mod
49135
cache: true
136+
- name: Prepare KVM-backed multi-node kind mounts
137+
run: |
138+
set -euxo pipefail
139+
test -e /dev/kvm
140+
sudo chmod 666 /dev/kvm
141+
for node in control-plane worker worker2; do
142+
sudo mkdir -p "/tmp/smolvm-kind-${node}-var-lib" "/tmp/smolvm-kind-${node}-var-run"
143+
sudo chmod 777 "/tmp/smolvm-kind-${node}-var-lib" "/tmp/smolvm-kind-${node}-var-run"
144+
done
145+
- name: Build runtime e2e images and manifest
146+
run: |
147+
docker build -t smolvm-operator:runtime-e2e .
148+
docker build -f Dockerfile.runtime --build-arg SMOLVM_VERSION=0.8.1 -t smolvm-runtime:runtime-e2e .
149+
make build-installer IMG=smolvm-operator:runtime-e2e RUNTIME_IMG=smolvm-runtime:runtime-e2e
50150
- uses: helm/kind-action@v1
51151
with:
52152
cluster_name: runtime
53-
- name: Install smolvm
153+
config: .github/kind-kvm-multinode-config.yaml
154+
- name: Load runtime e2e images
54155
run: |
55-
sudo apt-get update
56-
sudo apt-get install -y libvirglrenderer1 libepoxy0 libgbm1
57-
curl -fsSL -o /tmp/smolvm.tar.gz https://github.com/smol-machines/smolvm/releases/download/v0.8.1/smolvm-0.8.1-linux-x86_64.tar.gz
58-
mkdir -p /tmp/smolvm
59-
tar -xzf /tmp/smolvm.tar.gz -C /tmp/smolvm --strip-components=1
60-
echo /tmp/smolvm >> "$GITHUB_PATH"
61-
/tmp/smolvm/smolvm --version
62-
- name: Run operator against real smolvm runtime
156+
kind load docker-image smolvm-operator:runtime-e2e --name runtime
157+
kind load docker-image smolvm-runtime:runtime-e2e --name runtime
158+
- name: Run runtime lifecycle e2e
159+
env:
160+
RUN_E2E: "true"
161+
E2E_INSTALL_MANIFEST: dist/install.yaml
162+
KIND_CLUSTER: runtime
163+
RUNTIME_E2E: "true"
164+
run: make test-runtime-e2e-report
165+
- name: Upload runtime logs
166+
if: always()
167+
uses: actions/upload-artifact@v4
168+
with:
169+
name: runtime-e2e-logs
170+
path: reports/
171+
172+
release-hardening-e2e:
173+
name: upgrade multi-node and failure gates
174+
runs-on: ubuntu-latest
175+
needs: [envtest, release-artifact]
176+
steps:
177+
- uses: actions/checkout@v4
178+
- uses: actions/setup-go@v5
179+
with:
180+
go-version-file: go.mod
181+
cache: true
182+
- name: Prepare KVM-backed multi-node kind mounts
63183
run: |
64184
set -euxo pipefail
185+
test -e /dev/kvm
65186
sudo chmod 666 /dev/kvm
66-
export LD_LIBRARY_PATH="/tmp/smolvm/lib:${LD_LIBRARY_PATH:-}"
67-
export LD_PRELOAD="$(find /usr/lib -name 'libvirglrenderer.so.1' | head -1)"
68-
smolvm serve start --listen 127.0.0.1:8080 > smolvm-serve.log 2>&1 &
69-
serve_pid=$!
70-
trap 'kubectl delete smolvm runtime-smoke --ignore-not-found=true --wait=false || true; kill $serve_pid || true; cat smolvm-serve.log || true' EXIT
71-
72-
for i in {1..60}; do
73-
curl -fsS http://127.0.0.1:8080/api/v1/machines && break
74-
sleep 1
187+
for node in control-plane worker worker2; do
188+
sudo mkdir -p "/tmp/smolvm-kind-${node}-var-lib" "/tmp/smolvm-kind-${node}-var-run"
189+
sudo chmod 777 "/tmp/smolvm-kind-${node}-var-lib" "/tmp/smolvm-kind-${node}-var-run"
75190
done
76-
77-
make install
78-
SMOLVM_API_URL=http://127.0.0.1:8080 go run ./cmd/main.go \
79-
--metrics-bind-address=0 \
80-
--health-probe-bind-address=:8081 > manager.log 2>&1 &
81-
manager_pid=$!
82-
trap 'kubectl delete smolvm runtime-smoke --ignore-not-found=true --wait=false || true; kill $manager_pid || true; kill $serve_pid || true; cat manager.log || true; cat smolvm-serve.log || true' EXIT
83-
84-
cat <<'EOF' | kubectl apply -f -
85-
apiVersion: vm.smolvm.dev/v1alpha1
86-
kind: SmolVM
87-
metadata:
88-
name: runtime-smoke
89-
spec:
90-
running: true
91-
image: alpine:latest
92-
resources:
93-
cpus: 1
94-
memoryMiB: 128
95-
EOF
96-
97-
ready=false
98-
for i in {1..48}; do
99-
echo "--- poll $i ---"
100-
kubectl get smolvm runtime-smoke -o yaml || true
101-
curl -fsS http://127.0.0.1:8080/api/v1/machines || true
102-
status=$(kubectl get smolvm runtime-smoke -o jsonpath='{.status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || true)
103-
if [ "$status" = "True" ]; then
104-
ready=true
105-
break
106-
fi
107-
sleep 10
108-
done
109-
if [ "$ready" != "true" ]; then
110-
echo "runtime-smoke did not become Ready"
111-
kubectl get smolvm runtime-smoke -o yaml || true
112-
curl -fsS http://127.0.0.1:8080/api/v1/machines || true
191+
- name: Build hardening e2e images and manifests
192+
env:
193+
PREVIOUS_INSTALL_MANIFEST_URL: ${{ vars.PREVIOUS_INSTALL_MANIFEST_URL }}
194+
run: |
195+
set -euxo pipefail
196+
if [ -z "$PREVIOUS_INSTALL_MANIFEST_URL" ]; then
197+
echo "PREVIOUS_INSTALL_MANIFEST_URL repository variable is required for upgrade e2e" >&2
113198
exit 1
114199
fi
115-
test "$(kubectl get smolvm runtime-smoke -o jsonpath='{.status.conditions[?(@.type=="RuntimeReady")].status}')" = "True"
116-
test "$(kubectl get smolvm runtime-smoke -o jsonpath='{.status.conditions[?(@.type=="GuestReady")].status}')" = "Unknown"
117-
118-
kubectl patch smolvm runtime-smoke --type=merge -p '{"spec":{"running":false}}'
119-
kubectl wait smolvm runtime-smoke \
120-
--for=jsonpath='{.status.phase}'=Stopped \
121-
--timeout=5m
122-
123-
machine=$(kubectl get smolvm runtime-smoke -o jsonpath='{.status.machineName}')
124-
kubectl delete smolvm runtime-smoke --wait=true --timeout=5m
125-
for i in {1..30}; do
126-
if ! curl -fsS http://127.0.0.1:8080/api/v1/machines | grep -q "$machine"; then
127-
exit 0
128-
fi
129-
sleep 2
130-
done
131-
echo "runtime machine $machine still exists after CR deletion"
132-
curl -fsS http://127.0.0.1:8080/api/v1/machines || true
133-
exit 1
200+
mkdir -p dist
201+
curl -fsSL "$PREVIOUS_INSTALL_MANIFEST_URL" -o dist/previous-install.yaml
202+
docker build -t smolvm-operator:rc .
203+
docker build -f Dockerfile.runtime --build-arg SMOLVM_VERSION=0.8.1 -t smolvm-runtime:rc .
204+
make build-installer IMG=smolvm-operator:rc RUNTIME_IMG=smolvm-runtime:rc
205+
cp dist/install.yaml dist/rc-install.yaml
206+
- uses: helm/kind-action@v1
207+
with:
208+
cluster_name: hardening
209+
config: .github/kind-kvm-multinode-config.yaml
210+
- name: Load hardening images
211+
run: |
212+
kind load docker-image smolvm-operator:rc --name hardening
213+
kind load docker-image smolvm-runtime:rc --name hardening
214+
- name: Run upgrade, multi-node, and failure checks
215+
env:
216+
RUN_E2E: "true"
217+
E2E_INSTALL_MANIFEST: dist/rc-install.yaml
218+
PREVIOUS_INSTALL_MANIFEST: dist/previous-install.yaml
219+
RC_INSTALL_MANIFEST: dist/rc-install.yaml
220+
run: |
221+
make test-upgrade-e2e-report
222+
make test-multinode-e2e-report
223+
make test-failure-e2e-report
224+
- name: Upload release hardening reports
225+
if: always()
226+
uses: actions/upload-artifact@v4
227+
with:
228+
name: release-hardening-reports
229+
path: reports/

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*.dylib
88
bin/*
99
Dockerfile.cross
10+
reports/
1011

1112
# Test binary, built with `go test -c`
1213
*.test

.golangci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ linters:
2121
enable:
2222
- dupl
2323
- errcheck
24-
- exportloopref
2524
- goconst
2625
- gocyclo
2726
- gofmt

Dockerfile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ COPY go.sum go.sum
1212
RUN go mod download
1313

1414
# Copy the go source
15-
COPY cmd/main.go cmd/main.go
15+
COPY cmd/ cmd/
1616
COPY api/ api/
1717
COPY internal/controller/ internal/controller/
1818
COPY internal/smolvm/ internal/smolvm/
@@ -22,13 +22,15 @@ COPY internal/smolvm/ internal/smolvm/
2222
# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO
2323
# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore,
2424
# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform.
25-
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go
25+
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go && \
26+
CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o runtime-agent cmd/runtime-agent/main.go
2627

2728
# Use distroless as minimal base image to package the manager binary
2829
# Refer to https://github.com/GoogleContainerTools/distroless for more details
2930
FROM gcr.io/distroless/static:nonroot
3031
WORKDIR /
3132
COPY --from=builder /workspace/manager .
33+
COPY --from=builder /workspace/runtime-agent .
3234
USER 65532:65532
3335

3436
ENTRYPOINT ["/manager"]

0 commit comments

Comments
 (0)