diff --git a/docker.Makefile b/docker.Makefile index 69135e97a6..2ff2594a7f 100644 --- a/docker.Makefile +++ b/docker.Makefile @@ -105,7 +105,7 @@ shellcheck: build_shell_validate_image ## run shellcheck validation docker run -ti --rm $(ENVVARS) $(MOUNTS) $(VALIDATE_IMAGE_NAME) make shellcheck .PHONY: test-e2e ## run e2e tests -test-e2e: test-e2e-non-experimental test-e2e-experimental +test-e2e: test-e2e-non-experimental test-e2e-experimental test-e2e-connhelper-ssh .PHONY: test-e2e-experimental test-e2e-experimental: build_e2e_image @@ -115,6 +115,10 @@ test-e2e-experimental: build_e2e_image test-e2e-non-experimental: build_e2e_image docker run --rm -v /var/run/docker.sock:/var/run/docker.sock $(E2E_IMAGE_NAME) +.PHONY: test-e2e-connhelper-ssh +test-e2e-connhelper-ssh: build_e2e_image + docker run -e TEST_CONNHELPER=ssh -e DOCKERD_EXPERIMENTAL=1 --rm -v /var/run/docker.sock:/var/run/docker.sock $(E2E_IMAGE_NAME) + .PHONY: help help: ## print this help @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) diff --git a/dockerfiles/Dockerfile.e2e b/dockerfiles/Dockerfile.e2e index bed83e0e18..94d805d282 100644 --- a/dockerfiles/Dockerfile.e2e +++ b/dockerfiles/Dockerfile.e2e @@ -13,6 +13,7 @@ RUN apt-get update && apt-get install -y \ libapparmor-dev \ libseccomp-dev \ iptables \ + openssh-client \ && rm -rf /var/lib/apt/lists/* ARG COMPOSE_VERSION=1.21.2 diff --git a/e2e/compose-env.connhelper-ssh.yaml b/e2e/compose-env.connhelper-ssh.yaml new file mode 100644 index 0000000000..a1baa114fe --- /dev/null +++ b/e2e/compose-env.connhelper-ssh.yaml @@ -0,0 +1,9 @@ +version: '2.1' + +services: + engine: + build: + context: ./testdata + dockerfile: Dockerfile.connhelper-ssh + environment: + - TEST_CONNHELPER_SSH_ID_RSA_PUB diff --git a/e2e/testdata/Dockerfile.connhelper-ssh b/e2e/testdata/Dockerfile.connhelper-ssh new file mode 100644 index 0000000000..acf0620495 --- /dev/null +++ b/e2e/testdata/Dockerfile.connhelper-ssh @@ -0,0 +1,14 @@ +FROM docker:test-dind +RUN apk --no-cache add shadow openssh-server && \ + groupadd -f docker && \ + useradd -m penguin && \ + usermod -aG docker penguin && \ + usermod -p $(head -c32 /dev/urandom | base64) penguin && \ + chsh -s /bin/sh penguin && \ + ssh-keygen -A +# workaround: ssh session excludes /usr/local/bin from $PATH +RUN ln -s /usr/local/bin/docker /usr/bin/docker +COPY ./connhelper-ssh/entrypoint.sh / +EXPOSE 22 +ENTRYPOINT ["/entrypoint.sh"] +# usage: docker run --privileged -e TEST_CONNHELPER_SSH_ID_RSA_PUB=$(cat ~/.ssh/id_rsa.pub) -p 22 $THIS_IMAGE diff --git a/e2e/testdata/connhelper-ssh/entrypoint.sh b/e2e/testdata/connhelper-ssh/entrypoint.sh new file mode 100755 index 0000000000..f4f5464567 --- /dev/null +++ b/e2e/testdata/connhelper-ssh/entrypoint.sh @@ -0,0 +1,8 @@ +#!/bin/sh +set -ex +mkdir -m 0700 -p /home/penguin/.ssh +echo ${TEST_CONNHELPER_SSH_ID_RSA_PUB} > /home/penguin/.ssh/authorized_keys +chmod 0600 /home/penguin/.ssh/authorized_keys +chown -R penguin:penguin /home/penguin +/usr/sbin/sshd -E /var/log/sshd.log +exec dockerd-entrypoint.sh $@ diff --git a/internal/test/environment/testenv.go b/internal/test/environment/testenv.go index 42043c1bdf..a6e16814fa 100644 --- a/internal/test/environment/testenv.go +++ b/internal/test/environment/testenv.go @@ -1,15 +1,13 @@ package environment import ( - "context" "os" "strings" "testing" "time" - "github.com/docker/docker/client" "github.com/pkg/errors" - "gotest.tools/assert" + "gotest.tools/icmd" "gotest.tools/poll" "gotest.tools/skip" ) @@ -79,21 +77,14 @@ func boolFromString(val string) bool { } } -func dockerClient(t *testing.T) client.APIClient { - t.Helper() - c, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion("1.37")) - assert.NilError(t, err) - return c -} - // DefaultPollSettings used with gotestyourself/poll var DefaultPollSettings = poll.WithDelay(100 * time.Millisecond) // SkipIfNotExperimentalDaemon returns whether the test docker daemon is in experimental mode func SkipIfNotExperimentalDaemon(t *testing.T) { t.Helper() - c := dockerClient(t) - info, err := c.Info(context.Background()) - assert.NilError(t, err) - skip.If(t, !info.ExperimentalBuild, "running against a non-experimental daemon") + result := icmd.RunCmd(icmd.Command("docker", "info", "--format", "{{.ExperimentalBuild}}")) + result.Assert(t, icmd.Expected{Err: icmd.None}) + experimentalBuild := strings.TrimSpace(result.Stdout()) == "true" + skip.If(t, !experimentalBuild, "running against a non-experimental daemon") } diff --git a/scripts/test/e2e/run b/scripts/test/e2e/run index 2471c8e033..2b718e52f1 100755 --- a/scripts/test/e2e/run +++ b/scripts/test/e2e/run @@ -18,6 +18,14 @@ function setup { local file=$2 test "${DOCKERD_EXPERIMENTAL:-}" -eq "1" && file="${file}:./e2e/compose-env.experimental.yaml" + + if [[ "${TEST_CONNHELPER:-}" = "ssh" ]];then + test ! -f "${HOME}/.ssh/id_rsa" && ssh-keygen -t rsa -C docker-e2e-dummy -N "" -f "${HOME}/.ssh/id_rsa" -q + grep "^StrictHostKeyChecking no" "${HOME}/.ssh/config" > /dev/null 2>&1 || echo "StrictHostKeyChecking no" > "${HOME}/.ssh/config" + TEST_CONNHELPER_SSH_ID_RSA_PUB=$(cat "${HOME}/.ssh/id_rsa.pub") + export TEST_CONNHELPER_SSH_ID_RSA_PUB + file="${file}:./e2e/compose-env.connhelper-ssh.yaml" + fi COMPOSE_PROJECT_NAME=$project COMPOSE_FILE=$file docker-compose up --build -d >&2 local network="${project}_default" @@ -26,6 +34,9 @@ function setup { engine_ip="$(container_ip "${project}_engine_1" "$network")" engine_host="tcp://$engine_ip:2375" + if [[ "${TEST_CONNHELPER:-}" = "ssh" ]];then + engine_host="ssh://penguin@${engine_ip}" + fi ( export DOCKER_HOST="$engine_host" timeout 200 ./scripts/test/e2e/wait-on-daemon @@ -57,7 +68,7 @@ function runtests { TEST_REMOTE_DAEMON="${REMOTE_DAEMON-}" \ TEST_SKIP_PLUGIN_TESTS="${SKIP_PLUGIN_TESTS-}" \ GOPATH="$GOPATH" \ - PATH="$PWD/build/" \ + PATH="$PWD/build/:/usr/bin" \ "$(which go)" test -v ./e2e/... ${TESTFLAGS-} }