summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.dockerignore1
-rw-r--r--.github/CODEOWNERS3
-rw-r--r--.gitignore5
-rw-r--r--Dockerfile47
-rw-r--r--Jenkinsfile712
-rw-r--r--Makefile30
-rwxr-xr-xhack/ci/experimental2
-rwxr-xr-xhack/ci/janky4
-rwxr-xr-xhack/dind2
-rwxr-xr-xhack/dockerfile/install/containerd.installer8
-rwxr-xr-xhack/dockerfile/install/dockercli.installer7
-rwxr-xr-xhack/dockerfile/install/gometalinter.installer4
-rwxr-xr-xhack/dockerfile/install/gotestsum.installer11
-rwxr-xr-xhack/dockerfile/install/install.sh4
-rwxr-xr-xhack/dockerfile/install/proxy.installer2
-rwxr-xr-xhack/dockerfile/install/runc.installer4
-rwxr-xr-xhack/dockerfile/install/tini.installer4
-rwxr-xr-xhack/dockerfile/install/tomlv.installer2
-rwxr-xr-xhack/dockerfile/install/vndr.installer2
-rwxr-xr-xhack/generate-swagger-api.sh42
-rw-r--r--hack/integration-cli-on-swarm/README.md68
-rw-r--r--hack/integration-cli-on-swarm/agent/Dockerfile6
-rw-r--r--hack/integration-cli-on-swarm/agent/master/call.go132
-rw-r--r--hack/integration-cli-on-swarm/agent/master/master.go65
-rw-r--r--hack/integration-cli-on-swarm/agent/master/set.go28
-rw-r--r--hack/integration-cli-on-swarm/agent/master/set_test.go63
-rw-r--r--hack/integration-cli-on-swarm/agent/types/types.go18
-rw-r--r--hack/integration-cli-on-swarm/agent/vendor.conf2
-rw-r--r--hack/integration-cli-on-swarm/agent/vendor/github.com/bfirsh/funker-go/LICENSE191
-rw-r--r--hack/integration-cli-on-swarm/agent/vendor/github.com/bfirsh/funker-go/call.go50
-rw-r--r--hack/integration-cli-on-swarm/agent/vendor/github.com/bfirsh/funker-go/handle.go54
-rw-r--r--hack/integration-cli-on-swarm/agent/worker/executor.go118
-rw-r--r--hack/integration-cli-on-swarm/agent/worker/worker.go69
-rw-r--r--hack/integration-cli-on-swarm/host/compose.go122
-rw-r--r--hack/integration-cli-on-swarm/host/dockercmd.go64
-rw-r--r--hack/integration-cli-on-swarm/host/enumerate.go55
-rw-r--r--hack/integration-cli-on-swarm/host/enumerate_test.go84
-rw-r--r--hack/integration-cli-on-swarm/host/host.go198
-rw-r--r--hack/integration-cli-on-swarm/host/volume.go88
-rw-r--r--hack/make.ps113
-rwxr-xr-xhack/make.sh11
-rw-r--r--hack/make/.binary2
-rw-r--r--hack/make/.go-autogen4
-rw-r--r--hack/make/.integration-daemon-start10
-rw-r--r--hack/make/.integration-daemon-stop2
-rw-r--r--hack/make/.integration-test-helpers80
-rwxr-xr-xhack/make/build-integration-test-binary2
-rw-r--r--hack/make/cross16
-rw-r--r--hack/make/cross-platform-dependent2
-rw-r--r--hack/make/dynbinary7
-rw-r--r--hack/make/run8
-rw-r--r--hack/make/test-docker-py60
-rwxr-xr-xhack/make/test-integration16
-rw-r--r--hack/make/test-integration-flaky32
-rwxr-xr-xhack/test/e2e-run.sh22
-rwxr-xr-xhack/test/unit36
-rwxr-xr-xhack/validate/all4
-rwxr-xr-xhack/validate/changelog-date-descending4
-rwxr-xr-xhack/validate/changelog-well-formed16
-rwxr-xr-xhack/validate/dco2
-rwxr-xr-xhack/validate/default22
-rwxr-xr-xhack/validate/deprecate-integration-cli6
-rwxr-xr-xhack/validate/gometalinter2
-rwxr-xr-xhack/validate/swagger4
-rwxr-xr-xhack/validate/swagger-gen2
-rw-r--r--integration/plugin/logging/cmd/close_on_start/main_test.go1
-rw-r--r--integration/plugin/logging/cmd/cmd_test.go1
-rw-r--r--integration/plugin/logging/cmd/dummy/main_test.go1
-rw-r--r--integration/plugin/volumes/cmd/cmd_test.go1
-rw-r--r--integration/plugin/volumes/cmd/dummy/main_test.go1
-rw-r--r--internal/test/daemon/daemon.go18
71 files changed, 1043 insertions, 1736 deletions
diff --git a/.dockerignore b/.dockerignore
index 4a56f2e00c..8645f94037 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -3,5 +3,4 @@ bundles
vendor/pkg
.go-pkg-cache
.git
-hack/integration-cli-on-swarm/integration-cli-on-swarm
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 9081854965..b7fac27a66 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -13,8 +13,5 @@ daemon/graphdriver/overlay2/** @dmcgowan
daemon/graphdriver/windows/** @johnstep @jhowardmsft
daemon/logger/awslogs/** @samuelkarp
hack/** @tianon
-hack/integration-cli-on-swarm/** @AkihiroSuda
-integration-cli/** @vdemeester
-integration/** @vdemeester
plugin/** @cpuguy83
project/** @thaJeztah
diff --git a/.gitignore b/.gitignore
index 392bf963c5..abad293ee0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
# please consider a global .gitignore https://help.github.com/articles/ignoring-files
*.exe
*.exe~
+*.gz
*.orig
test.main
.*.swp
@@ -19,6 +20,6 @@ contrib/builder/rpm/*/changelog
dockerversion/version_autogen.go
dockerversion/version_autogen_unix.go
vendor/pkg/
-hack/integration-cli-on-swarm/integration-cli-on-swarm
-coverage.txt
+go-test-report.json
profile.out
+junit-report.xml
diff --git a/Dockerfile b/Dockerfile
index fb4a3864f3..4acc6495c2 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -72,17 +72,6 @@ RUN set -x \
esac \
&& rm -rf "$GOPATH"
-
-
-FROM base AS docker-py
-# Get the "docker-py" source so we can run their integration tests
-ENV DOCKER_PY_COMMIT ac922192959870774ad8428344d9faa0555f7ba6
-RUN git clone https://github.com/docker/docker-py.git /build \
- && cd /build \
- && git checkout -q $DOCKER_PY_COMMIT
-
-
-
FROM base AS swagger
# Install go-swagger for validating swagger.yaml
ENV GO_SWAGGER_COMMIT c28258affb0b6251755d92489ef685af8d4ff3eb
@@ -93,7 +82,6 @@ RUN set -x \
&& go build -o /build/swagger github.com/go-swagger/go-swagger/cmd/swagger \
&& rm -rf "$GOPATH"
-
FROM base AS frozen-images
RUN apt-get update && apt-get install -y jq ca-certificates --no-install-recommends
# Get useful and necessary Hub images so we can "docker load" locally instead of pulling
@@ -144,6 +132,12 @@ COPY hack/dockerfile/install/install.sh ./install.sh
COPY hack/dockerfile/install/$INSTALL_BINARY_NAME.installer ./
RUN PREFIX=/build/ ./install.sh $INSTALL_BINARY_NAME
+FROM base AS gotestsum
+ENV INSTALL_BINARY_NAME=gotestsum
+COPY hack/dockerfile/install/install.sh ./install.sh
+COPY hack/dockerfile/install/$INSTALL_BINARY_NAME.installer ./
+RUN PREFIX=/build ./install.sh $INSTALL_BINARY_NAME
+
FROM base AS dockercli
ENV INSTALL_BINARY_NAME=dockercli
COPY hack/dockerfile/install/install.sh ./install.sh
@@ -186,25 +180,14 @@ RUN apt-get update && apt-get install -y \
jq \
libcap2-bin \
libdevmapper-dev \
-# libffi-dev and libssl-dev appear to be required for compiling paramiko on s390x/ppc64le
- libffi-dev \
- libssl-dev \
libudev-dev \
libsystemd-dev \
binutils-mingw-w64 \
g++-mingw-w64-x86-64 \
net-tools \
pigz \
- python-backports.ssl-match-hostname \
- python-dev \
-# python-cffi appears to be required for compiling paramiko on s390x/ppc64le
- python-cffi \
- python-mock \
- python-pip \
- python-requests \
- python-setuptools \
- python-websocket \
- python-wheel \
+ python3-pip \
+ python3-setuptools \
thin-provisioning-tools \
vim \
vim-common \
@@ -213,9 +196,13 @@ RUN apt-get update && apt-get install -y \
bzip2 \
xz-utils \
--no-install-recommends
+
+RUN pip3 install yamllint==1.16.0
+
COPY --from=swagger /build/swagger* /usr/local/bin/
COPY --from=frozen-images /build/ /docker-frozen-images
COPY --from=gometalinter /build/ /usr/local/bin/
+COPY --from=gotestsum /build/ /usr/local/bin/
COPY --from=tomlv /build/ /usr/local/bin/
COPY --from=vndr /build/ /usr/local/bin/
COPY --from=tini /build/ /usr/local/bin/
@@ -225,16 +212,6 @@ COPY --from=proxy /build/ /usr/local/bin/
COPY --from=dockercli /build/ /usr/local/cli
COPY --from=registry /build/registry* /usr/local/bin/
COPY --from=criu /build/ /usr/local/
-COPY --from=docker-py /build/ /docker-py
-# TODO: This is for the docker-py tests, which shouldn't really be needed for
-# this image, but currently CI is expecting to run this image. This should be
-# split out into a separate image, including all the `python-*` deps installed
-# above.
-RUN cd /docker-py \
- && pip install docker-pycreds==0.4.0 \
- && pip install paramiko==2.4.2 \
- && pip install yamllint==1.5.0 \
- && pip install -r test-requirements.txt
ENV PATH=/usr/local/cli:$PATH
ENV DOCKER_BUILDTAGS apparmor seccomp selinux
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000000..eb52655a3c
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,712 @@
+#!groovy
+pipeline {
+ agent none
+
+ options {
+ buildDiscarder(logRotator(daysToKeepStr: '30'))
+ timeout(time: 2, unit: 'HOURS')
+ timestamps()
+ }
+ parameters {
+ booleanParam(name: 'unit_validate', defaultValue: true, description: 'x86 unit tests and vendor check')
+ booleanParam(name: 'janky', defaultValue: true, description: 'x86 Build/Test')
+ booleanParam(name: 'z', defaultValue: true, description: 'IBM Z (s390x) Build/Test')
+ booleanParam(name: 'powerpc', defaultValue: true, description: 'PowerPC (ppc64le) Build/Test')
+ booleanParam(name: 'windowsRS1', defaultValue: false, description: 'Windows 2016 (RS1) Build/Test')
+ booleanParam(name: 'windowsRS5', defaultValue: false, description: 'Windows 2019 (RS5) Build/Test')
+ }
+ environment {
+ DOCKER_BUILDKIT = '1'
+ DOCKER_EXPERIMENTAL = '1'
+ DOCKER_GRAPHDRIVER = 'overlay2'
+ APT_MIRROR = 'cdn-fastly.deb.debian.org'
+ CHECK_CONFIG_COMMIT = '78405559cfe5987174aa2cb6463b9b2c1b917255'
+ TIMEOUT = '120m'
+ }
+ stages {
+ stage('Build') {
+ parallel {
+ stage('unit-validate') {
+ when {
+ beforeAgent true
+ expression { params.unit_validate }
+ }
+ agent { label 'amd64 && ubuntu-1804 && overlay2' }
+
+ stages {
+ stage("Print info") {
+ steps {
+ sh 'docker version'
+ sh 'docker info'
+ sh '''
+ echo "check-config.sh version: ${CHECK_CONFIG_COMMIT}"
+ curl -fsSL -o ${WORKSPACE}/check-config.sh "https://raw.githubusercontent.com/moby/moby/${CHECK_CONFIG_COMMIT}/contrib/check-config.sh" \
+ && bash ${WORKSPACE}/check-config.sh || true
+ '''
+ }
+ }
+ stage("Build dev image") {
+ steps {
+ sh 'docker build --force-rm --build-arg APT_MIRROR -t docker:${GIT_COMMIT} .'
+ }
+ }
+ stage("Validate") {
+ steps {
+ sh '''
+ docker run --rm -t --privileged \
+ -v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
+ -v "$WORKSPACE/.git:/go/src/github.com/docker/docker/.git" \
+ --name docker-pr$BUILD_NUMBER \
+ -e DOCKER_EXPERIMENTAL \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ docker:${GIT_COMMIT} \
+ hack/validate/default
+ '''
+ }
+ }
+ stage("Docker-py") {
+ steps {
+ sh '''
+ docker run --rm -t --privileged \
+ -v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
+ --name docker-pr$BUILD_NUMBER \
+ -e DOCKER_EXPERIMENTAL \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ docker:${GIT_COMMIT} \
+ hack/make.sh \
+ dynbinary-daemon \
+ test-docker-py
+ '''
+ }
+ post {
+ always {
+ junit testResults: 'bundles/test-docker-py/junit-report.xml', allowEmptyResults: true
+
+ sh '''
+ echo "Ensuring container killed."
+ docker rm -vf docker-pr$BUILD_NUMBER || true
+ '''
+
+ sh '''
+ echo 'Chowning /workspace to jenkins user'
+ docker run --rm -v "$WORKSPACE:/workspace" busybox chown -R "$(id -u):$(id -g)" /workspace
+ '''
+
+ sh '''
+ echo 'Creating docker-py-bundles.tar.gz'
+ tar -czf docker-py-bundles.tar.gz bundles/test-docker-py/*.xml bundles/test-docker-py/*.log
+ '''
+
+ archiveArtifacts artifacts: 'docker-py-bundles.tar.gz'
+ }
+ }
+ }
+ stage("Static") {
+ steps {
+ sh '''
+ docker run --rm -t --privileged \
+ -v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
+ --name docker-pr$BUILD_NUMBER \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ docker:${GIT_COMMIT} \
+ hack/make.sh binary-daemon
+ '''
+ }
+ }
+ stage("Cross") {
+ steps {
+ sh '''
+ docker run --rm -t --privileged \
+ -v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
+ --name docker-pr$BUILD_NUMBER \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ docker:${GIT_COMMIT} \
+ hack/make.sh cross
+ '''
+ }
+ }
+ // needs to be last stage that calls make.sh for the junit report to work
+ stage("Unit tests") {
+ steps {
+ sh '''
+ docker run --rm -t --privileged \
+ -v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
+ --name docker-pr$BUILD_NUMBER \
+ -e DOCKER_EXPERIMENTAL \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ docker:${GIT_COMMIT} \
+ hack/test/unit
+ '''
+ }
+ post {
+ always {
+ junit testResults: 'bundles/junit-report.xml', allowEmptyResults: true
+ }
+ }
+ }
+ stage("Validate vendor") {
+ steps {
+ sh '''
+ docker run --rm -t --privileged \
+ -v "$WORKSPACE/.git:/go/src/github.com/docker/docker/.git" \
+ --name docker-pr$BUILD_NUMBER \
+ -e DOCKER_EXPERIMENTAL \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ docker:${GIT_COMMIT} \
+ hack/validate/vendor
+ '''
+ }
+ }
+ stage("Build e2e image") {
+ steps {
+ sh '''
+ echo "Building e2e image"
+ docker build --build-arg DOCKER_GITCOMMIT=${GIT_COMMIT} -t moby-e2e-test -f Dockerfile.e2e .
+ '''
+ }
+ }
+ }
+
+ post {
+ always {
+ sh '''
+ echo 'Ensuring container killed.'
+ docker rm -vf docker-pr$BUILD_NUMBER || true
+ '''
+
+ sh '''
+ echo 'Chowning /workspace to jenkins user'
+ docker run --rm -v "$WORKSPACE:/workspace" busybox chown -R "$(id -u):$(id -g)" /workspace
+ '''
+
+ sh '''
+ echo 'Creating unit-bundles.tar.gz'
+ tar -czvf unit-bundles.tar.gz bundles/junit-report.xml bundles/go-test-report.json bundles/profile.out
+ '''
+
+ archiveArtifacts artifacts: 'unit-bundles.tar.gz'
+ }
+ cleanup {
+ sh 'make clean'
+ deleteDir()
+ }
+ }
+ }
+ stage('janky') {
+ when {
+ beforeAgent true
+ expression { params.janky }
+ }
+ agent { label 'amd64 && ubuntu-1804 && overlay2' }
+
+ stages {
+ stage("Print info") {
+ steps {
+ sh 'docker version'
+ sh 'docker info'
+ sh '''
+ echo "check-config.sh version: ${CHECK_CONFIG_COMMIT}"
+ curl -fsSL -o ${WORKSPACE}/check-config.sh "https://raw.githubusercontent.com/moby/moby/${CHECK_CONFIG_COMMIT}/contrib/check-config.sh" \
+ && bash ${WORKSPACE}/check-config.sh || true
+ '''
+ }
+ }
+ stage("Build dev image") {
+ steps {
+ sh '''
+ # todo: include ip_vs in base image
+ sudo modprobe ip_vs
+
+ docker build --force-rm --build-arg APT_MIRROR -t docker:${GIT_COMMIT} .
+ '''
+ }
+ }
+ stage("Run tests") {
+ steps {
+ sh '''#!/bin/bash
+ # bash is needed so 'jobs -p' works properly
+ # it also accepts setting inline envvars for functions without explicitly exporting
+
+ run_tests() {
+ [ -n "$TESTDEBUG" ] && rm= || rm=--rm;
+ docker run $rm -t --privileged \
+ -v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
+ -v "$WORKSPACE/.git:/go/src/github.com/docker/docker/.git" \
+ --name "$CONTAINER_NAME" \
+ -e KEEPBUNDLE=1 \
+ -e TESTDEBUG \
+ -e TESTFLAGS \
+ -e TEST_INTEGRATION_DEST \
+ -e TEST_SKIP_INTEGRATION \
+ -e TEST_SKIP_INTEGRATION_CLI \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ -e TIMEOUT \
+ docker:${GIT_COMMIT} \
+ hack/make.sh \
+ "$1" \
+ test-integration
+ }
+
+ trap "exit" INT TERM
+ trap 'pids=$(jobs -p); echo "Remaining pids to kill: [$pids]"; [ -z "$pids" ] || kill $pids' EXIT
+
+ CONTAINER_NAME=docker-pr$BUILD_NUMBER
+
+ docker run --rm -t --privileged \
+ -v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
+ -v "$WORKSPACE/.git:/go/src/github.com/docker/docker/.git" \
+ --name ${CONTAINER_NAME}-build \
+ -e DOCKER_EXPERIMENTAL \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ docker:${GIT_COMMIT} \
+ hack/make.sh \
+ dynbinary-daemon
+
+ # flaky + integration
+ TEST_INTEGRATION_DEST=1 CONTAINER_NAME=${CONTAINER_NAME}-1 TEST_SKIP_INTEGRATION_CLI=1 run_tests test-integration-flaky &
+
+ # integration-cli first set
+ TEST_INTEGRATION_DEST=2 CONTAINER_NAME=${CONTAINER_NAME}-2 TEST_SKIP_INTEGRATION=1 TESTFLAGS="-check.f ^(DockerSuite|DockerNetworkSuite|DockerHubPullSuite|DockerRegistrySuite|DockerSchema1RegistrySuite|DockerRegistryAuthTokenSuite|DockerRegistryAuthHtpasswdSuite)" run_tests &
+
+ # integration-cli second set
+ TEST_INTEGRATION_DEST=3 CONTAINER_NAME=${CONTAINER_NAME}-3 TEST_SKIP_INTEGRATION=1 TESTFLAGS="-check.f ^(DockerSwarmSuite|DockerDaemonSuite|DockerExternalVolumeSuite)" run_tests &
+
+ set +x
+ c=0
+ for job in $(jobs -p); do
+ wait ${job} || c=$?
+ done
+ exit $c
+ '''
+ }
+ }
+ }
+
+ post {
+ always {
+ sh '''
+ echo "Ensuring container killed."
+ docker rm -vf docker-pr$BUILD_NUMBER || true
+ '''
+
+ sh '''
+ echo "Chowning /workspace to jenkins user"
+ docker run --rm -v "$WORKSPACE:/workspace" busybox chown -R "$(id -u):$(id -g)" /workspace
+ '''
+
+ sh '''
+ echo "Creating janky-bundles.tar.gz"
+ # exclude overlay2 directories
+ find bundles -path '*/root/*overlay2' -prune -o -type f \\( -name '*.log' -o -name '*.prof' \\) -print | xargs tar -czf janky-bundles.tar.gz
+ '''
+
+ archiveArtifacts artifacts: 'janky-bundles.tar.gz'
+ }
+ cleanup {
+ sh 'make clean'
+ deleteDir()
+ }
+ }
+ }
+ stage('z') {
+ when {
+ beforeAgent true
+ expression { params.z }
+ }
+ agent { label 's390x-ubuntu-1604' }
+ // s390x machines run on Docker 18.06, and buildkit has some bugs on that version
+ environment { DOCKER_BUILDKIT = '0' }
+
+ stages {
+ stage("Print info") {
+ steps {
+ sh 'docker version'
+ sh 'docker info'
+ sh '''
+ echo "check-config.sh version: ${CHECK_CONFIG_COMMIT}"
+ curl -fsSL -o ${WORKSPACE}/check-config.sh "https://raw.githubusercontent.com/moby/moby/${CHECK_CONFIG_COMMIT}/contrib/check-config.sh" \
+ && bash ${WORKSPACE}/check-config.sh || true
+ '''
+ }
+ }
+ stage("Build dev image") {
+ steps {
+ sh '''
+ docker build --force-rm --build-arg APT_MIRROR -t docker:${GIT_COMMIT} -f Dockerfile .
+ '''
+ }
+ }
+ stage("Unit tests") {
+ steps {
+ sh '''
+ docker run --rm -t --privileged \
+ -v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
+ --name docker-pr$BUILD_NUMBER \
+ -e DOCKER_EXPERIMENTAL \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ docker:${GIT_COMMIT} \
+ hack/test/unit
+ '''
+ }
+ post {
+ always {
+ junit testResults: 'bundles/junit-report.xml', allowEmptyResults: true
+ }
+ }
+ }
+ stage("Integration tests") {
+ environment { TEST_SKIP_INTEGRATION_CLI = '1' }
+ steps {
+ sh '''
+ docker run --rm -t --privileged \
+ -v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
+ --name docker-pr$BUILD_NUMBER \
+ -e DOCKER_EXPERIMENTAL \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ -e TEST_SKIP_INTEGRATION_CLI \
+ -e TIMEOUT \
+ docker:${GIT_COMMIT} \
+ hack/make.sh \
+ dynbinary \
+ test-integration
+ '''
+ }
+ }
+ }
+
+ post {
+ always {
+ sh '''
+ echo "Ensuring container killed."
+ docker rm -vf docker-pr$BUILD_NUMBER || true
+ '''
+
+ sh '''
+ echo "Chowning /workspace to jenkins user"
+ docker run --rm -v "$WORKSPACE:/workspace" busybox chown -R "$(id -u):$(id -g)" /workspace
+ '''
+
+ sh '''
+ echo "Creating s390x-integration-bundles.tar.gz"
+ # exclude overlay2 directories
+ find bundles -path '*/root/*overlay2' -prune -o -type f \\( -name '*.log' -o -name '*.prof' \\) -print | xargs tar -czf s390x-integration-bundles.tar.gz
+ '''
+
+ archiveArtifacts artifacts: 's390x-integration-bundles.tar.gz'
+ }
+ cleanup {
+ sh 'make clean'
+ deleteDir()
+ }
+ }
+ }
+ stage('z-master') {
+ when {
+ beforeAgent true
+ branch 'master'
+ expression { params.z }
+ }
+ agent { label 's390x-ubuntu-1604' }
+ // s390x machines run on Docker 18.06, and buildkit has some bugs on that version
+ environment { DOCKER_BUILDKIT = '0' }
+
+ stages {
+ stage("Print info") {
+ steps {
+ sh 'docker version'
+ sh 'docker info'
+ sh '''
+ echo "check-config.sh version: ${CHECK_CONFIG_COMMIT}"
+ curl -fsSL -o ${WORKSPACE}/check-config.sh "https://raw.githubusercontent.com/moby/moby/${CHECK_CONFIG_COMMIT}/contrib/check-config.sh" \
+ && bash ${WORKSPACE}/check-config.sh || true
+ '''
+ }
+ }
+ stage("Build dev image") {
+ steps {
+ sh '''
+ docker build --force-rm --build-arg APT_MIRROR -t docker:${GIT_COMMIT} -f Dockerfile .
+ '''
+ }
+ }
+ stage("Integration-cli tests") {
+ environment { TEST_SKIP_INTEGRATION = '1' }
+ steps {
+ sh '''
+ docker run --rm -t --privileged \
+ -v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
+ --name docker-pr$BUILD_NUMBER \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ -e TEST_SKIP_INTEGRATION \
+ -e TIMEOUT \
+ docker:${GIT_COMMIT} \
+ hack/make.sh \
+ dynbinary \
+ test-integration
+ '''
+ }
+ }
+ }
+
+ post {
+ always {
+ sh '''
+ echo "Ensuring container killed."
+ docker rm -vf docker-pr$BUILD_NUMBER || true
+ '''
+
+ sh '''
+ echo "Chowning /workspace to jenkins user"
+ docker run --rm -v "$WORKSPACE:/workspace" busybox chown -R "$(id -u):$(id -g)" /workspace
+ '''
+
+ sh '''
+ echo "Creating s390x-integration-cli-bundles.tar.gz"
+ find bundles -path '*/root/*overlay2' -prune -o -type f \\( -name '*.log' -o -name '*.prof' \\) -print | xargs tar -czf s390x-integration-cli-bundles.tar.gz
+ '''
+
+ archiveArtifacts artifacts: 's390x-integration-cli-bundles.tar.gz'
+ }
+ cleanup {
+ sh 'make clean'
+ deleteDir()
+ }
+ }
+ }
+ stage('powerpc') {
+ when {
+ beforeAgent true
+ expression { params.powerpc }
+ }
+ agent { label 'ppc64le-ubuntu-1604' }
+ // power machines run on Docker 18.06, and buildkit has some bugs on that version
+ environment { DOCKER_BUILDKIT = '0' }
+
+ stages {
+ stage("Print info") {
+ steps {
+ sh 'docker version'
+ sh 'docker info'
+ sh '''
+ echo "check-config.sh version: ${CHECK_CONFIG_COMMIT}"
+ curl -fsSL -o ${WORKSPACE}/check-config.sh "https://raw.githubusercontent.com/moby/moby/${CHECK_CONFIG_COMMIT}/contrib/check-config.sh" \
+ && bash ${WORKSPACE}/check-config.sh || true
+ '''
+ }
+ }
+ stage("Build dev image") {
+ steps {
+ sh 'docker build --force-rm --build-arg APT_MIRROR -t docker:${GIT_COMMIT} -f Dockerfile .'
+ }
+ }
+ stage("Unit tests") {
+ steps {
+ sh '''
+ docker run --rm -t --privileged \
+ -v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
+ --name docker-pr$BUILD_NUMBER \
+ -e DOCKER_EXPERIMENTAL \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ docker:${GIT_COMMIT} \
+ hack/test/unit
+ '''
+ }
+ post {
+ always {
+ junit testResults: 'bundles/junit-report.xml', allowEmptyResults: true
+ }
+ }
+ }
+ stage("Integration tests") {
+ environment { TEST_SKIP_INTEGRATION_CLI = '1' }
+ steps {
+ sh '''
+ docker run --rm -t --privileged \
+ -v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
+ --name docker-pr$BUILD_NUMBER \
+ -e DOCKER_EXPERIMENTAL \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ -e TEST_SKIP_INTEGRATION_CLI \
+ -e TIMEOUT \
+ docker:${GIT_COMMIT} \
+ hack/make.sh \
+ dynbinary \
+ test-integration
+ '''
+ }
+ }
+ }
+
+ post {
+ always {
+ sh '''
+ echo "Ensuring container killed."
+ docker rm -vf docker-pr$BUILD_NUMBER || true
+ '''
+
+ sh '''
+ echo "Chowning /workspace to jenkins user"
+ docker run --rm -v "$WORKSPACE:/workspace" busybox chown -R "$(id -u):$(id -g)" /workspace
+ '''
+
+ sh '''
+ echo "Creating powerpc-integration-bundles.tar.gz"
+ # exclude overlay2 directories
+ find bundles -path '*/root/*overlay2' -prune -o -type f \\( -name '*.log' -o -name '*.prof' \\) -print | xargs tar -czf powerpc-integration-bundles.tar.gz
+ '''
+
+ archiveArtifacts artifacts: 'powerpc-integration-bundles.tar.gz'
+ }
+ cleanup {
+ sh 'make clean'
+ deleteDir()
+ }
+ }
+ }
+ stage('powerpc-master') {
+ when {
+ beforeAgent true
+ branch 'master'
+ expression { params.powerpc }
+ }
+ agent { label 'ppc64le-ubuntu-1604' }
+ // power machines run on Docker 18.06, and buildkit has some bugs on that version
+ environment { DOCKER_BUILDKIT = '0' }
+
+ stages {
+ stage("Print info") {
+ steps {
+ sh 'docker version'
+ sh 'docker info'
+ sh '''
+ echo "check-config.sh version: ${CHECK_CONFIG_COMMIT}"
+ curl -fsSL -o ${WORKSPACE}/check-config.sh "https://raw.githubusercontent.com/moby/moby/${CHECK_CONFIG_COMMIT}/contrib/check-config.sh" \
+ && bash ${WORKSPACE}/check-config.sh || true
+ '''
+ }
+ }
+ stage("Build dev image") {
+ steps {
+ sh 'docker build --force-rm --build-arg APT_MIRROR -t docker:${GIT_COMMIT} -f Dockerfile .'
+ }
+ }
+ stage("Integration-cli tests") {
+ environment { TEST_SKIP_INTEGRATION = '1' }
+ steps {
+ sh '''
+ docker run --rm -t --privileged \
+ -v "$WORKSPACE/bundles:/go/src/github.com/docker/docker/bundles" \
+ --name docker-pr$BUILD_NUMBER \
+ -e DOCKER_GITCOMMIT=${GIT_COMMIT} \
+ -e DOCKER_GRAPHDRIVER \
+ -e TEST_SKIP_INTEGRATION \
+ -e TIMEOUT \
+ docker:${GIT_COMMIT} \
+ hack/make.sh \
+ dynbinary \
+ test-integration
+ '''
+ }
+ }
+ }
+
+ post {
+ always {
+ sh '''
+ echo "Ensuring container killed."
+ docker rm -vf docker-pr$BUILD_NUMBER || true
+ '''
+
+ sh '''
+ echo "Chowning /workspace to jenkins user"
+ docker run --rm -v "$WORKSPACE:/workspace" busybox chown -R "$(id -u):$(id -g)" /workspace
+ '''
+
+ sh '''
+ echo "Creating powerpc-integration-cli-bundles.tar.gz"
+ find bundles -path '*/root/*overlay2' -prune -o -type f \\( -name '*.log' -o -name '*.prof' \\) -print | xargs tar -czf powerpc-integration-cli-bundles.tar.gz
+ '''
+
+ archiveArtifacts artifacts: 'powerpc-integration-cli-bundles.tar.gz'
+ }
+ cleanup {
+ sh 'make clean'
+ deleteDir()
+ }
+ }
+ }
+ stage('windowsRS1') {
+ when {
+ beforeAgent true
+ expression { params.windowsRS1 }
+ }
+ agent {
+ node {
+ label 'windows-rs1'
+ customWorkspace 'c:\\gopath\\src\\github.com\\docker\\docker'
+ }
+ }
+ stages {
+ stage("Print info") {
+ steps {
+ sh 'docker version'
+ sh 'docker info'
+ }
+ }
+ stage("Run tests") {
+ steps {
+ powershell '''
+ $ErrorActionPreference = 'Stop'
+ .\\hack\\ci\\windows.ps1
+ exit $LastExitCode
+ '''
+ }
+ }
+ }
+ }
+ stage('windowsRS5-process') {
+ when {
+ beforeAgent true
+ expression { params.windowsRS5 }
+ }
+ agent {
+ node {
+ label 'windows-rs5'
+ customWorkspace 'c:\\gopath\\src\\github.com\\docker\\docker'
+ }
+ }
+ stages {
+ stage("Print info") {
+ steps {
+ sh 'docker version'
+ sh 'docker info'
+ }
+ }
+ stage("Run tests") {
+ steps {
+ powershell '''
+ $ErrorActionPreference = 'Stop'
+ .\\hack\\ci\\windows.ps1
+ exit $LastExitCode
+ '''
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Makefile b/Makefile
index f9fed3e086..a8f5ad9b06 100644
--- a/Makefile
+++ b/Makefile
@@ -47,11 +47,18 @@ DOCKER_ENVS := \
-e DOCKER_PORT \
-e DOCKER_REMAP_ROOT \
-e DOCKER_STORAGE_OPTS \
+ -e DOCKER_TEST_HOST \
-e DOCKER_USERLANDPROXY \
-e DOCKERD_ARGS \
+ -e TEST_INTEGRATION_DEST \
-e TEST_INTEGRATION_DIR \
+ -e TEST_SKIP_INTEGRATION \
+ -e TEST_SKIP_INTEGRATION_CLI \
+ -e TESTDEBUG \
-e TESTDIRS \
-e TESTFLAGS \
+ -e TESTFLAGS_INTEGRATION \
+ -e TESTFLAGS_INTEGRATION_CLI \
-e TIMEOUT \
-e VALIDATE_REPO \
-e VALIDATE_BRANCH \
@@ -102,9 +109,6 @@ export BUILD_APT_MIRROR
SWAGGER_DOCS_PORT ?= 9000
-INTEGRATION_CLI_MASTER_IMAGE := $(if $(INTEGRATION_CLI_MASTER_IMAGE), $(INTEGRATION_CLI_MASTER_IMAGE), integration-cli-master)
-INTEGRATION_CLI_WORKER_IMAGE := $(if $(INTEGRATION_CLI_WORKER_IMAGE), $(INTEGRATION_CLI_WORKER_IMAGE), integration-cli-worker)
-
define \n
@@ -172,8 +176,13 @@ test-docker-py: build ## run the docker-py tests
test-integration-cli: test-integration ## (DEPRECATED) use test-integration
+ifneq ($(and $(TEST_SKIP_INTEGRATION),$(TEST_SKIP_INTEGRATION_CLI)),)
+test-integration:
+ @echo Both integrations suites skipped per environment variables
+else
test-integration: build ## run the integration tests
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary test-integration
+endif
test-integration-flaky: build ## run the stress test for all new integration tests
$(DOCKER_RUN_DOCKER) hack/make.sh dynbinary test-integration-flaky
@@ -202,18 +211,3 @@ swagger-docs: ## preview the API documentation
-e 'REDOC_OPTIONS=hide-hostname="true" lazy-rendering' \
-p $(SWAGGER_DOCS_PORT):80 \
bfirsh/redoc:1.6.2
-
-build-integration-cli-on-swarm: build ## build images and binary for running integration-cli on Swarm in parallel
- @echo "Building hack/integration-cli-on-swarm (if build fails, please refer to hack/integration-cli-on-swarm/README.md)"
- go build -buildmode=pie -o ./hack/integration-cli-on-swarm/integration-cli-on-swarm ./hack/integration-cli-on-swarm/host
- @echo "Building $(INTEGRATION_CLI_MASTER_IMAGE)"
- docker build -t $(INTEGRATION_CLI_MASTER_IMAGE) hack/integration-cli-on-swarm/agent
- @echo "Building $(INTEGRATION_CLI_WORKER_IMAGE) from $(DOCKER_IMAGE)"
- $(eval tmp := integration-cli-worker-tmp)
-# We mount pkgcache, but not bundle (bundle needs to be baked into the image)
-# For avoiding bakings DOCKER_GRAPHDRIVER and so on to image, we cannot use $(DOCKER_ENVS) here
- docker run -t -d --name $(tmp) -e DOCKER_GITCOMMIT -e BUILDFLAGS --privileged $(DOCKER_IMAGE) top
- docker exec $(tmp) hack/make.sh build-integration-test-binary dynbinary
- docker exec $(tmp) go build -buildmode=pie -o /worker github.com/docker/docker/hack/integration-cli-on-swarm/agent/worker
- docker commit -c 'ENTRYPOINT ["/worker"]' $(tmp) $(INTEGRATION_CLI_WORKER_IMAGE)
- docker rm -f $(tmp)
diff --git a/hack/ci/experimental b/hack/ci/experimental
index 9ccbc8425f..10297c7dc9 100755
--- a/hack/ci/experimental
+++ b/hack/ci/experimental
@@ -2,7 +2,7 @@
# Entrypoint for jenkins experimental CI
set -eu -o pipefail
-export DOCKER_EXPERIMENTAL=y
+export DOCKER_EXPERIMENTAL=1
hack/make.sh \
binary-daemon \
diff --git a/hack/ci/janky b/hack/ci/janky
index 88cb9d9c61..ec48165896 100755
--- a/hack/ci/janky
+++ b/hack/ci/janky
@@ -4,10 +4,6 @@ set -eu -o pipefail
hack/validate/default
hack/test/unit
-bash <(curl -s https://codecov.io/bash) \
- -f coverage.txt \
- -C "$GIT_SHA1" || \
- echo 'Codecov failed to upload'
hack/make.sh \
binary-daemon \
diff --git a/hack/dind b/hack/dind
index 3254f9dbe7..4188c1befe 100755
--- a/hack/dind
+++ b/hack/dind
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#!/bin/sh
set -e
# DinD: a wrapper script which allows docker to be run inside a docker container.
diff --git a/hack/dockerfile/install/containerd.installer b/hack/dockerfile/install/containerd.installer
index 8b15eb8ff6..e9f9e4a494 100755
--- a/hack/dockerfile/install/containerd.installer
+++ b/hack/dockerfile/install/containerd.installer
@@ -28,9 +28,9 @@ install_containerd() {
make
)
- mkdir -p ${PREFIX}
+ mkdir -p "${PREFIX}"
- cp bin/containerd ${PREFIX}/containerd
- cp bin/containerd-shim ${PREFIX}/containerd-shim
- cp bin/ctr ${PREFIX}/ctr
+ cp bin/containerd "${PREFIX}/containerd"
+ cp bin/containerd-shim "${PREFIX}/containerd-shim"
+ cp bin/ctr "${PREFIX}/ctr"
}
diff --git a/hack/dockerfile/install/dockercli.installer b/hack/dockerfile/install/dockercli.installer
index ae3aa0dd45..03435fe54b 100755
--- a/hack/dockerfile/install/dockercli.installer
+++ b/hack/dockerfile/install/dockercli.installer
@@ -8,14 +8,13 @@ install_dockercli() {
arch=$(uname -m)
# No official release of these platforms
- if [[ "$arch" != "x86_64" ]] && [[ "$arch" != "s390x" ]]; then
+ if [ "$arch" != "x86_64" ] && [ "$arch" != "s390x" ]; then
build_dockercli
return
fi
url=https://download.docker.com/linux/static
- curl -Ls $url/$DOCKERCLI_CHANNEL/$arch/docker-$DOCKERCLI_VERSION.tgz | \
- tar -xz docker/docker
+ curl -Ls "${url}/${DOCKERCLI_CHANNEL}/${arch}/docker-${DOCKERCLI_VERSION}.tgz" | tar -xz docker/docker
mkdir -p ${PREFIX}
mv docker/docker ${PREFIX}/
rmdir docker
@@ -27,5 +26,5 @@ build_dockercli() {
git checkout -q "v$DOCKERCLI_VERSION"
mkdir -p "$GOPATH/src/github.com/docker"
mv components/cli "$GOPATH/src/github.com/docker/cli"
- go build -buildmode=pie -o ${PREFIX}/docker github.com/docker/cli/cmd/docker
+ go build -buildmode=pie -o "${PREFIX}/docker" "github.com/docker/cli/cmd/docker"
}
diff --git a/hack/dockerfile/install/gometalinter.installer b/hack/dockerfile/install/gometalinter.installer
index d921fd739a..461850f936 100755
--- a/hack/dockerfile/install/gometalinter.installer
+++ b/hack/dockerfile/install/gometalinter.installer
@@ -7,6 +7,6 @@ install_gometalinter() {
go get -d github.com/alecthomas/gometalinter
cd "$GOPATH/src/github.com/alecthomas/gometalinter"
git checkout -q "$GOMETALINTER_COMMIT"
- go build -buildmode=pie -o ${PREFIX}/gometalinter github.com/alecthomas/gometalinter
- GOBIN=${PREFIX} ${PREFIX}/gometalinter --install
+ go build -buildmode=pie -o "${PREFIX}/gometalinter" "github.com/alecthomas/gometalinter"
+ GOBIN=${PREFIX} "${PREFIX}/gometalinter" --install
}
diff --git a/hack/dockerfile/install/gotestsum.installer b/hack/dockerfile/install/gotestsum.installer
new file mode 100755
index 0000000000..032f46f2fe
--- /dev/null
+++ b/hack/dockerfile/install/gotestsum.installer
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+GOTESTSUM_COMMIT='v0.3.5'
+
+install_gotestsum() {
+ echo "Installing gotestsum version $GOTESTSUM_COMMIT"
+ go get -d gotest.tools/gotestsum
+ cd "$GOPATH/src/gotest.tools/gotestsum"
+ git checkout -q "$GOTESTSUM_COMMIT"
+ go build -buildmode=pie -o "${PREFIX}/gotestsum" 'gotest.tools/gotestsum'
+}
diff --git a/hack/dockerfile/install/install.sh b/hack/dockerfile/install/install.sh
index a0ff09da55..5e4a396789 100755
--- a/hack/dockerfile/install/install.sh
+++ b/hack/dockerfile/install/install.sh
@@ -26,5 +26,5 @@ if [ ! -f "${dir}/${bin}.installer" ]; then
exit 1
fi
-. $dir/$bin.installer
-install_$bin "$@"
+. ${dir}/${bin}.installer
+install_${bin} "$@"
diff --git a/hack/dockerfile/install/proxy.installer b/hack/dockerfile/install/proxy.installer
index 0dc73ba725..1b286c5ae1 100755
--- a/hack/dockerfile/install/proxy.installer
+++ b/hack/dockerfile/install/proxy.installer
@@ -32,7 +32,7 @@ _install_proxy() {
git clone https://github.com/docker/libnetwork.git "$GOPATH/src/github.com/docker/libnetwork"
cd "$GOPATH/src/github.com/docker/libnetwork"
git checkout -q "$LIBNETWORK_COMMIT"
- go build $BUILD_MODE -ldflags="$PROXY_LDFLAGS" -o ${PREFIX}/docker-proxy github.com/docker/libnetwork/cmd/proxy
+ go build ${BUILD_MODE} -ldflags="$PROXY_LDFLAGS" -o ${PREFIX}/docker-proxy github.com/docker/libnetwork/cmd/proxy
}
diff --git a/hack/dockerfile/install/runc.installer b/hack/dockerfile/install/runc.installer
index a8156db97f..dd9950ff34 100755
--- a/hack/dockerfile/install/runc.installer
+++ b/hack/dockerfile/install/runc.installer
@@ -25,6 +25,6 @@ install_runc() {
target="$1"
fi
make BUILDTAGS="$RUNC_BUILDTAGS" "$target"
- mkdir -p ${PREFIX}
- cp runc ${PREFIX}/runc
+ mkdir -p "${PREFIX}"
+ cp runc "${PREFIX}/runc"
}
diff --git a/hack/dockerfile/install/tini.installer b/hack/dockerfile/install/tini.installer
index 34f43f15f4..c622357365 100755
--- a/hack/dockerfile/install/tini.installer
+++ b/hack/dockerfile/install/tini.installer
@@ -9,6 +9,6 @@ install_tini() {
git checkout -q "$TINI_COMMIT"
cmake .
make tini-static
- mkdir -p ${PREFIX}
- cp tini-static ${PREFIX}/docker-init
+ mkdir -p "${PREFIX}"
+ cp tini-static "${PREFIX}/docker-init"
}
diff --git a/hack/dockerfile/install/tomlv.installer b/hack/dockerfile/install/tomlv.installer
index c926454f22..52f793122f 100755
--- a/hack/dockerfile/install/tomlv.installer
+++ b/hack/dockerfile/install/tomlv.installer
@@ -8,5 +8,5 @@ install_tomlv() {
echo "Install tomlv version $TOMLV_COMMIT"
git clone https://github.com/BurntSushi/toml.git "$GOPATH/src/github.com/BurntSushi/toml"
cd "$GOPATH/src/github.com/BurntSushi/toml" && git checkout -q "$TOMLV_COMMIT"
- go build -v -buildmode=pie -o ${PREFIX}/tomlv github.com/BurntSushi/toml/cmd/tomlv
+ go build -v -buildmode=pie -o "${PREFIX}/tomlv" "github.com/BurntSushi/toml/cmd/tomlv"
}
diff --git a/hack/dockerfile/install/vndr.installer b/hack/dockerfile/install/vndr.installer
index e6a94e7071..d53fadaf7a 100755
--- a/hack/dockerfile/install/vndr.installer
+++ b/hack/dockerfile/install/vndr.installer
@@ -7,5 +7,5 @@ install_vndr() {
git clone https://github.com/LK4D4/vndr.git "$GOPATH/src/github.com/LK4D4/vndr"
cd "$GOPATH/src/github.com/LK4D4/vndr"
git checkout -q "$VNDR_COMMIT"
- go build -buildmode=pie -v -o ${PREFIX}/vndr .
+ go build -buildmode=pie -v -o "${PREFIX}/vndr" .
}
diff --git a/hack/generate-swagger-api.sh b/hack/generate-swagger-api.sh
index a01a57387a..90a01df027 100755
--- a/hack/generate-swagger-api.sh
+++ b/hack/generate-swagger-api.sh
@@ -2,26 +2,26 @@
set -eu
swagger generate model -f api/swagger.yaml \
- -t api -m types --skip-validator -C api/swagger-gen.yaml \
- -n ErrorResponse \
- -n GraphDriverData \
- -n IdResponse \
- -n ImageDeleteResponseItem \
- -n ImageSummary \
- -n Plugin -n PluginDevice -n PluginMount -n PluginEnv -n PluginInterfaceType \
- -n Port \
- -n ServiceUpdateResponse \
- -n Volume
+ -t api -m types --skip-validator -C api/swagger-gen.yaml \
+ -n ErrorResponse \
+ -n GraphDriverData \
+ -n IdResponse \
+ -n ImageDeleteResponseItem \
+ -n ImageSummary \
+ -n Plugin -n PluginDevice -n PluginMount -n PluginEnv -n PluginInterfaceType \
+ -n Port \
+ -n ServiceUpdateResponse \
+ -n Volume
swagger generate operation -f api/swagger.yaml \
- -t api -a types -m types -C api/swagger-gen.yaml \
- -T api/templates --skip-responses --skip-parameters --skip-validator \
- -n Authenticate \
- -n ContainerChanges \
- -n ContainerCreate \
- -n ContainerTop \
- -n ContainerUpdate \
- -n ContainerWait \
- -n ImageHistory \
- -n VolumeCreate \
- -n VolumeList
+ -t api -a types -m types -C api/swagger-gen.yaml \
+ -T api/templates --skip-responses --skip-parameters --skip-validator \
+ -n Authenticate \
+ -n ContainerChanges \
+ -n ContainerCreate \
+ -n ContainerTop \
+ -n ContainerUpdate \
+ -n ContainerWait \
+ -n ImageHistory \
+ -n VolumeCreate \
+ -n VolumeList
diff --git a/hack/integration-cli-on-swarm/README.md b/hack/integration-cli-on-swarm/README.md
deleted file mode 100644
index 852b36cea1..0000000000
--- a/hack/integration-cli-on-swarm/README.md
+++ /dev/null
@@ -1,68 +0,0 @@
-# Integration Testing on Swarm
-
-IT on Swarm allows you to execute integration test in parallel across a Docker Swarm cluster
-
-## Architecture
-
-### Master service
-
- - Works as a funker caller
- - Calls a worker funker (`-worker-service`) with a chunk of `-check.f` filter strings (passed as a file via `-input` flag, typically `/mnt/input`)
-
-### Worker service
-
- - Works as a funker callee
- - Executes an equivalent of `TESTFLAGS=-check.f TestFoo|TestBar|TestBaz ... make test-integration` using the bind-mounted API socket (`docker.sock`)
-
-### Client
-
- - Controls master and workers via `docker stack`
- - No need to have a local daemon
-
-Typically, the master and workers are supposed to be running on a cloud environment,
-while the client is supposed to be running on a laptop, e.g. Docker for Mac/Windows.
-
-## Requirement
-
- - Docker daemon 1.13 or later
- - Private registry for distributed execution with multiple nodes
-
-## Usage
-
-### Step 1: Prepare images
-
- $ make build-integration-cli-on-swarm
-
-Following environment variables are known to work in this step:
-
- - `BUILDFLAGS`
-
-Note: during the transition into Moby Project, you might need to create a symbolic link `$GOPATH/src/github.com/docker/docker` to `$GOPATH/src/github.com/moby/moby`.
-
-### Step 2: Execute tests
-
- $ ./hack/integration-cli-on-swarm/integration-cli-on-swarm -replicas 40 -push-worker-image YOUR_REGISTRY.EXAMPLE.COM/integration-cli-worker:latest
-
-Following environment variables are known to work in this step:
-
- - `DOCKER_GRAPHDRIVER`
- - `DOCKER_EXPERIMENTAL`
-
-#### Flags
-
-Basic flags:
-
- - `-replicas N`: the number of worker service replicas. i.e. degree of parallelism.
- - `-chunks N`: the number of chunks. By default, `chunks` == `replicas`.
- - `-push-worker-image REGISTRY/IMAGE:TAG`: push the worker image to the registry. Note that if you have only single node and hence you do not need a private registry, you do not need to specify `-push-worker-image`.
-
-Experimental flags for mitigating makespan nonuniformity:
-
- - `-shuffle`: Shuffle the test filter strings
-
-Flags for debugging IT on Swarm itself:
-
- - `-rand-seed N`: the random seed. This flag is useful for deterministic replaying. By default(0), the timestamp is used.
- - `-filters-file FILE`: the file contains `-check.f` strings. By default, the file is automatically generated.
- - `-dry-run`: skip the actual workload
- - `keep-executor`: do not auto-remove executor containers, which is used for running privileged programs on Swarm
diff --git a/hack/integration-cli-on-swarm/agent/Dockerfile b/hack/integration-cli-on-swarm/agent/Dockerfile
deleted file mode 100644
index 1ae228f6ef..0000000000
--- a/hack/integration-cli-on-swarm/agent/Dockerfile
+++ /dev/null
@@ -1,6 +0,0 @@
-# this Dockerfile is solely used for the master image.
-# Please refer to the top-level Makefile for the worker image.
-FROM golang:1.7
-ADD . /go/src/github.com/docker/docker/hack/integration-cli-on-swarm/agent
-RUN go build -buildmode=pie -o /master github.com/docker/docker/hack/integration-cli-on-swarm/agent/master
-ENTRYPOINT ["/master"]
diff --git a/hack/integration-cli-on-swarm/agent/master/call.go b/hack/integration-cli-on-swarm/agent/master/call.go
deleted file mode 100644
index dab9c67077..0000000000
--- a/hack/integration-cli-on-swarm/agent/master/call.go
+++ /dev/null
@@ -1,132 +0,0 @@
-package main
-
-import (
- "encoding/json"
- "fmt"
- "log"
- "strings"
- "sync"
- "sync/atomic"
- "time"
-
- "github.com/bfirsh/funker-go"
- "github.com/docker/docker/hack/integration-cli-on-swarm/agent/types"
-)
-
-const (
- // funkerRetryTimeout is for the issue https://github.com/bfirsh/funker/issues/3
- // When all the funker replicas are busy in their own job, we cannot connect to funker.
- funkerRetryTimeout = 1 * time.Hour
- funkerRetryDuration = 1 * time.Second
-)
-
-// ticker is needed for some CI (e.g., on Travis, job is aborted when no output emitted for 10 minutes)
-func ticker(d time.Duration) chan struct{} {
- t := time.NewTicker(d)
- stop := make(chan struct{})
- go func() {
- for {
- select {
- case <-t.C:
- log.Printf("tick (just for keeping CI job active) per %s", d.String())
- case <-stop:
- t.Stop()
- }
- }
- }()
- return stop
-}
-
-func executeTests(funkerName string, testChunks [][]string) error {
- tickerStopper := ticker(9*time.Minute + 55*time.Second)
- defer func() {
- close(tickerStopper)
- }()
- begin := time.Now()
- log.Printf("Executing %d chunks in parallel, against %q", len(testChunks), funkerName)
- var wg sync.WaitGroup
- var passed, failed uint32
- for chunkID, tests := range testChunks {
- log.Printf("Executing chunk %d (contains %d test filters)", chunkID, len(tests))
- wg.Add(1)
- go func(chunkID int, tests []string) {
- defer wg.Done()
- chunkBegin := time.Now()
- result, err := executeTestChunkWithRetry(funkerName, types.Args{
- ChunkID: chunkID,
- Tests: tests,
- })
- if result.RawLog != "" {
- for _, s := range strings.Split(result.RawLog, "\n") {
- log.Printf("Log (chunk %d): %s", chunkID, s)
- }
- }
- if err != nil {
- log.Printf("Error while executing chunk %d: %v",
- chunkID, err)
- atomic.AddUint32(&failed, 1)
- } else {
- if result.Code == 0 {
- atomic.AddUint32(&passed, 1)
- } else {
- atomic.AddUint32(&failed, 1)
- }
- log.Printf("Finished chunk %d [%d/%d] with %d test filters in %s, code=%d.",
- chunkID, passed+failed, len(testChunks), len(tests),
- time.Since(chunkBegin), result.Code)
- }
- }(chunkID, tests)
- }
- wg.Wait()
- // TODO: print actual tests rather than chunks
- log.Printf("Executed %d chunks in %s. PASS: %d, FAIL: %d.",
- len(testChunks), time.Since(begin), passed, failed)
- if failed > 0 {
- return fmt.Errorf("%d chunks failed", failed)
- }
- return nil
-}
-
-func executeTestChunk(funkerName string, args types.Args) (types.Result, error) {
- ret, err := funker.Call(funkerName, args)
- if err != nil {
- return types.Result{}, err
- }
- tmp, err := json.Marshal(ret)
- if err != nil {
- return types.Result{}, err
- }
- var result types.Result
- err = json.Unmarshal(tmp, &result)
- return result, err
-}
-
-func executeTestChunkWithRetry(funkerName string, args types.Args) (types.Result, error) {
- begin := time.Now()
- for i := 0; time.Since(begin) < funkerRetryTimeout; i++ {
- result, err := executeTestChunk(funkerName, args)
- if err == nil {
- log.Printf("executeTestChunk(%q, %d) returned code %d in trial %d", funkerName, args.ChunkID, result.Code, i)
- return result, nil
- }
- if errorSeemsInteresting(err) {
- log.Printf("Error while calling executeTestChunk(%q, %d), will retry (trial %d): %v",
- funkerName, args.ChunkID, i, err)
- }
- // TODO: non-constant sleep
- time.Sleep(funkerRetryDuration)
- }
- return types.Result{}, fmt.Errorf("could not call executeTestChunk(%q, %d) in %v", funkerName, args.ChunkID, funkerRetryTimeout)
-}
-
-// errorSeemsInteresting returns true if err does not seem about https://github.com/bfirsh/funker/issues/3
-func errorSeemsInteresting(err error) bool {
- boringSubstrs := []string{"connection refused", "connection reset by peer", "no such host", "transport endpoint is not connected", "no route to host"}
- errS := err.Error()
- for _, boringS := range boringSubstrs {
- if strings.Contains(errS, boringS) {
- return false
- }
- }
- return true
-}
diff --git a/hack/integration-cli-on-swarm/agent/master/master.go b/hack/integration-cli-on-swarm/agent/master/master.go
deleted file mode 100644
index a0d9a0d381..0000000000
--- a/hack/integration-cli-on-swarm/agent/master/master.go
+++ /dev/null
@@ -1,65 +0,0 @@
-package main
-
-import (
- "errors"
- "flag"
- "io/ioutil"
- "log"
- "strings"
-)
-
-func main() {
- if err := xmain(); err != nil {
- log.Fatalf("fatal error: %v", err)
- }
-}
-
-func xmain() error {
- workerService := flag.String("worker-service", "", "Name of worker service")
- chunks := flag.Int("chunks", 0, "Number of chunks")
- input := flag.String("input", "", "Path to input file")
- randSeed := flag.Int64("rand-seed", int64(0), "Random seed")
- shuffle := flag.Bool("shuffle", false, "Shuffle the input so as to mitigate makespan nonuniformity")
- flag.Parse()
- if *workerService == "" {
- return errors.New("worker-service unset")
- }
- if *chunks == 0 {
- return errors.New("chunks unset")
- }
- if *input == "" {
- return errors.New("input unset")
- }
-
- tests, err := loadTests(*input)
- if err != nil {
- return err
- }
- testChunks := chunkTests(tests, *chunks, *shuffle, *randSeed)
- log.Printf("Loaded %d tests (%d chunks)", len(tests), len(testChunks))
- return executeTests(*workerService, testChunks)
-}
-
-func chunkTests(tests []string, numChunks int, shuffle bool, randSeed int64) [][]string {
- // shuffling (experimental) mitigates makespan nonuniformity
- // Not sure this can cause some locality problem..
- if shuffle {
- shuffleStrings(tests, randSeed)
- }
- return chunkStrings(tests, numChunks)
-}
-
-func loadTests(filename string) ([]string, error) {
- b, err := ioutil.ReadFile(filename)
- if err != nil {
- return nil, err
- }
- var tests []string
- for _, line := range strings.Split(string(b), "\n") {
- s := strings.TrimSpace(line)
- if s != "" {
- tests = append(tests, s)
- }
- }
- return tests, nil
-}
diff --git a/hack/integration-cli-on-swarm/agent/master/set.go b/hack/integration-cli-on-swarm/agent/master/set.go
deleted file mode 100644
index d28c41da7f..0000000000
--- a/hack/integration-cli-on-swarm/agent/master/set.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package main
-
-import (
- "math/rand"
-)
-
-// chunkStrings chunks the string slice
-func chunkStrings(x []string, numChunks int) [][]string {
- var result [][]string
- chunkSize := (len(x) + numChunks - 1) / numChunks
- for i := 0; i < len(x); i += chunkSize {
- ub := i + chunkSize
- if ub > len(x) {
- ub = len(x)
- }
- result = append(result, x[i:ub])
- }
- return result
-}
-
-// shuffleStrings shuffles strings
-func shuffleStrings(x []string, seed int64) {
- r := rand.New(rand.NewSource(seed))
- for i := range x {
- j := r.Intn(i + 1)
- x[i], x[j] = x[j], x[i]
- }
-}
diff --git a/hack/integration-cli-on-swarm/agent/master/set_test.go b/hack/integration-cli-on-swarm/agent/master/set_test.go
deleted file mode 100644
index c172562b1b..0000000000
--- a/hack/integration-cli-on-swarm/agent/master/set_test.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package main
-
-import (
- "fmt"
- "reflect"
- "testing"
- "time"
-)
-
-func generateInput(inputLen int) []string {
- var input []string
- for i := 0; i < inputLen; i++ {
- input = append(input, fmt.Sprintf("s%d", i))
- }
-
- return input
-}
-
-func testChunkStrings(t *testing.T, inputLen, numChunks int) {
- t.Logf("inputLen=%d, numChunks=%d", inputLen, numChunks)
- input := generateInput(inputLen)
- result := chunkStrings(input, numChunks)
- t.Logf("result has %d chunks", len(result))
- var inputReconstructedFromResult []string
- for i, chunk := range result {
- t.Logf("chunk %d has %d elements", i, len(chunk))
- inputReconstructedFromResult = append(inputReconstructedFromResult, chunk...)
- }
- if !reflect.DeepEqual(input, inputReconstructedFromResult) {
- t.Fatal("input != inputReconstructedFromResult")
- }
-}
-
-func TestChunkStrings_4_4(t *testing.T) {
- testChunkStrings(t, 4, 4)
-}
-
-func TestChunkStrings_4_1(t *testing.T) {
- testChunkStrings(t, 4, 1)
-}
-
-func TestChunkStrings_1_4(t *testing.T) {
- testChunkStrings(t, 1, 4)
-}
-
-func TestChunkStrings_1000_8(t *testing.T) {
- testChunkStrings(t, 1000, 8)
-}
-
-func TestChunkStrings_1000_9(t *testing.T) {
- testChunkStrings(t, 1000, 9)
-}
-
-func testShuffleStrings(t *testing.T, inputLen int, seed int64) {
- t.Logf("inputLen=%d, seed=%d", inputLen, seed)
- x := generateInput(inputLen)
- shuffleStrings(x, seed)
- t.Logf("shuffled: %v", x)
-}
-
-func TestShuffleStrings_100(t *testing.T) {
- testShuffleStrings(t, 100, time.Now().UnixNano())
-}
diff --git a/hack/integration-cli-on-swarm/agent/types/types.go b/hack/integration-cli-on-swarm/agent/types/types.go
deleted file mode 100644
index fc598f0330..0000000000
--- a/hack/integration-cli-on-swarm/agent/types/types.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package types
-
-// Args is the type for funker args
-type Args struct {
- // ChunkID is an unique number of the chunk
- ChunkID int `json:"chunk_id"`
- // Tests is the set of the strings that are passed as `-check.f` filters
- Tests []string `json:"tests"`
-}
-
-// Result is the type for funker result
-type Result struct {
- // ChunkID corresponds to Args.ChunkID
- ChunkID int `json:"chunk_id"`
- // Code is the exit code
- Code int `json:"code"`
- RawLog string `json:"raw_log"`
-}
diff --git a/hack/integration-cli-on-swarm/agent/vendor.conf b/hack/integration-cli-on-swarm/agent/vendor.conf
deleted file mode 100644
index efd6d6d049..0000000000
--- a/hack/integration-cli-on-swarm/agent/vendor.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-# dependencies specific to worker (i.e. github.com/docker/docker/...) are not vendored here
-github.com/bfirsh/funker-go eaa0a2e06f30e72c9a0b7f858951e581e26ef773
diff --git a/hack/integration-cli-on-swarm/agent/vendor/github.com/bfirsh/funker-go/LICENSE b/hack/integration-cli-on-swarm/agent/vendor/github.com/bfirsh/funker-go/LICENSE
deleted file mode 100644
index 75191a4dc7..0000000000
--- a/hack/integration-cli-on-swarm/agent/vendor/github.com/bfirsh/funker-go/LICENSE
+++ /dev/null
@@ -1,191 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- Copyright 2016 Docker, Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/hack/integration-cli-on-swarm/agent/vendor/github.com/bfirsh/funker-go/call.go b/hack/integration-cli-on-swarm/agent/vendor/github.com/bfirsh/funker-go/call.go
deleted file mode 100644
index ac0338d2d7..0000000000
--- a/hack/integration-cli-on-swarm/agent/vendor/github.com/bfirsh/funker-go/call.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package funker
-
-import (
- "encoding/json"
- "io/ioutil"
- "net"
- "time"
-)
-
-// Call a Funker function
-func Call(name string, args interface{}) (interface{}, error) {
- argsJSON, err := json.Marshal(args)
- if err != nil {
- return nil, err
- }
-
- addr, err := net.ResolveTCPAddr("tcp", name+":9999")
- if err != nil {
- return nil, err
- }
-
- conn, err := net.DialTCP("tcp", nil, addr)
- if err != nil {
- return nil, err
- }
- // Keepalive is a workaround for docker/docker#29655 .
- // The implementation of FIN_WAIT2 seems weird on Swarm-mode.
- // It seems always refuseing any packet after 60 seconds.
- //
- // TODO: remove this workaround if the issue gets resolved on the Docker side
- if err := conn.SetKeepAlive(true); err != nil {
- return nil, err
- }
- if err := conn.SetKeepAlivePeriod(30 * time.Second); err != nil {
- return nil, err
- }
- if _, err = conn.Write(argsJSON); err != nil {
- return nil, err
- }
- if err = conn.CloseWrite(); err != nil {
- return nil, err
- }
- retJSON, err := ioutil.ReadAll(conn)
- if err != nil {
- return nil, err
- }
- var ret interface{}
- err = json.Unmarshal(retJSON, &ret)
- return ret, err
-}
diff --git a/hack/integration-cli-on-swarm/agent/vendor/github.com/bfirsh/funker-go/handle.go b/hack/integration-cli-on-swarm/agent/vendor/github.com/bfirsh/funker-go/handle.go
deleted file mode 100644
index 89878994dc..0000000000
--- a/hack/integration-cli-on-swarm/agent/vendor/github.com/bfirsh/funker-go/handle.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package funker
-
-import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "net"
- "reflect"
-)
-
-// Handle a Funker function.
-func Handle(handler interface{}) error {
- handlerValue := reflect.ValueOf(handler)
- handlerType := handlerValue.Type()
- if handlerType.Kind() != reflect.Func || handlerType.NumIn() != 1 || handlerType.NumOut() != 1 {
- return fmt.Errorf("Handler must be a function with a single parameter and single return value.")
- }
- argsValue := reflect.New(handlerType.In(0))
-
- listener, err := net.Listen("tcp", ":9999")
- if err != nil {
- return err
- }
- conn, err := listener.Accept()
- if err != nil {
- return err
- }
- // We close listener, because we only allow single request.
- // Note that TCP "backlog" cannot be used for that purpose.
- // http://www.perlmonks.org/?node_id=940662
- if err = listener.Close(); err != nil {
- return err
- }
- argsJSON, err := ioutil.ReadAll(conn)
- if err != nil {
- return err
- }
- err = json.Unmarshal(argsJSON, argsValue.Interface())
- if err != nil {
- return err
- }
-
- ret := handlerValue.Call([]reflect.Value{argsValue.Elem()})[0].Interface()
- retJSON, err := json.Marshal(ret)
- if err != nil {
- return err
- }
-
- if _, err = conn.Write(retJSON); err != nil {
- return err
- }
-
- return conn.Close()
-}
diff --git a/hack/integration-cli-on-swarm/agent/worker/executor.go b/hack/integration-cli-on-swarm/agent/worker/executor.go
deleted file mode 100644
index d37b6533f6..0000000000
--- a/hack/integration-cli-on-swarm/agent/worker/executor.go
+++ /dev/null
@@ -1,118 +0,0 @@
-package main
-
-import (
- "bytes"
- "context"
- "fmt"
- "io"
- "os"
- "strings"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/container"
- "github.com/docker/docker/api/types/mount"
- "github.com/docker/docker/client"
- "github.com/docker/docker/pkg/stdcopy"
-)
-
-// testChunkExecutor executes integration-cli binary.
-// image needs to be the worker image itself. testFlags are OR-set of regexp for filtering tests.
-type testChunkExecutor func(image string, tests []string) (int64, string, error)
-
-func dryTestChunkExecutor() testChunkExecutor {
- return func(image string, tests []string) (int64, string, error) {
- return 0, fmt.Sprintf("DRY RUN (image=%q, tests=%v)", image, tests), nil
- }
-}
-
-// privilegedTestChunkExecutor invokes a privileged container from the worker
-// service via bind-mounted API socket so as to execute the test chunk
-func privilegedTestChunkExecutor(autoRemove bool) testChunkExecutor {
- return func(image string, tests []string) (int64, string, error) {
- cli, err := client.NewClientWithOpts(client.FromEnv)
- if err != nil {
- return 0, "", err
- }
- // propagate variables from the host (needs to be defined in the compose file)
- experimental := os.Getenv("DOCKER_EXPERIMENTAL")
- graphdriver := os.Getenv("DOCKER_GRAPHDRIVER")
- if graphdriver == "" {
- info, err := cli.Info(context.Background())
- if err != nil {
- return 0, "", err
- }
- graphdriver = info.Driver
- }
- // `daemon_dest` is similar to `$DEST` (e.g. `bundles/VERSION/test-integration`)
- // but it exists outside of `bundles` so as to make `$DOCKER_GRAPHDRIVER` work.
- //
- // Without this hack, `$DOCKER_GRAPHDRIVER` fails because of (e.g.) `overlay2 is not supported over overlayfs`
- //
- // see integration-cli/daemon/daemon.go
- daemonDest := "/daemon_dest"
- config := container.Config{
- Image: image,
- Env: []string{
- "TESTFLAGS=-check.f " + strings.Join(tests, "|"),
- "KEEPBUNDLE=1",
- "DOCKER_INTEGRATION_TESTS_VERIFIED=1", // for avoiding rebuilding integration-cli
- "DOCKER_EXPERIMENTAL=" + experimental,
- "DOCKER_GRAPHDRIVER=" + graphdriver,
- "DOCKER_INTEGRATION_DAEMON_DEST=" + daemonDest,
- },
- Labels: map[string]string{
- "org.dockerproject.integration-cli-on-swarm": "",
- "org.dockerproject.integration-cli-on-swarm.comment": "this non-service container is created for running privileged programs on Swarm. you can remove this container manually if the corresponding service is already stopped.",
- },
- Entrypoint: []string{"hack/dind"},
- Cmd: []string{"hack/make.sh", "test-integration"},
- }
- hostConfig := container.HostConfig{
- AutoRemove: autoRemove,
- Privileged: true,
- Mounts: []mount.Mount{
- {
- Type: mount.TypeVolume,
- Target: daemonDest,
- },
- },
- }
- id, stream, err := runContainer(context.Background(), cli, config, hostConfig)
- if err != nil {
- return 0, "", err
- }
- var b bytes.Buffer
- teeContainerStream(&b, os.Stdout, os.Stderr, stream)
- resultC, errC := cli.ContainerWait(context.Background(), id, "")
- select {
- case err := <-errC:
- return 0, "", err
- case result := <-resultC:
- return result.StatusCode, b.String(), nil
- }
- }
-}
-
-func runContainer(ctx context.Context, cli *client.Client, config container.Config, hostConfig container.HostConfig) (string, io.ReadCloser, error) {
- created, err := cli.ContainerCreate(context.Background(),
- &config, &hostConfig, nil, "")
- if err != nil {
- return "", nil, err
- }
- if err = cli.ContainerStart(ctx, created.ID, types.ContainerStartOptions{}); err != nil {
- return "", nil, err
- }
- stream, err := cli.ContainerLogs(ctx,
- created.ID,
- types.ContainerLogsOptions{
- ShowStdout: true,
- ShowStderr: true,
- Follow: true,
- })
- return created.ID, stream, err
-}
-
-func teeContainerStream(w, stdout, stderr io.Writer, stream io.ReadCloser) {
- stdcopy.StdCopy(io.MultiWriter(w, stdout), io.MultiWriter(w, stderr), stream)
- stream.Close()
-}
diff --git a/hack/integration-cli-on-swarm/agent/worker/worker.go b/hack/integration-cli-on-swarm/agent/worker/worker.go
deleted file mode 100644
index ea8bb3fe27..0000000000
--- a/hack/integration-cli-on-swarm/agent/worker/worker.go
+++ /dev/null
@@ -1,69 +0,0 @@
-package main
-
-import (
- "flag"
- "fmt"
- "log"
- "time"
-
- "github.com/bfirsh/funker-go"
- "github.com/docker/distribution/reference"
- "github.com/docker/docker/hack/integration-cli-on-swarm/agent/types"
-)
-
-func main() {
- if err := xmain(); err != nil {
- log.Fatalf("fatal error: %v", err)
- }
-}
-
-func validImageDigest(s string) bool {
- return reference.DigestRegexp.FindString(s) != ""
-}
-
-func xmain() error {
- workerImageDigest := flag.String("worker-image-digest", "", "Needs to be the digest of this worker image itself")
- dryRun := flag.Bool("dry-run", false, "Dry run")
- keepExecutor := flag.Bool("keep-executor", false, "Do not auto-remove executor containers, which is used for running privileged programs on Swarm")
- flag.Parse()
- if !validImageDigest(*workerImageDigest) {
- // Because of issue #29582.
- // `docker service create localregistry.example.com/blahblah:latest` pulls the image data to local, but not a tag.
- // So, `docker run localregistry.example.com/blahblah:latest` fails: `Unable to find image 'localregistry.example.com/blahblah:latest' locally`
- return fmt.Errorf("worker-image-digest must be a digest, got %q", *workerImageDigest)
- }
- executor := privilegedTestChunkExecutor(!*keepExecutor)
- if *dryRun {
- executor = dryTestChunkExecutor()
- }
- return handle(*workerImageDigest, executor)
-}
-
-func handle(workerImageDigest string, executor testChunkExecutor) error {
- log.Printf("Waiting for a funker request")
- return funker.Handle(func(args *types.Args) types.Result {
- log.Printf("Executing chunk %d, contains %d test filters",
- args.ChunkID, len(args.Tests))
- begin := time.Now()
- code, rawLog, err := executor(workerImageDigest, args.Tests)
- if err != nil {
- log.Printf("Error while executing chunk %d: %v", args.ChunkID, err)
- if code == 0 {
- // Make sure this is a failure
- code = 1
- }
- return types.Result{
- ChunkID: args.ChunkID,
- Code: int(code),
- RawLog: rawLog,
- }
- }
- elapsed := time.Since(begin)
- log.Printf("Finished chunk %d, code=%d, elapsed=%v", args.ChunkID, code, elapsed)
- return types.Result{
- ChunkID: args.ChunkID,
- Code: int(code),
- RawLog: rawLog,
- }
- })
-}
diff --git a/hack/integration-cli-on-swarm/host/compose.go b/hack/integration-cli-on-swarm/host/compose.go
deleted file mode 100644
index a92282a1a0..0000000000
--- a/hack/integration-cli-on-swarm/host/compose.go
+++ /dev/null
@@ -1,122 +0,0 @@
-package main
-
-import (
- "context"
- "io/ioutil"
- "os"
- "path/filepath"
- "text/template"
-
- "github.com/docker/docker/client"
-)
-
-const composeTemplate = `# generated by integration-cli-on-swarm
-version: "3"
-
-services:
- worker:
- image: "{{.WorkerImage}}"
- command: ["-worker-image-digest={{.WorkerImageDigest}}", "-dry-run={{.DryRun}}", "-keep-executor={{.KeepExecutor}}"]
- networks:
- - net
- volumes:
-# Bind-mount the API socket so that we can invoke "docker run --privileged" within the service containers
- - /var/run/docker.sock:/var/run/docker.sock
- environment:
- - DOCKER_GRAPHDRIVER={{.EnvDockerGraphDriver}}
- - DOCKER_EXPERIMENTAL={{.EnvDockerExperimental}}
- deploy:
- mode: replicated
- replicas: {{.Replicas}}
- restart_policy:
-# The restart condition needs to be any for funker function
- condition: any
-
- master:
- image: "{{.MasterImage}}"
- command: ["-worker-service=worker", "-input=/mnt/input", "-chunks={{.Chunks}}", "-shuffle={{.Shuffle}}", "-rand-seed={{.RandSeed}}"]
- networks:
- - net
- volumes:
- - {{.Volume}}:/mnt
- deploy:
- mode: replicated
- replicas: 1
- restart_policy:
- condition: none
- placement:
-# Make sure the master can access the volume
- constraints: [node.id == {{.SelfNodeID}}]
-
-networks:
- net:
-
-volumes:
- {{.Volume}}:
- external: true
-`
-
-type composeOptions struct {
- Replicas int
- Chunks int
- MasterImage string
- WorkerImage string
- Volume string
- Shuffle bool
- RandSeed int64
- DryRun bool
- KeepExecutor bool
-}
-
-type composeTemplateOptions struct {
- composeOptions
- WorkerImageDigest string
- SelfNodeID string
- EnvDockerGraphDriver string
- EnvDockerExperimental string
-}
-
-// createCompose creates "dir/docker-compose.yml".
-// If dir is empty, TempDir() is used.
-func createCompose(dir string, cli *client.Client, opts composeOptions) (string, error) {
- if dir == "" {
- var err error
- dir, err = ioutil.TempDir("", "integration-cli-on-swarm-")
- if err != nil {
- return "", err
- }
- }
- resolved := composeTemplateOptions{}
- resolved.composeOptions = opts
- workerImageInspect, _, err := cli.ImageInspectWithRaw(context.Background(), defaultWorkerImageName)
- if err != nil {
- return "", err
- }
- if len(workerImageInspect.RepoDigests) > 0 {
- resolved.WorkerImageDigest = workerImageInspect.RepoDigests[0]
- } else {
- // fall back for non-pushed image
- resolved.WorkerImageDigest = workerImageInspect.ID
- }
- info, err := cli.Info(context.Background())
- if err != nil {
- return "", err
- }
- resolved.SelfNodeID = info.Swarm.NodeID
- resolved.EnvDockerGraphDriver = os.Getenv("DOCKER_GRAPHDRIVER")
- resolved.EnvDockerExperimental = os.Getenv("DOCKER_EXPERIMENTAL")
- composeFilePath := filepath.Join(dir, "docker-compose.yml")
- tmpl, err := template.New("").Parse(composeTemplate)
- if err != nil {
- return "", err
- }
- f, err := os.Create(composeFilePath)
- if err != nil {
- return "", err
- }
- defer f.Close()
- if err = tmpl.Execute(f, resolved); err != nil {
- return "", err
- }
- return composeFilePath, nil
-}
diff --git a/hack/integration-cli-on-swarm/host/dockercmd.go b/hack/integration-cli-on-swarm/host/dockercmd.go
deleted file mode 100644
index c08b763a2b..0000000000
--- a/hack/integration-cli-on-swarm/host/dockercmd.go
+++ /dev/null
@@ -1,64 +0,0 @@
-package main
-
-import (
- "fmt"
- "os"
- "os/exec"
- "strings"
- "time"
-
- "github.com/docker/docker/client"
-)
-
-func system(commands [][]string) error {
- for _, c := range commands {
- cmd := exec.Command(c[0], c[1:]...)
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- cmd.Env = os.Environ()
- if err := cmd.Run(); err != nil {
- return err
- }
- }
- return nil
-}
-
-func pushImage(unusedCli *client.Client, remote, local string) error {
- // FIXME: eliminate os/exec (but it is hard to pass auth without os/exec ...)
- return system([][]string{
- {"docker", "image", "tag", local, remote},
- {"docker", "image", "push", remote},
- })
-}
-
-func deployStack(unusedCli *client.Client, stackName, composeFilePath string) error {
- // FIXME: eliminate os/exec (but stack is implemented in CLI ...)
- return system([][]string{
- {"docker", "stack", "deploy",
- "--compose-file", composeFilePath,
- "--with-registry-auth",
- stackName},
- })
-}
-
-func hasStack(unusedCli *client.Client, stackName string) bool {
- // FIXME: eliminate os/exec (but stack is implemented in CLI ...)
- out, err := exec.Command("docker", "stack", "ls").CombinedOutput()
- if err != nil {
- panic(fmt.Errorf("`docker stack ls` failed with: %s", string(out)))
- }
- // FIXME: not accurate
- return strings.Contains(string(out), stackName)
-}
-
-func removeStack(unusedCli *client.Client, stackName string) error {
- // FIXME: eliminate os/exec (but stack is implemented in CLI ...)
- if err := system([][]string{
- {"docker", "stack", "rm", stackName},
- }); err != nil {
- return err
- }
- // FIXME
- time.Sleep(10 * time.Second)
- return nil
-}
diff --git a/hack/integration-cli-on-swarm/host/enumerate.go b/hack/integration-cli-on-swarm/host/enumerate.go
deleted file mode 100644
index 3354c23c07..0000000000
--- a/hack/integration-cli-on-swarm/host/enumerate.go
+++ /dev/null
@@ -1,55 +0,0 @@
-package main
-
-import (
- "fmt"
- "io/ioutil"
- "path/filepath"
- "regexp"
-)
-
-var testFuncRegexp *regexp.Regexp
-
-func init() {
- testFuncRegexp = regexp.MustCompile(`(?m)^\s*func\s+\(\w*\s*\*(\w+Suite)\)\s+(Test\w+)`)
-}
-
-func enumerateTestsForBytes(b []byte) ([]string, error) {
- var tests []string
- submatches := testFuncRegexp.FindAllSubmatch(b, -1)
- for _, submatch := range submatches {
- if len(submatch) == 3 {
- tests = append(tests, fmt.Sprintf("%s.%s$", submatch[1], submatch[2]))
- }
- }
- return tests, nil
-}
-
-// enumerateTests enumerates valid `-check.f` strings for all the test functions.
-// Note that we use regexp rather than parsing Go files for performance reason.
-// (Try `TESTFLAGS=-check.list make test-integration` to see the slowness of parsing)
-// The files needs to be `gofmt`-ed
-//
-// The result will be as follows, but unsorted ('$' is appended because they are regexp for `-check.f`):
-// "DockerAuthzSuite.TestAuthZPluginAPIDenyResponse$"
-// "DockerAuthzSuite.TestAuthZPluginAllowEventStream$"
-// ...
-// "DockerTrustedSwarmSuite.TestTrustedServiceUpdate$"
-func enumerateTests(wd string) ([]string, error) {
- testGoFiles, err := filepath.Glob(filepath.Join(wd, "integration-cli", "*_test.go"))
- if err != nil {
- return nil, err
- }
- var allTests []string
- for _, testGoFile := range testGoFiles {
- b, err := ioutil.ReadFile(testGoFile)
- if err != nil {
- return nil, err
- }
- tests, err := enumerateTestsForBytes(b)
- if err != nil {
- return nil, err
- }
- allTests = append(allTests, tests...)
- }
- return allTests, nil
-}
diff --git a/hack/integration-cli-on-swarm/host/enumerate_test.go b/hack/integration-cli-on-swarm/host/enumerate_test.go
deleted file mode 100644
index d6049ae52e..0000000000
--- a/hack/integration-cli-on-swarm/host/enumerate_test.go
+++ /dev/null
@@ -1,84 +0,0 @@
-package main
-
-import (
- "os"
- "path/filepath"
- "reflect"
- "sort"
- "strings"
- "testing"
-)
-
-func getRepoTopDir(t *testing.T) string {
- wd, err := os.Getwd()
- if err != nil {
- t.Fatal(err)
- }
- wd = filepath.Clean(wd)
- suffix := "hack/integration-cli-on-swarm/host"
- if !strings.HasSuffix(wd, suffix) {
- t.Skipf("cwd seems strange (needs to have suffix %s): %v", suffix, wd)
- }
- return filepath.Clean(filepath.Join(wd, "../../.."))
-}
-
-func TestEnumerateTests(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping in short mode")
- }
- tests, err := enumerateTests(getRepoTopDir(t))
- if err != nil {
- t.Fatal(err)
- }
- sort.Strings(tests)
- t.Logf("enumerated %d test filter strings:", len(tests))
- for _, s := range tests {
- t.Logf("- %q", s)
- }
-}
-
-func TestEnumerateTestsForBytes(t *testing.T) {
- b := []byte(`package main
-import (
- "github.com/go-check/check"
-)
-
-func (s *FooSuite) TestA(c *check.C) {
-}
-
-func (s *FooSuite) TestAAA(c *check.C) {
-}
-
-func (s *BarSuite) TestBar(c *check.C) {
-}
-
-func (x *FooSuite) TestC(c *check.C) {
-}
-
-func (*FooSuite) TestD(c *check.C) {
-}
-
-// should not be counted
-func (s *FooSuite) testE(c *check.C) {
-}
-
-// counted, although we don't support ungofmt file
- func (s *FooSuite) TestF (c *check.C){}
-`)
- expected := []string{
- "FooSuite.TestA$",
- "FooSuite.TestAAA$",
- "BarSuite.TestBar$",
- "FooSuite.TestC$",
- "FooSuite.TestD$",
- "FooSuite.TestF$",
- }
-
- actual, err := enumerateTestsForBytes(b)
- if err != nil {
- t.Fatal(err)
- }
- if !reflect.DeepEqual(expected, actual) {
- t.Fatalf("expected %q, got %q", expected, actual)
- }
-}
diff --git a/hack/integration-cli-on-swarm/host/host.go b/hack/integration-cli-on-swarm/host/host.go
deleted file mode 100644
index c4cb2484a6..0000000000
--- a/hack/integration-cli-on-swarm/host/host.go
+++ /dev/null
@@ -1,198 +0,0 @@
-package main
-
-import (
- "context"
- "flag"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "strings"
- "time"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/filters"
- "github.com/docker/docker/client"
- "github.com/docker/docker/pkg/stdcopy"
- "github.com/sirupsen/logrus"
-)
-
-const (
- defaultStackName = "integration-cli-on-swarm"
- defaultVolumeName = "integration-cli-on-swarm"
- defaultMasterImageName = "integration-cli-master"
- defaultWorkerImageName = "integration-cli-worker"
-)
-
-func main() {
- rc, err := xmain()
- if err != nil {
- logrus.Fatalf("fatal error: %v", err)
- }
- os.Exit(rc)
-}
-
-func xmain() (int, error) {
- // Should we use cobra maybe?
- replicas := flag.Int("replicas", 1, "Number of worker service replica")
- chunks := flag.Int("chunks", 0, "Number of test chunks executed in batch (0 == replicas)")
- pushWorkerImage := flag.String("push-worker-image", "", "Push the worker image to the registry. Required for distributed execution. (empty == not to push)")
- shuffle := flag.Bool("shuffle", false, "Shuffle the input so as to mitigate makespan nonuniformity")
- // flags below are rarely used
- randSeed := flag.Int64("rand-seed", int64(0), "Random seed used for shuffling (0 == current time)")
- filtersFile := flag.String("filters-file", "", "Path to optional file composed of `-check.f` filter strings")
- dryRun := flag.Bool("dry-run", false, "Dry run")
- keepExecutor := flag.Bool("keep-executor", false, "Do not auto-remove executor containers, which is used for running privileged programs on Swarm")
- flag.Parse()
- if *chunks == 0 {
- *chunks = *replicas
- }
- if *randSeed == int64(0) {
- *randSeed = time.Now().UnixNano()
- }
- cli, err := client.NewClientWithOpts(client.FromEnv)
- if err != nil {
- return 1, err
- }
- if hasStack(cli, defaultStackName) {
- logrus.Infof("Removing stack %s", defaultStackName)
- removeStack(cli, defaultStackName)
- }
- if hasVolume(cli, defaultVolumeName) {
- logrus.Infof("Removing volume %s", defaultVolumeName)
- removeVolume(cli, defaultVolumeName)
- }
- if err = ensureImages(cli, []string{defaultWorkerImageName, defaultMasterImageName}); err != nil {
- return 1, err
- }
- workerImageForStack := defaultWorkerImageName
- if *pushWorkerImage != "" {
- logrus.Infof("Pushing %s to %s", defaultWorkerImageName, *pushWorkerImage)
- if err = pushImage(cli, *pushWorkerImage, defaultWorkerImageName); err != nil {
- return 1, err
- }
- workerImageForStack = *pushWorkerImage
- }
- compose, err := createCompose("", cli, composeOptions{
- Replicas: *replicas,
- Chunks: *chunks,
- MasterImage: defaultMasterImageName,
- WorkerImage: workerImageForStack,
- Volume: defaultVolumeName,
- Shuffle: *shuffle,
- RandSeed: *randSeed,
- DryRun: *dryRun,
- KeepExecutor: *keepExecutor,
- })
- if err != nil {
- return 1, err
- }
- filters, err := filtersBytes(*filtersFile)
- if err != nil {
- return 1, err
- }
- logrus.Infof("Creating volume %s with input data", defaultVolumeName)
- if err = createVolumeWithData(cli,
- defaultVolumeName,
- map[string][]byte{"/input": filters},
- defaultMasterImageName); err != nil {
- return 1, err
- }
- logrus.Infof("Deploying stack %s from %s", defaultStackName, compose)
- defer func() {
- logrus.Infof("NOTE: You may want to inspect or clean up following resources:")
- logrus.Infof(" - Stack: %s", defaultStackName)
- logrus.Infof(" - Volume: %s", defaultVolumeName)
- logrus.Infof(" - Compose file: %s", compose)
- logrus.Infof(" - Master image: %s", defaultMasterImageName)
- logrus.Infof(" - Worker image: %s", workerImageForStack)
- }()
- if err = deployStack(cli, defaultStackName, compose); err != nil {
- return 1, err
- }
- logrus.Infof("The log will be displayed here after some duration."+
- "You can watch the live status via `docker service logs %s_worker`",
- defaultStackName)
- masterContainerID, err := waitForMasterUp(cli, defaultStackName)
- if err != nil {
- return 1, err
- }
- rc, err := waitForContainerCompletion(cli, os.Stdout, os.Stderr, masterContainerID)
- if err != nil {
- return 1, err
- }
- logrus.Infof("Exit status: %d", rc)
- return int(rc), nil
-}
-
-func ensureImages(cli *client.Client, images []string) error {
- for _, image := range images {
- _, _, err := cli.ImageInspectWithRaw(context.Background(), image)
- if err != nil {
- return fmt.Errorf("could not find image %s, please run `make build-integration-cli-on-swarm`: %v",
- image, err)
- }
- }
- return nil
-}
-
-func filtersBytes(optionalFiltersFile string) ([]byte, error) {
- var b []byte
- if optionalFiltersFile == "" {
- tests, err := enumerateTests(".")
- if err != nil {
- return b, err
- }
- b = []byte(strings.Join(tests, "\n") + "\n")
- } else {
- var err error
- b, err = ioutil.ReadFile(optionalFiltersFile)
- if err != nil {
- return b, err
- }
- }
- return b, nil
-}
-
-func waitForMasterUp(cli *client.Client, stackName string) (string, error) {
- // FIXME(AkihiroSuda): it should retry until master is up, rather than pre-sleeping
- time.Sleep(10 * time.Second)
-
- fil := filters.NewArgs()
- fil.Add("label", "com.docker.stack.namespace="+stackName)
- // FIXME(AkihiroSuda): we should not rely on internal service naming convention
- fil.Add("label", "com.docker.swarm.service.name="+stackName+"_master")
- masters, err := cli.ContainerList(context.Background(), types.ContainerListOptions{
- All: true,
- Filters: fil,
- })
- if err != nil {
- return "", err
- }
- if len(masters) == 0 {
- return "", fmt.Errorf("master not running in stack %s?", stackName)
- }
- return masters[0].ID, nil
-}
-
-func waitForContainerCompletion(cli *client.Client, stdout, stderr io.Writer, containerID string) (int64, error) {
- stream, err := cli.ContainerLogs(context.Background(),
- containerID,
- types.ContainerLogsOptions{
- ShowStdout: true,
- ShowStderr: true,
- Follow: true,
- })
- if err != nil {
- return 1, err
- }
- stdcopy.StdCopy(stdout, stderr, stream)
- stream.Close()
- resultC, errC := cli.ContainerWait(context.Background(), containerID, "")
- select {
- case err := <-errC:
- return 1, err
- case result := <-resultC:
- return result.StatusCode, nil
- }
-}
diff --git a/hack/integration-cli-on-swarm/host/volume.go b/hack/integration-cli-on-swarm/host/volume.go
deleted file mode 100644
index a6ddc6fae7..0000000000
--- a/hack/integration-cli-on-swarm/host/volume.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package main
-
-import (
- "archive/tar"
- "bytes"
- "context"
- "io"
-
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/api/types/container"
- "github.com/docker/docker/api/types/mount"
- "github.com/docker/docker/api/types/volume"
- "github.com/docker/docker/client"
-)
-
-func createTar(data map[string][]byte) (io.Reader, error) {
- var b bytes.Buffer
- tw := tar.NewWriter(&b)
- for path, datum := range data {
- hdr := tar.Header{
- Name: path,
- Mode: 0644,
- Size: int64(len(datum)),
- }
- if err := tw.WriteHeader(&hdr); err != nil {
- return nil, err
- }
- _, err := tw.Write(datum)
- if err != nil {
- return nil, err
- }
- }
- if err := tw.Close(); err != nil {
- return nil, err
- }
- return &b, nil
-}
-
-// createVolumeWithData creates a volume with the given data (e.g. data["/foo"] = []byte("bar"))
-// Internally, a container is created from the image so as to provision the data to the volume,
-// which is attached to the container.
-func createVolumeWithData(cli *client.Client, volumeName string, data map[string][]byte, image string) error {
- _, err := cli.VolumeCreate(context.Background(),
- volume.VolumeCreateBody{
- Driver: "local",
- Name: volumeName,
- })
- if err != nil {
- return err
- }
- mnt := "/mnt"
- miniContainer, err := cli.ContainerCreate(context.Background(),
- &container.Config{
- Image: image,
- },
- &container.HostConfig{
- Mounts: []mount.Mount{
- {
- Type: mount.TypeVolume,
- Source: volumeName,
- Target: mnt,
- },
- },
- }, nil, "")
- if err != nil {
- return err
- }
- tr, err := createTar(data)
- if err != nil {
- return err
- }
- if cli.CopyToContainer(context.Background(),
- miniContainer.ID, mnt, tr, types.CopyToContainerOptions{}); err != nil {
- return err
- }
- return cli.ContainerRemove(context.Background(),
- miniContainer.ID,
- types.ContainerRemoveOptions{})
-}
-
-func hasVolume(cli *client.Client, volumeName string) bool {
- _, err := cli.VolumeInspect(context.Background(), volumeName)
- return err == nil
-}
-
-func removeVolume(cli *client.Client, volumeName string) error {
- return cli.VolumeRemove(context.Background(), volumeName, true)
-}
diff --git a/hack/make.ps1 b/hack/make.ps1
index be60c0816c..6ff7a7fbe6 100644
--- a/hack/make.ps1
+++ b/hack/make.ps1
@@ -327,19 +327,16 @@ Function Run-UnitTests() {
# Run the integration tests
Function Run-IntegrationTests() {
$env:DOCKER_INTEGRATION_DAEMON_DEST = $root + "\bundles\tmp"
- $dirs = Get-ChildItem -Path integration -Directory -Recurse
+ $dirs = go list -test -f '{{- if ne .ForTest `"`" -}}{{- .Dir -}}{{- end -}}' .\integration\...
$integration_api_dirs = @()
ForEach($dir in $dirs) {
- $RelativePath = "." + $dir.FullName -replace "$($PWD.Path -replace "\\","\\")",""
- If ($RelativePath -notmatch '(^.\\integration($|\\internal)|\\testdata)') {
- $integration_api_dirs += $dir
- Write-Host "Building test suite binary $RelativePath"
- go test -c -o "$RelativePath\test.exe" $RelativePath
- }
+ $integration_api_dirs += $dir
+ Write-Host "Building test suite binary $dir"
+ go test -c -o "$dir\test.exe" $dir
}
ForEach($dir in $integration_api_dirs) {
- Set-Location $dir.FullName
+ Set-Location $dir
Write-Host "Running $($PWD.Path)"
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "$($PWD.Path)\test.exe"
diff --git a/hack/make.sh b/hack/make.sh
index 62c72a09e2..58efc74ee5 100755
--- a/hack/make.sh
+++ b/hack/make.sh
@@ -148,16 +148,7 @@ EXTLDFLAGS_STATIC='-static'
ORIG_BUILDFLAGS=( -tags "autogen netgo osusergo static_build $DOCKER_BUILDTAGS" -installsuffix netgo )
# see https://github.com/golang/go/issues/9369#issuecomment-69864440 for why -installsuffix is necessary here
-BUILDFLAGS=( $BUILDFLAGS "${ORIG_BUILDFLAGS[@]}" )
-
-# Test timeout.
-if [ "${DOCKER_ENGINE_GOARCH}" == "arm64" ] || [ "${DOCKER_ENGINE_GOARCH}" == "arm" ]; then
- : ${TIMEOUT:=10m}
-elif [ "${DOCKER_ENGINE_GOARCH}" == "windows" ]; then
- : ${TIMEOUT:=8m}
-else
- : ${TIMEOUT:=5m}
-fi
+BUILDFLAGS=( ${BUILDFLAGS} "${ORIG_BUILDFLAGS[@]}" )
LDFLAGS_STATIC_DOCKER="
$LDFLAGS_STATIC
diff --git a/hack/make/.binary b/hack/make/.binary
index 010c2c11da..ff33e18cab 100644
--- a/hack/make/.binary
+++ b/hack/make/.binary
@@ -68,7 +68,7 @@ go build \
$LDFLAGS_STATIC_DOCKER
$DOCKER_LDFLAGS
" \
- $GO_PACKAGE
+ ${GO_PACKAGE}
)
echo "Created binary: $DEST/$BINARY_FULLNAME"
diff --git a/hack/make/.go-autogen b/hack/make/.go-autogen
index ea8a32ff5d..0afd559200 100644
--- a/hack/make/.go-autogen
+++ b/hack/make/.go-autogen
@@ -67,7 +67,7 @@ if [ "$(go env GOOS)" = "windows" ]; then
[ ! -z $GITCOMMIT ] && defs="$defs -D DOCKER_COMMIT=\"$GITCOMMIT\""
function makeres {
- $WINDRES \
+ ${WINDRES} \
-i hack/make/.resources-windows/$1 \
-o $3 \
-F $2 \
@@ -76,7 +76,7 @@ if [ "$(go env GOOS)" = "windows" ]; then
$defs
}
- $WINDMC \
+ ${WINDMC} \
hack/make/.resources-windows/event_messages.mc \
-h autogen/winresources/tmp \
-r autogen/winresources/tmp
diff --git a/hack/make/.integration-daemon-start b/hack/make/.integration-daemon-start
index dabcfbe262..34a2c872a6 100644
--- a/hack/make/.integration-daemon-start
+++ b/hack/make/.integration-daemon-start
@@ -20,7 +20,7 @@ fi
# This is a temporary hack for split-binary mode. It can be removed once
# https://github.com/docker/docker/pull/22134 is merged into docker master
if [ "$(go env GOOS)" = 'windows' ]; then
- return
+ return
fi
if [ -z "$DOCKER_TEST_HOST" ]; then
@@ -86,8 +86,8 @@ if [ -z "$DOCKER_TEST_HOST" ]; then
--storage-driver "$DOCKER_GRAPHDRIVER" \
--pidfile "$DEST/docker.pid" \
--userland-proxy="$DOCKER_USERLANDPROXY" \
- $storage_params \
- $extra_params \
+ ${storage_params} \
+ ${extra_params} \
&> "$DEST/docker.log"
) &
else
@@ -97,7 +97,7 @@ fi
# give it a little time to come up so it's "ready"
tries=60
echo "INFO: Waiting for daemon to start..."
-while ! $TEST_CLIENT_BINARY version &> /dev/null; do
+while ! ${TEST_CLIENT_BINARY} version &> /dev/null; do
(( tries-- ))
if [ $tries -le 0 ]; then
printf "\n"
@@ -106,7 +106,7 @@ while ! $TEST_CLIENT_BINARY version &> /dev/null; do
echo >&2 " check $DEST/docker.log for details"
else
echo >&2 "error: daemon at $DOCKER_HOST fails to '$TEST_CLIENT_BINARY version':"
- $TEST_CLIENT_BINARY version >&2 || true
+ ${TEST_CLIENT_BINARY} version >&2 || true
# Additional Windows CI debugging as this is a common error as of
# January 2016
if [ "$(go env GOOS)" = 'windows' ]; then
diff --git a/hack/make/.integration-daemon-stop b/hack/make/.integration-daemon-stop
index c1d43e1a5e..63f7f361b4 100644
--- a/hack/make/.integration-daemon-stop
+++ b/hack/make/.integration-daemon-stop
@@ -10,6 +10,8 @@ if [ ! "$(go env GOOS)" = 'windows' ]; then
if ! wait "$pid"; then
echo >&2 "warning: PID $pid from $pidFile had a nonzero exit code"
fi
+ root=$(dirname "$pidFile")/root
+ umount "$root" || true
done
if [ -z "$DOCKER_TEST_HOST" ]; then
diff --git a/hack/make/.integration-test-helpers b/hack/make/.integration-test-helpers
index 149b653800..abe69474ae 100644
--- a/hack/make/.integration-test-helpers
+++ b/hack/make/.integration-test-helpers
@@ -5,7 +5,19 @@
#
# TESTFLAGS='-check.f DockerSuite.TestBuild*' ./hack/make.sh binary test-integration
#
-if [ -z $MAKEDIR ]; then
+
+if [[ "${TESTFLAGS}" = *-check.f* ]]; then
+ echo Skipping integration tests since TESTFLAGS includes integration-cli only flags
+ TEST_SKIP_INTEGRATION=1
+fi
+
+if [[ "${TESTFLAGS}" = *-test.run* ]]; then
+ echo Skipping integration-cli tests since TESTFLAGS includes integration only flags
+ TEST_SKIP_INTEGRATION_CLI=1
+fi
+
+
+if [ -z ${MAKEDIR} ]; then
export MAKEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
fi
source "$MAKEDIR/.go-autogen"
@@ -15,31 +27,34 @@ source "$MAKEDIR/.go-autogen"
: ${TESTFLAGS:=}
: ${TESTDEBUG:=}
-integration_api_dirs=${TEST_INTEGRATION_DIR:-"$(
- find ./integration -type d |
- grep -vE '(^./integration($|/internal)|/testdata)')"}
+integration_api_dirs=${TEST_INTEGRATION_DIR:-"$(go list -test -f '{{- if ne .ForTest "" -}}{{- .Dir -}}{{- end -}}' ./integration/...)"}
run_test_integration() {
- [[ "$TESTFLAGS" != *-check.f* ]] && run_test_integration_suites
- run_test_integration_legacy_suites
+ set_platform_timeout
+ if [ -z "${TEST_SKIP_INTEGRATION}" ]; then
+ run_test_integration_suites
+ fi
+ if [ -z "${TEST_SKIP_INTEGRATION_CLI}" ]; then
+ run_test_integration_legacy_suites
+ fi
}
run_test_integration_suites() {
- local flags="-test.v -test.timeout=${TIMEOUT} $TESTFLAGS"
- for dir in $integration_api_dirs; do
+ local flags="-test.v -test.timeout=${TIMEOUT} $TESTFLAGS ${TESTFLAGS_INTEGRATION}"
+ for dir in ${integration_api_dirs}; do
if ! (
- cd $dir
- echo "Running $PWD"
- test_env ./test.main $flags
+ cd "$dir"
+ echo "Running $PWD flags=${flags}"
+ test_env ./test.main ${flags}
); then exit 1; fi
done
}
run_test_integration_legacy_suites() {
(
- flags="-check.v -check.timeout=${TIMEOUT} -test.timeout=360m $TESTFLAGS"
+ flags="-check.v -check.timeout=${TIMEOUT} -test.timeout=360m $TESTFLAGS ${TESTFLAGS_INTEGRATION_CLI}"
cd integration-cli
- echo "Running $PWD"
+ echo "Running $PWD flags=${flags}"
test_env ./test.main $flags
)
}
@@ -49,10 +64,14 @@ build_test_suite_binaries() {
echo "Skipping building test binaries; as DOCKER_INTEGRATION_TESTS_VERIFIED is set"
return
fi
- build_test_suite_binary ./integration-cli "test.main"
- for dir in $integration_api_dirs; do
- build_test_suite_binary "$dir" "test.main"
- done
+ if [ -z "${TEST_SKIP_INTEGRATION_CLI}" ]; then
+ build_test_suite_binary ./integration-cli "test.main"
+ fi
+ if [ -z "${TEST_SKIP_INTEGRATION}" ]; then
+ for dir in ${integration_api_dirs}; do
+ build_test_suite_binary "$dir" "test.main"
+ done
+ fi
}
# Build a binary for a test suite package
@@ -70,7 +89,7 @@ cleanup_test_suite_binaries() {
}
repeat() {
- for i in $(seq 1 $TEST_REPEAT); do
+ for i in $(seq 1 ${TEST_REPEAT}); do
echo "Running integration-test (iteration $i)"
$@
done
@@ -104,10 +123,9 @@ test_env() {
"$@"
)
}
-
error_on_leaked_containerd_shims() {
- if [ "$(go env GOOS)" == 'windows' ]; then
+ if [ "$(go env GOOS)" = 'windows' ]; then
return
fi
@@ -115,8 +133,28 @@ error_on_leaked_containerd_shims() {
awk '$2 == "containerd-shim" && $4 ~ /.*\/bundles\/.*\/test-integration/ { print $1 }')
if [ -n "$leftovers" ]; then
ps aux
- kill -9 $leftovers 2> /dev/null
+ kill -9 ${leftovers} 2> /dev/null
echo "!!!! WARNING you have left over shim(s), Cleanup your test !!!!"
exit 1
fi
}
+
+set_platform_timeout() {
+ # Test timeout.
+ if [ "${DOCKER_ENGINE_GOARCH}" = "arm64" ] || [ "${DOCKER_ENGINE_GOARCH}" = "arm" ]; then
+ : ${TIMEOUT:=10m}
+ elif [ "${DOCKER_ENGINE_GOARCH}" = "windows" ]; then
+ : ${TIMEOUT:=8m}
+ else
+ : ${TIMEOUT:=5m}
+ fi
+
+ if [ "${TEST_REPEAT}" -gt 1 ]; then
+ # TIMEOUT needs to take TEST_REPEAT into account, or a premature time out may happen.
+ # The following ugliness will:
+ # - remove last character (usually 'm' from '10m')
+ # - multiply by testcount
+ # - add last character back
+ TIMEOUT=$((${TIMEOUT::-1} * ${TEST_REPEAT}))${TIMEOUT:$((${#TIMEOUT}-1)):1}
+ fi
+}
diff --git a/hack/make/build-integration-test-binary b/hack/make/build-integration-test-binary
index bbd5a22bcc..698717f0f5 100755
--- a/hack/make/build-integration-test-binary
+++ b/hack/make/build-integration-test-binary
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# required by `make build-integration-cli-on-swarm`
+# required by https://github.com/AkihiroSuda/kube-moby-integration
set -e
source hack/make/.integration-test-helpers
diff --git a/hack/make/cross b/hack/make/cross
index 497f02ae4b..47cb667af2 100644
--- a/hack/make/cross
+++ b/hack/make/cross
@@ -2,28 +2,28 @@
set -e
# if we have our linux/amd64 version compiled, let's symlink it in
-if [ -x "$DEST/../binary-daemon/dockerd-$VERSION" ]; then
+if [ -x "${DEST}/../binary-daemon/dockerd-${VERSION}" ]; then
arch=$(go env GOHOSTARCH)
mkdir -p "$DEST/linux/${arch}"
(
- cd "$DEST/linux/${arch}"
+ cd "${DEST}/linux/${arch}"
ln -sf ../../../binary-daemon/* ./
)
- echo "Created symlinks:" "$DEST/linux/${arch}/"*
+ echo "Created symlinks:" "${DEST}/linux/${arch}/"*
fi
DOCKER_CROSSPLATFORMS=${DOCKER_CROSSPLATFORMS:-"linux/amd64 windows/amd64"}
-for platform in $DOCKER_CROSSPLATFORMS; do
+for platform in ${DOCKER_CROSSPLATFORMS}; do
(
export KEEPDEST=1
- export DEST="$DEST/$platform" # bundles/VERSION/cross/GOOS/GOARCH/docker-VERSION
+ export DEST="${DEST}/${platform}" # bundles/VERSION/cross/GOOS/GOARCH/docker-VERSION
export GOOS=${platform%/*}
export GOARCH=${platform##*/}
- echo "Cross building: $DEST"
- mkdir -p "$DEST"
- ABS_DEST="$(cd "$DEST" && pwd -P)"
+ echo "Cross building: ${DEST}"
+ mkdir -p "${DEST}"
+ ABS_DEST="$(cd "${DEST}" && pwd -P)"
source "${MAKEDIR}/binary-daemon"
source "${MAKEDIR}/cross-platform-dependent"
diff --git a/hack/make/cross-platform-dependent b/hack/make/cross-platform-dependent
index 52632c3036..21824ed7c9 100644
--- a/hack/make/cross-platform-dependent
+++ b/hack/make/cross-platform-dependent
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -e
-if [ $platform == "windows/amd64" ]; then
+if [ ${platform} == "windows/amd64" ]; then
source "${MAKEDIR}/containerutility"
fi
diff --git a/hack/make/dynbinary b/hack/make/dynbinary
index 981e505e9f..2424046e98 100644
--- a/hack/make/dynbinary
+++ b/hack/make/dynbinary
@@ -3,8 +3,7 @@ set -e
# This script exists as backwards compatibility for CI
(
-
- DEST="${DEST}-daemon"
- ABS_DEST="${ABS_DEST}-daemon"
- . hack/make/dynbinary-daemon
+ DEST="${DEST}-daemon"
+ ABS_DEST="${ABS_DEST}-daemon"
+ . hack/make/dynbinary-daemon
)
diff --git a/hack/make/run b/hack/make/run
index 3254280260..eff7dd95aa 100644
--- a/hack/make/run
+++ b/hack/make/run
@@ -35,10 +35,10 @@ fi
args="--debug \
--host tcp://0.0.0.0:${listen_port} --host unix:///var/run/docker.sock \
- --storage-driver "$DOCKER_GRAPHDRIVER" \
- --userland-proxy="$DOCKER_USERLANDPROXY" \
+ --storage-driver "${DOCKER_GRAPHDRIVER}" \
+ --userland-proxy="${DOCKER_USERLANDPROXY}" \
$storage_params \
$extra_params"
-echo dockerd $args
-exec dockerd $args
+echo dockerd ${args}
+exec dockerd ${args}
diff --git a/hack/make/test-docker-py b/hack/make/test-docker-py
index b30879e3a0..9625f47e61 100644
--- a/hack/make/test-docker-py
+++ b/hack/make/test-docker-py
@@ -3,18 +3,62 @@ set -e
source hack/make/.integration-test-helpers
-# subshell so that we can export PATH without breaking other things
+# The commit or tag to use for testing
+# TODO docker 17.06 cli client used in CI fails to build using a sha;
+# unable to prepare context: unable to 'git clone' to temporary context directory: error fetching: error: no such remote ref ead0bb9e08c13dd3d1712759491eee06bf5a5602
+#: exit status 128
+: "${DOCKER_PY_COMMIT:=4.0.2}"
+
+# custom options to pass py.test
+# TODO remove these skip once we update to a docker-py version that has https://github.com/docker/docker-py/pull/2369, https://github.com/docker/docker-py/pull/2380, https://github.com/docker/docker-py/pull/2382
+: "${PY_TEST_OPTIONS:=\
+--deselect=tests/integration/api_swarm_test.py::SwarmTest::test_init_swarm_data_path_addr \
+--deselect=tests/integration/api_exec_test.py::ExecTest::test_detach_with_arg \
+--deselect=tests/integration/api_exec_test.py::ExecDemuxTest::test_exec_command_tty_stream_no_demux \
+--deselect=tests/integration/api_build_test.py::BuildTest::test_build_invalid_platform \
+--deselect=tests/integration/api_image_test.py::PullImageTest::test_pull_invalid_platform \
+--junitxml=${DEST}/junit-report.xml \
+}"
(
bundle .integration-daemon-start
- dockerPy='/docker-py'
- [ -d "$dockerPy" ] || {
- dockerPy="$DEST/docker-py"
- git clone https://github.com/docker/docker-py.git "$dockerPy"
- }
+ docker_host_scheme=$(echo "${DOCKER_HOST}" | cut -d: -f1 -)
+
+ case "${docker_host_scheme}" in
+ unix)
+ # trim the tcp:// scheme, and bind-mount the docker socket into the container
+ run_opts="--mount type=bind,src=${DOCKER_HOST#unix://},dst=/var/run/docker.sock"
+ ;;
+
+ tcp)
+ # run container in host-mode networking so that it can connect to the
+ # daemon from the current networking namespace (e.g., to connect to localhost)
+ run_opts="--network=host -e DOCKER_HOST=${DOCKER_HOST}"
+ ;;
+
+ *)
+ echo "WARN: Skipping test-docker-py: connecting to docker daemon using ${docker_host_scheme} (${DOCKER_HOST}) not supported"
+ bundle .integration-daemon-stop
+ return 0
+ esac
- # exporting PYTHONPATH to import "docker" from our local docker-py
- test_env PYTHONPATH="$dockerPy" py.test --junitxml="$DEST/results.xml" "$dockerPy/tests/integration"
+ docker_py_image="docker-sdk-python3:${DOCKER_PY_COMMIT}"
+ if ! docker image inspect "dockerPyImage" &> /dev/null; then
+ echo INFO: Building ${docker_py_image}...
+ (
+ [ -n "${TESTDEBUG}" ] && set -x
+ [ -z "${TESTDEBUG}" ] && build_opts="--quiet"
+ [ -f /.dockerenv ] || build_opts="${build_opts} --network=host"
+ # shellcheck disable=SC2086
+ exec docker build ${build_opts} -t "${docker_py_image}" -f tests/Dockerfile "https://github.com/docker/docker-py.git#${DOCKER_PY_COMMIT}"
+ )
+ fi
+ echo INFO: Starting docker-py tests...
+ (
+ [ -n "${TESTDEBUG}" ] && set -x
+ # shellcheck disable=SC2086,SC2140
+ exec docker run --rm ${run_opts} --mount type=bind,"src=${ABS_DEST}","dst=/src/${DEST}" "${docker_py_image}" pytest ${PY_TEST_OPTIONS} tests/integration
+ )
bundle .integration-daemon-stop
) 2>&1 | tee -a "$DEST/test.log"
diff --git a/hack/make/test-integration b/hack/make/test-integration
index c807cd4978..039afc9526 100755
--- a/hack/make/test-integration
+++ b/hack/make/test-integration
@@ -1,14 +1,26 @@
#!/usr/bin/env bash
set -e -o pipefail
+if [ -n "$TEST_INTEGRATION_DEST" ]; then
+ export DEST="$ABS_DEST/$TEST_INTEGRATION_DEST"
+ export DOCKER_INTEGRATION_DAEMON_DEST="$DEST"
+ mkdir -p "$DEST"
+fi
+
source hack/make/.integration-test-helpers
+if [ ! -z "${TEST_SKIP_INTEGRATION}" ] && [ ! -z "${TEST_SKIP_INTEGRATION_CLI}" ]; then
+ echo integration and integration-cli skipped according to env vars
+ exit 0
+fi
+
(
+ env
build_test_suite_binaries
bundle .integration-daemon-start
bundle .integration-daemon-setup
- local testexit=0
+ testexit=0
( repeat run_test_integration ) || testexit=$?
# Always run cleanup, even if the subshell fails
@@ -16,6 +28,6 @@ source hack/make/.integration-test-helpers
cleanup_test_suite_binaries
error_on_leaked_containerd_shims
- exit $testexit
+ exit ${testexit}
) 2>&1 | tee -a "$DEST/test.log"
diff --git a/hack/make/test-integration-flaky b/hack/make/test-integration-flaky
index 14fb034b75..a613d6ccbc 100644
--- a/hack/make/test-integration-flaky
+++ b/hack/make/test-integration-flaky
@@ -3,13 +3,13 @@ set -e -o pipefail
source hack/validate/.validate
new_tests=$(
- validate_diff --diff-filter=ACMR --unified=0 -- 'integration/*_test.go' |
- grep -E '^(\+func )(.*)(\*testing)' || true
+ validate_diff --diff-filter=ACMR --unified=0 -- 'integration/*_test.go' |
+ grep -E '^(\+func )(.*)(\*testing)' || true
)
if [ -z "$new_tests" ]; then
- echo 'No new tests added to integration.'
- return
+ echo 'No new tests added to integration.'
+ return
fi
echo
@@ -18,20 +18,12 @@ echo "$new_tests"
echo "Running stress test for them."
(
- TESTARRAY=$(echo "$new_tests" | sed 's/+func //' | awk -F'\\(' '{print $1}' | tr '\n' '|')
- # Note: TEST_REPEAT will make the test suite run 5 times, restarting the daemon
- # whereas testcount will make each test run 5 times in a row under the same daemon.
- # This will make a total of 25 runs for each test in TESTARRAY.
- export TEST_REPEAT=5
- local testcount=5
- # However, TIMEOUT needs to take testcount into account, or a premature time out may happen.
- # The following ugliness will:
- # - remove last character (usually 'm' from '10m')
- # - multiply by testcount
- # - add last character back
- export TIMEOUT=$((${TIMEOUT::-1} * $testcount))${TIMEOUT:$((${#TIMEOUT}-1)):1}
-
- export TESTFLAGS="-test.count $testcount -test.run ${TESTARRAY%?}"
- echo "Using test flags: $TESTFLAGS"
- source hack/make/test-integration
+ TESTARRAY=$(echo "$new_tests" | sed 's/+func //' | awk -F'\\(' '{print $1}' | tr '\n' '|')
+ # Note: TEST_REPEAT will make the test suite run 5 times, restarting the daemon
+ # and each test will run 5 times in a row under the same daemon.
+ # This will make a total of 25 runs for each test in TESTARRAY.
+ export TEST_REPEAT=5
+ export TESTFLAGS="-test.count ${TEST_REPEAT} -test.run ${TESTARRAY%?}"
+ echo "Using test flags: $TESTFLAGS"
+ source hack/make/test-integration
)
diff --git a/hack/test/e2e-run.sh b/hack/test/e2e-run.sh
index 122d58f8ef..6463f2f85d 100755
--- a/hack/test/e2e-run.sh
+++ b/hack/test/e2e-run.sh
@@ -2,7 +2,7 @@
set -e -u -o pipefail
ARCH=$(uname -m)
-if [ "$ARCH" == "x86_64" ]; then
+if [ "$ARCH" = "x86_64" ]; then
ARCH="amd64"
fi
@@ -17,8 +17,13 @@ integration_api_dirs=${TEST_INTEGRATION_DIR:-"$(
grep -vE '(^/tests/integration($|/internal)|/testdata)')"}
run_test_integration() {
- [[ "$TESTFLAGS" != *-check.f* ]] && run_test_integration_suites
- run_test_integration_legacy_suites
+ set_platform_timeout
+ if [[ "$TESTFLAGS" != *-check.f* ]]; then
+ run_test_integration_suites
+ fi
+ if [[ "$TESTFLAGS" != *-test.run* ]]; then
+ run_test_integration_legacy_suites
+ fi
}
run_test_integration_suites() {
@@ -68,5 +73,16 @@ test_env() {
)
}
+set_platform_timeout() {
+ # Test timeout.
+ if [ "${DOCKER_ENGINE_GOARCH}" = "arm64" ] || [ "${DOCKER_ENGINE_GOARCH}" = "arm" ]; then
+ : ${TIMEOUT:=10m}
+ elif [ "${DOCKER_ENGINE_GOARCH}" = "windows" ]; then
+ : ${TIMEOUT:=8m}
+ else
+ : ${TIMEOUT:=5m}
+ fi
+}
+
sh /scripts/ensure-emptyfs.sh
run_test_integration
diff --git a/hack/test/unit b/hack/test/unit
index ac27f68c30..1aea06c54b 100755
--- a/hack/test/unit
+++ b/hack/test/unit
@@ -1,34 +1,28 @@
#!/usr/bin/env bash
#
-# Run unit tests
+# Run unit tests and create report
#
# TESTFLAGS - add additional test flags. Ex:
#
-# TESTFLAGS="-v -run TestBuild" hack/test/unit
+# TESTFLAGS='-v -run TestBuild' hack/test/unit
#
# TESTDIRS - run tests for specified packages. Ex:
#
-# TESTDIRS="./pkg/term" hack/test/unit
+# TESTDIRS='./pkg/term' hack/test/unit
#
set -eu -o pipefail
-TESTFLAGS+=" -test.timeout=${TIMEOUT:-5m}"
-BUILDFLAGS=( -tags "netgo seccomp libdm_no_deferred_remove" )
-TESTDIRS="${TESTDIRS:-"./..."}"
-
-exclude_paths="/vendor/|/integration"
+BUILDFLAGS=( -tags 'netgo seccomp libdm_no_deferred_remove' )
+TESTFLAGS+="-test.timeout=${TIMEOUT:-5m}"
+TESTDIRS="${TESTDIRS:-./...}"
+exclude_paths='/vendor/|/integration'
pkg_list=$(go list $TESTDIRS | grep -vE "($exclude_paths)")
-for pkg in $pkg_list; do
- go test "${BUILDFLAGS[@]}" \
- -cover \
- -coverprofile=profile.out \
- -covermode=atomic \
- $TESTFLAGS \
- "${pkg}"
-
- if test -f profile.out; then
- cat profile.out >> coverage.txt
- rm profile.out
- fi
-done
+mkdir -p bundles
+gotestsum --format=standard-quiet --jsonfile=bundles/go-test-report.json --junitfile=bundles/junit-report.xml -- \
+ "${BUILDFLAGS[@]}" \
+ -cover \
+ -coverprofile=bundles/profile.out \
+ -covermode=atomic \
+ ${TESTFLAGS} \
+ ${pkg_list}
diff --git a/hack/validate/all b/hack/validate/all
index 9d95c2d2fd..8e3cbfcd3b 100755
--- a/hack/validate/all
+++ b/hack/validate/all
@@ -4,5 +4,5 @@
export SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-. $SCRIPTDIR/default
-. $SCRIPTDIR/vendor
+. ${SCRIPTDIR}/default
+. ${SCRIPTDIR}/vendor
diff --git a/hack/validate/changelog-date-descending b/hack/validate/changelog-date-descending
index b9c3368ca6..301f9ba0b5 100755
--- a/hack/validate/changelog-date-descending
+++ b/hack/validate/changelog-date-descending
@@ -3,8 +3,8 @@
changelogFile=${1:-CHANGELOG.md}
if [ ! -r "$changelogFile" ]; then
- echo "Unable to read file $changelogFile" >&2
- exit 1
+ echo "Unable to read file $changelogFile" >&2
+ exit 1
fi
grep -e '^## ' "$changelogFile" | awk '{print$3}' | sort -c -r || exit 2
diff --git a/hack/validate/changelog-well-formed b/hack/validate/changelog-well-formed
index 6c7ce1a1c0..ea7ef0ff5d 100755
--- a/hack/validate/changelog-well-formed
+++ b/hack/validate/changelog-well-formed
@@ -3,8 +3,8 @@
changelogFile=${1:-CHANGELOG.md}
if [ ! -r "$changelogFile" ]; then
- echo "Unable to read file $changelogFile" >&2
- exit 1
+ echo "Unable to read file $changelogFile" >&2
+ exit 1
fi
changelogWellFormed=1
@@ -12,14 +12,14 @@ changelogWellFormed=1
# e.g. "## 1.12.3 (2016-10-26)"
VER_LINE_REGEX='^## [0-9]+\.[0-9]+\.[0-9]+(-ce)? \([0-9]+-[0-9]+-[0-9]+\)$'
while read -r line; do
- if ! [[ "$line" =~ $VER_LINE_REGEX ]]; then
- echo "Malformed changelog $changelogFile line \"$line\"" >&2
- changelogWellFormed=0
- fi
+ if ! [[ "$line" =~ $VER_LINE_REGEX ]]; then
+ echo "Malformed changelog $changelogFile line \"$line\"" >&2
+ changelogWellFormed=0
+ fi
done < <(grep '^## ' $changelogFile)
if [[ "$changelogWellFormed" == "1" ]]; then
- echo "Congratulations! Changelog $changelogFile is well-formed."
+ echo "Congratulations! Changelog $changelogFile is well-formed."
else
- exit 2
+ exit 2
fi
diff --git a/hack/validate/dco b/hack/validate/dco
index f391001601..9e1ed80f77 100755
--- a/hack/validate/dco
+++ b/hack/validate/dco
@@ -21,7 +21,7 @@ check_dco() {
grep -qE "$dcoRegex"
}
-if [ $adds -eq 0 -a $dels -eq 0 ]; then
+if [ ${adds} -eq 0 -a ${dels} -eq 0 ]; then
echo '0 adds, 0 deletions; nothing to validate! :)'
else
commits=( $(validate_log --format='format:%H%n') )
diff --git a/hack/validate/default b/hack/validate/default
index 8ec978876d..4ca7e91476 100755
--- a/hack/validate/default
+++ b/hack/validate/default
@@ -4,14 +4,14 @@
export SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-. $SCRIPTDIR/dco
-. $SCRIPTDIR/default-seccomp
-. $SCRIPTDIR/gometalinter
-. $SCRIPTDIR/pkg-imports
-. $SCRIPTDIR/swagger
-. $SCRIPTDIR/swagger-gen
-. $SCRIPTDIR/test-imports
-. $SCRIPTDIR/toml
-. $SCRIPTDIR/changelog-well-formed
-. $SCRIPTDIR/changelog-date-descending
-. $SCRIPTDIR/deprecate-integration-cli
+. ${SCRIPTDIR}/dco
+. ${SCRIPTDIR}/default-seccomp
+. ${SCRIPTDIR}/gometalinter
+. ${SCRIPTDIR}/pkg-imports
+. ${SCRIPTDIR}/swagger
+. ${SCRIPTDIR}/swagger-gen
+. ${SCRIPTDIR}/test-imports
+. ${SCRIPTDIR}/toml
+. ${SCRIPTDIR}/changelog-well-formed
+. ${SCRIPTDIR}/changelog-date-descending
+. ${SCRIPTDIR}/deprecate-integration-cli
diff --git a/hack/validate/deprecate-integration-cli b/hack/validate/deprecate-integration-cli
index da6f8310f4..bc20bf9f75 100755
--- a/hack/validate/deprecate-integration-cli
+++ b/hack/validate/deprecate-integration-cli
@@ -5,13 +5,13 @@ export SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "${SCRIPTDIR}/.validate"
new_tests=$(
- validate_diff --diff-filter=ACMR --unified=0 -- 'integration-cli/*_cli_*.go' |
- grep -E '^\+func (.*) Test' || true
+ validate_diff --diff-filter=ACMR --unified=0 -- 'integration-cli/*_cli_*.go' |
+ grep -E '^\+func (.*) Test' || true
)
if [ -z "$new_tests" ]; then
echo 'Congratulations! No new tests added to integration-cli.'
- exit
+ exit
fi
echo "The following new tests were added to integration-cli:"
diff --git a/hack/validate/gometalinter b/hack/validate/gometalinter
index 8f42597fce..0c0ae0d7ee 100755
--- a/hack/validate/gometalinter
+++ b/hack/validate/gometalinter
@@ -10,4 +10,4 @@ SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
gometalinter \
${GOMETALINTER_OPTS} \
- --config $SCRIPTDIR/gometalinter.json ./...
+ --config ${SCRIPTDIR}/gometalinter.json ./...
diff --git a/hack/validate/swagger b/hack/validate/swagger
index 0b3c2719d8..58c032a716 100755
--- a/hack/validate/swagger
+++ b/hack/validate/swagger
@@ -8,6 +8,6 @@ files=( $(validate_diff --diff-filter=ACMR --name-only -- 'api/swagger.yaml' ||
unset IFS
if [ ${#files[@]} -gt 0 ]; then
- yamllint -c ${SCRIPTDIR}/.swagger-yamllint api/swagger.yaml
- swagger validate api/swagger.yaml
+ LANG=C.UTF-8 yamllint -c ${SCRIPTDIR}/.swagger-yamllint api/swagger.yaml
+ swagger validate api/swagger.yaml
fi
diff --git a/hack/validate/swagger-gen b/hack/validate/swagger-gen
index 07c22b5a62..744f627eb4 100755
--- a/hack/validate/swagger-gen
+++ b/hack/validate/swagger-gen
@@ -25,5 +25,5 @@ if [ ${#files[@]} -gt 0 ]; then
echo 'Congratulations! All api changes are done the right way.'
fi
else
- echo 'No api/types/ or api/swagger.yaml changes in diff.'
+ echo 'No api/types/ or api/swagger.yaml changes in diff.'
fi
diff --git a/integration/plugin/logging/cmd/close_on_start/main_test.go b/integration/plugin/logging/cmd/close_on_start/main_test.go
deleted file mode 100644
index 06ab7d0f9a..0000000000
--- a/integration/plugin/logging/cmd/close_on_start/main_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package main
diff --git a/integration/plugin/logging/cmd/cmd_test.go b/integration/plugin/logging/cmd/cmd_test.go
deleted file mode 100644
index 1d619dd05e..0000000000
--- a/integration/plugin/logging/cmd/cmd_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package cmd
diff --git a/integration/plugin/logging/cmd/dummy/main_test.go b/integration/plugin/logging/cmd/dummy/main_test.go
deleted file mode 100644
index 06ab7d0f9a..0000000000
--- a/integration/plugin/logging/cmd/dummy/main_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package main
diff --git a/integration/plugin/volumes/cmd/cmd_test.go b/integration/plugin/volumes/cmd/cmd_test.go
deleted file mode 100644
index 1d619dd05e..0000000000
--- a/integration/plugin/volumes/cmd/cmd_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package cmd
diff --git a/integration/plugin/volumes/cmd/dummy/main_test.go b/integration/plugin/volumes/cmd/dummy/main_test.go
deleted file mode 100644
index 06ab7d0f9a..0000000000
--- a/integration/plugin/volumes/cmd/dummy/main_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package main
diff --git a/internal/test/daemon/daemon.go b/internal/test/daemon/daemon.go
index 61fbdb4e74..b81da18f3f 100644
--- a/internal/test/daemon/daemon.go
+++ b/internal/test/daemon/daemon.go
@@ -33,6 +33,13 @@ type testingT interface {
Fatalf(string, ...interface{})
}
+type namer interface {
+ Name() string
+}
+type testNamer interface {
+ TestName() string
+}
+
type logT interface {
Logf(string, ...interface{})
}
@@ -91,6 +98,13 @@ func New(t testingT, ops ...func(*Daemon)) *Daemon {
if dest == "" {
dest = os.Getenv("DEST")
}
+ switch v := t.(type) {
+ case namer:
+ dest = filepath.Join(dest, v.Name())
+ case testNamer:
+ dest = filepath.Join(dest, v.TestName())
+ }
+ t.Logf("Creating a new daemon at: %s", dest)
assert.Check(t, dest != "", "Please set the DOCKER_INTEGRATION_DAEMON_DEST or the DEST environment variable")
storageDriver := os.Getenv("DOCKER_GRAPHDRIVER")
@@ -607,7 +621,9 @@ func (d *Daemon) getClientConfig() (*clientConfig, error) {
return nil, err
}
transport.DisableKeepAlives = true
-
+ if proto == "unix" {
+ addr = filepath.Base(addr)
+ }
return &clientConfig{
transport: transport,
scheme: scheme,