-
Notifications
You must be signed in to change notification settings - Fork 8
Fix e2e runner missing docker CLI on Debian trixie #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
46d3064
0880c62
5bb20da
64c0fc6
3e740ad
9745faa
ce1f432
6d0c2c1
0ceed77
a5a1d8c
68cb597
91c79e8
da206ac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| name: e2e | ||
|
|
||
| on: | ||
| push: | ||
| tags: | ||
| - v* | ||
| branches: | ||
| - master | ||
| pull_request: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| e2e: | ||
| name: e2e | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Check out code into the Go module directory | ||
| uses: actions/checkout@v3 | ||
| with: | ||
| fetch-depth: 0 | ||
| submodules: 'recursive' | ||
|
|
||
| - name: Run e2e tests in docker compose runner | ||
| run: | | ||
| docker compose -f e2e/docker-compose.yml up -d docker-sshd-e2e-target | ||
| trap "docker compose -f e2e/docker-compose.yml down || true" EXIT | ||
| docker compose -f e2e/docker-compose.yml run --rm e2e-runner |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| FROM golang:1.26 | ||
|
|
||
| RUN apt-get update && apt-get install -y --no-install-recommends openssh-client curl ca-certificates docker-cli && rm -rf /var/lib/apt/lists/* \ | ||
| && curl -fsSL https://dl.k8s.io/release/v1.34.1/bin/linux/amd64/kubectl -o /usr/local/bin/kubectl \ | ||
| && GOBIN=/usr/local/bin go install sigs.k8s.io/kind@v0.30.0 \ | ||
| && chmod +x /usr/local/bin/kubectl | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| services: | ||
| docker-sshd-e2e-target: | ||
|
tg123 marked this conversation as resolved.
|
||
| image: alpine:3.20 | ||
| container_name: docker-sshd-e2e-test | ||
| command: ["sleep", "300"] | ||
| e2e-runner: | ||
| build: | ||
| context: .. | ||
| dockerfile: e2e/Dockerfile.testrunner | ||
| depends_on: | ||
| - docker-sshd-e2e-target | ||
| privileged: true | ||
| working_dir: /src | ||
| environment: | ||
| - KUBECONFIG=/root/.kube/config | ||
| volumes: | ||
| - ..:/src | ||
| - /var/run/docker.sock:/var/run/docker.sock | ||
| - ${KUBECONFIG:-/tmp/invalid-kubeconfig-path}:/root/.kube/config:ro | ||
| command: | ||
| - /bin/sh | ||
| - -ec | ||
| - | | ||
| export GOFLAGS=-buildvcs=false | ||
| mkdir -p /tmp/bin | ||
| go build -o /tmp/bin/docker-sshd ./cmd/docker-sshd | ||
| go build -o /tmp/bin/kube-sshd ./cmd/kube-sshd | ||
| if [ "$${KUBE_SSHD_E2E:-1}" = "1" ]; then | ||
| kind get clusters | grep -qx docker-sshd-e2e || kind create cluster --name docker-sshd-e2e | ||
| kind export kubeconfig --name docker-sshd-e2e --internal | ||
| kubectl wait --for=condition=Ready pod -n kube-system --all --timeout=2m | ||
|
Comment on lines
+14
to
+31
|
||
| fi | ||
| DOCKER_SSHD_E2E=$${DOCKER_SSHD_E2E:-1} \ | ||
| KUBE_SSHD_E2E=$${KUBE_SSHD_E2E:-1} \ | ||
| DOCKER_SSHD_BIN=/tmp/bin/docker-sshd \ | ||
| KUBE_SSHD_BIN=/tmp/bin/kube-sshd \ | ||
| go test ./e2e -v | ||
| if [ "$${KUBE_SSHD_E2E:-1}" = "1" ]; then | ||
| kind delete cluster --name docker-sshd-e2e || true | ||
| fi | ||
|
Comment on lines
+20
to
+40
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| package e2e | ||
|
|
||
| import ( | ||
| "os" | ||
| "os/exec" | ||
| "strings" | ||
| "testing" | ||
| "time" | ||
| ) | ||
|
|
||
| func TestDockerSSHD(t *testing.T) { | ||
| if os.Getenv("DOCKER_SSHD_E2E") != "1" { | ||
| t.Skip("set DOCKER_SSHD_E2E=1 to run") | ||
| } | ||
|
|
||
| bin := os.Getenv("DOCKER_SSHD_BIN") | ||
| if bin == "" { | ||
| t.Fatal("DOCKER_SSHD_BIN is required") | ||
| } | ||
|
|
||
| container := os.Getenv("DOCKER_E2E_CONTAINER") | ||
| if container == "" { | ||
| container = "docker-sshd-e2e-test" | ||
| } | ||
|
|
||
| key := t.TempDir() + "/docker-sshd-e2e-key" | ||
| mustRun(t, "ssh-keygen", "-t", "ed25519", "-N", "", "-f", key) | ||
|
|
||
| cmd := exec.Command(bin, "--address", "127.0.0.1", "--port", "2232", "--server-key", key) | ||
| cmd.Stdout = os.Stdout | ||
| cmd.Stderr = os.Stderr | ||
| if err := cmd.Start(); err != nil { | ||
| t.Fatalf("start docker-sshd: %v", err) | ||
| } | ||
| defer func() { | ||
| _ = cmd.Process.Kill() | ||
| _, _ = cmd.Process.Wait() | ||
| }() | ||
|
|
||
| out := retrySSH(t, "2232", container+"@127.0.0.1") | ||
| if !hasOKLine(out) { | ||
|
Comment on lines
+29
to
+41
|
||
| t.Fatalf("expected ok, got %q", out) | ||
| } | ||
| } | ||
|
|
||
| func TestKubeSSHD(t *testing.T) { | ||
| if os.Getenv("KUBE_SSHD_E2E") != "1" { | ||
| t.Skip("set KUBE_SSHD_E2E=1 to run") | ||
| } | ||
|
|
||
| bin := os.Getenv("KUBE_SSHD_BIN") | ||
| if bin == "" { | ||
| t.Fatal("KUBE_SSHD_BIN is required") | ||
| } | ||
|
|
||
| pod := "kube-sshd-e2e-" + strings.ToLower(time.Now().Format("150405.000000000")) | ||
| pod = strings.ReplaceAll(pod, ".", "-") | ||
| mustRun(t, "kubectl", "run", pod, "--image=busybox:1.36", "--restart=Never", "--command", "--", "sleep", "300") | ||
| defer func() { | ||
| if out, err := run(t, "kubectl", "delete", "pod", pod, "--ignore-not-found=true", "--wait=false"); err != nil { | ||
| t.Logf("cleanup pod %s failed: %v\n%s", pod, err, out) | ||
| } | ||
| }() | ||
| mustRun(t, "kubectl", "wait", "--for=condition=Ready", "pod/"+pod, "--timeout=120s") | ||
|
|
||
| key := t.TempDir() + "/kube-sshd-e2e-key" | ||
| mustRun(t, "ssh-keygen", "-t", "ed25519", "-N", "", "-f", key) | ||
|
|
||
| cmd := exec.Command(bin, "--address", "127.0.0.1", "--port", "2233", "--server-key", key, "--namespace", "default") | ||
| cmd.Stdout = os.Stdout | ||
| cmd.Stderr = os.Stderr | ||
| if err := cmd.Start(); err != nil { | ||
| t.Fatalf("start kube-sshd: %v", err) | ||
| } | ||
| defer func() { | ||
| _ = cmd.Process.Kill() | ||
| _, _ = cmd.Process.Wait() | ||
| }() | ||
|
|
||
| out := retrySSH(t, "2233", pod+"@127.0.0.1") | ||
| if !hasOKLine(out) { | ||
| t.Fatalf("expected ok, got %q", out) | ||
| } | ||
| } | ||
|
|
||
| func hasOKLine(out string) bool { | ||
| for _, line := range strings.Split(out, "\n") { | ||
| if strings.TrimSpace(line) == "ok" { | ||
| return true | ||
| } | ||
| } | ||
| return false | ||
| } | ||
|
|
||
| func retrySSH(t *testing.T, port, userHost string) string { | ||
| t.Helper() | ||
|
|
||
| var out string | ||
| var err error | ||
| for range 30 { | ||
| out, err = run(t, | ||
| "ssh", | ||
| "-o", "StrictHostKeyChecking=no", | ||
| "-o", "UserKnownHostsFile=/dev/null", | ||
| "-o", "PreferredAuthentications=none", | ||
| "-p", port, | ||
| userHost, | ||
| "echo", "ok", | ||
| ) | ||
| if err == nil { | ||
| return out | ||
| } | ||
| time.Sleep(time.Second) | ||
| } | ||
|
|
||
| t.Fatalf("ssh did not succeed: %v", err) | ||
| return "" | ||
| } | ||
|
|
||
| func mustRun(t *testing.T, name string, args ...string) string { | ||
| t.Helper() | ||
| out, err := run(t, name, args...) | ||
| if err != nil { | ||
| t.Fatalf("%s %v failed: %v\n%s", name, args, err, out) | ||
| } | ||
| return out | ||
| } | ||
|
|
||
| func run(t *testing.T, name string, args ...string) (string, error) { | ||
| t.Helper() | ||
| cmd := exec.Command(name, args...) | ||
| out, err := cmd.CombinedOutput() | ||
| return string(out), err | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Dockerfile hardcodes downloading
kubectlforlinux/amd64, which will break the runner image build on ARM64 hosts (e.g., Apple Silicon) and any non-amd64 CI. Also, the directcurldownload is not integrity-verified. Consider usingARG TARGETARCH(BuildKit) to select the correct kubectl binary, and verify the download via the published SHA256 (or install via a trusted package source).