github.com/ph/moby@v1.13.1/hack/Jenkins/W2L/setup.sh (about) 1 # Jenkins CI script for Windows to Linux CI. 2 # Heavily modified by John Howard (@jhowardmsft) December 2015 to try to make it more reliable. 3 set +xe 4 SCRIPT_VER="Wed Apr 20 18:30:19 UTC 2016" 5 6 # TODO to make (even) more resilient: 7 # - Wait for daemon to be running before executing docker commands 8 # - Check if jq is installed 9 # - Make sure bash is v4.3 or later. Can't do until all Azure nodes on the latest version 10 # - Make sure we are not running as local system. Can't do until all Azure nodes are updated. 11 # - Error if docker versions are not equal. Can't do until all Azure nodes are updated 12 # - Error if go versions are not equal. Can't do until all Azure nodes are updated. 13 # - Error if running 32-bit posix tools. Probably can take from bash --version and check contains "x86_64" 14 # - Warn if the CI directory cannot be deleted afterwards. Otherwise turdlets are left behind 15 # - Use %systemdrive% ($SYSTEMDRIVE) rather than hard code to c: for TEMP 16 # - Consider cross builing the Windows binary and copy across. That's a bit of a heavy lift. Only reason 17 # for doing that is that it mirrors the actual release process for docker.exe which is cross-built. 18 # However, should absolutely not be a problem if built natively, so nit-picking. 19 # - Tidy up of images and containers. Either here, or in the teardown script. 20 21 ec=0 22 uniques=1 23 echo INFO: Started at `date`. Script version $SCRIPT_VER 24 25 26 # !README! 27 # There are two daemons running on the remote Linux host: 28 # - outer: specified by DOCKER_HOST, this is the daemon that will build and run the inner docker daemon 29 # from the sources matching the PR. 30 # - inner: runs on the host network, on a port number similar to that of DOCKER_HOST but the last two digits are inverted 31 # (2357 if DOCKER_HOST had port 2375; and 2367 if DOCKER_HOST had port 2376). 32 # The windows integration tests are run against this inner daemon. 33 34 # get the ip, inner and outer ports. 35 ip="${DOCKER_HOST#*://}" 36 port_outer="${ip#*:}" 37 # inner port is like outer port with last two digits inverted. 38 port_inner=$(echo "$port_outer" | sed -E 's/(.)(.)$/\2\1/') 39 ip="${ip%%:*}" 40 41 echo "INFO: IP=$ip PORT_OUTER=$port_outer PORT_INNER=$port_inner" 42 43 # If TLS is enabled 44 if [ -n "$DOCKER_TLS_VERIFY" ]; then 45 protocol=https 46 if [ -z "$DOCKER_MACHINE_NAME" ]; then 47 ec=1 48 echo "ERROR: DOCKER_MACHINE_NAME is undefined" 49 fi 50 certs=$(echo ~/.docker/machine/machines/$DOCKER_MACHINE_NAME) 51 curlopts="--cacert $certs/ca.pem --cert $certs/cert.pem --key $certs/key.pem" 52 run_extra_args="-v tlscerts:/etc/docker" 53 daemon_extra_args="--tlsverify --tlscacert /etc/docker/ca.pem --tlscert /etc/docker/server.pem --tlskey /etc/docker/server-key.pem" 54 else 55 protocol=http 56 fi 57 58 # Save for use by make.sh and scripts it invokes 59 export MAIN_DOCKER_HOST="tcp://$ip:$port_inner" 60 61 # Verify we can get the remote node to respond to _ping 62 if [ $ec -eq 0 ]; then 63 reply=`curl -s $curlopts $protocol://$ip:$port_outer/_ping` 64 if [ "$reply" != "OK" ]; then 65 ec=1 66 echo "ERROR: Failed to get an 'OK' response from the docker daemon on the Linux node" 67 echo " at $ip:$port_outer when called with an http request for '_ping'. This implies that" 68 echo " either the daemon has crashed/is not running, or the Linux node is unavailable." 69 echo 70 echo " A regular ping to the remote Linux node is below. It should reply. If not, the" 71 echo " machine cannot be reached at all and may have crashed. If it does reply, it is" 72 echo " likely a case of the Linux daemon not running or having crashed, which requires" 73 echo " further investigation." 74 echo 75 echo " Try re-running this CI job, or ask on #docker-dev or #docker-maintainers" 76 echo " for someone to perform further diagnostics, or take this node out of rotation." 77 echo 78 ping $ip 79 else 80 echo "INFO: The Linux nodes outer daemon replied to a ping. Good!" 81 fi 82 fi 83 84 # Get the version from the remote node. Note this may fail if jq is not installed. 85 # That's probably worth checking to make sure, just in case. 86 if [ $ec -eq 0 ]; then 87 remoteVersion=`curl -s $curlopts $protocol://$ip:$port_outer/version | jq -c '.Version'` 88 echo "INFO: Remote daemon is running docker version $remoteVersion" 89 fi 90 91 # Compare versions. We should really fail if result is no 1. Output at end of script. 92 if [ $ec -eq 0 ]; then 93 uniques=`docker version | grep Version | /usr/bin/sort -u | wc -l` 94 fi 95 96 # Make sure we are in repo 97 if [ $ec -eq 0 ]; then 98 if [ ! -d hack ]; then 99 echo "ERROR: Are you sure this is being launched from a the root of docker repository?" 100 echo " If this is a Windows CI machine, it should be c:\jenkins\gopath\src\github.com\docker\docker." 101 echo " Current directory is `pwd`" 102 ec=1 103 fi 104 fi 105 106 # Are we in split binary mode? 107 if [ `grep DOCKER_CLIENTONLY Makefile | wc -l` -gt 0 ]; then 108 splitBinary=0 109 echo "INFO: Running in single binary mode" 110 else 111 splitBinary=1 112 echo "INFO: Running in split binary mode" 113 fi 114 115 116 # Get the commit has and verify we have something 117 if [ $ec -eq 0 ]; then 118 export COMMITHASH=$(git rev-parse --short HEAD) 119 echo INFO: Commmit hash is $COMMITHASH 120 if [ -z $COMMITHASH ]; then 121 echo "ERROR: Failed to get commit hash. Are you sure this is a docker repository?" 122 ec=1 123 fi 124 fi 125 126 # Redirect to a temporary location. Check is here for local runs from Jenkins machines just in case not 127 # in the right directory where the repo is cloned. We also redirect TEMP to not use the environment 128 # TEMP as when running as a standard user (not local system), it otherwise exposes a bug in posix tar which 129 # will cause CI to fail from Windows to Linux. Obviously it's not best practice to ever run as local system... 130 if [ $ec -eq 0 ]; then 131 export TEMP=/c/CI/CI-$COMMITHASH 132 export TMP=$TEMP 133 /usr/bin/mkdir -p $TEMP # Make sure Linux mkdir for -p 134 fi 135 136 # Tidy up time 137 if [ $ec -eq 0 ]; then 138 echo INFO: Deleting pre-existing containers and images... 139 140 # Force remove all containers based on a previously built image with this commit 141 ! docker rm -f $(docker ps -aq --filter "ancestor=docker:$COMMITHASH") &>/dev/null 142 143 # Force remove any container with this commithash as a name 144 ! docker rm -f $(docker ps -aq --filter "name=docker-$COMMITHASH") &>/dev/null 145 146 # This SHOULD never happen, but just in case, also blow away any containers 147 # that might be around. 148 ! if [ ! $(docker ps -aq | wc -l) -eq 0 ]; then 149 echo WARN: There were some leftover containers. Cleaning them up. 150 ! docker rm -f $(docker ps -aq) 151 fi 152 153 # Force remove the image if it exists 154 ! docker rmi -f "docker-$COMMITHASH" &>/dev/null 155 fi 156 157 # Provide the docker version for debugging purposes. If these fail, game over. 158 # as the Linux box isn't responding for some reason. 159 if [ $ec -eq 0 ]; then 160 echo INFO: Docker version and info of the outer daemon on the Linux node 161 echo 162 docker version 163 ec=$? 164 if [ 0 -ne $ec ]; then 165 echo "ERROR: The main linux daemon does not appear to be running. Has the Linux node crashed?" 166 fi 167 echo 168 fi 169 170 # Same as above, but docker info 171 if [ $ec -eq 0 ]; then 172 echo 173 docker info 174 ec=$? 175 if [ 0 -ne $ec ]; then 176 echo "ERROR: The main linux daemon does not appear to be running. Has the Linux node crashed?" 177 fi 178 echo 179 fi 180 181 # build the daemon image 182 if [ $ec -eq 0 ]; then 183 echo "INFO: Running docker build on Linux host at $DOCKER_HOST" 184 if [ $splitBinary -eq 0 ]; then 185 set -x 186 docker build --rm --force-rm --build-arg APT_MIRROR=cdn-fastly.deb.debian.org -t "docker:$COMMITHASH" . 187 cat <<EOF | docker build --rm --force-rm -t "docker:$COMMITHASH" - 188 FROM docker:$COMMITHASH 189 RUN hack/make.sh binary 190 RUN cp bundles/latest/binary/docker /bin/docker 191 CMD docker daemon -D -H tcp://0.0.0.0:$port_inner $daemon_extra_args 192 EOF 193 else 194 set -x 195 docker build --rm --force-rm --build-arg APT_MIRROR=cdn-fastly.deb.debian.org -t "docker:$COMMITHASH" . 196 cat <<EOF | docker build --rm --force-rm -t "docker:$COMMITHASH" - 197 FROM docker:$COMMITHASH 198 RUN hack/make.sh binary 199 RUN cp bundles/latest/binary-daemon/dockerd /bin/dockerd 200 CMD dockerd -D -H tcp://0.0.0.0:$port_inner $daemon_extra_args 201 EOF 202 203 fi 204 ec=$? 205 set +x 206 if [ 0 -ne $ec ]; then 207 echo "ERROR: docker build failed" 208 fi 209 fi 210 211 # Start the docker-in-docker daemon from the image we just built 212 if [ $ec -eq 0 ]; then 213 echo "INFO: Starting build of a Linux daemon to test against, and starting it..." 214 set -x 215 # aufs in aufs is faster than vfs in aufs 216 docker run -d $run_extra_args -e DOCKER_GRAPHDRIVER=aufs --pid host --privileged --name "docker-$COMMITHASH" --net host "docker:$COMMITHASH" 217 ec=$? 218 set +x 219 if [ 0 -ne $ec ]; then 220 echo "ERROR: Failed to compile and start the linux daemon" 221 fi 222 fi 223 224 # Build locally. 225 if [ $ec -eq 0 ]; then 226 echo "INFO: Starting local build of Windows binary..." 227 set -x 228 export TIMEOUT="120m" 229 export DOCKER_HOST="tcp://$ip:$port_inner" 230 # This can be removed 231 export DOCKER_TEST_HOST="tcp://$ip:$port_inner" 232 unset DOCKER_CLIENTONLY 233 export DOCKER_REMOTE_DAEMON=1 234 hack/make.sh binary 235 ec=$? 236 set +x 237 if [ 0 -ne $ec ]; then 238 echo "ERROR: Build of binary on Windows failed" 239 fi 240 fi 241 242 # Make a local copy of the built binary and ensure that is first in our path 243 if [ $ec -eq 0 ]; then 244 VERSION=$(< ./VERSION) 245 if [ $splitBinary -eq 0 ]; then 246 cp bundles/$VERSION/binary/docker.exe $TEMP 247 else 248 cp bundles/$VERSION/binary-client/docker.exe $TEMP 249 fi 250 ec=$? 251 if [ 0 -ne $ec ]; then 252 echo "ERROR: Failed to copy built binary to $TEMP" 253 fi 254 export PATH=$TEMP:$PATH 255 fi 256 257 # Run the integration tests 258 if [ $ec -eq 0 ]; then 259 echo "INFO: Running Integration tests..." 260 set -x 261 export DOCKER_TEST_TLS_VERIFY="$DOCKER_TLS_VERIFY" 262 export DOCKER_TEST_CERT_PATH="$DOCKER_CERT_PATH" 263 #export TESTFLAGS='-check.vv' 264 hack/make.sh test-integration-cli 265 ec=$? 266 set +x 267 if [ 0 -ne $ec ]; then 268 echo "ERROR: CLI test failed." 269 # Next line is useful, but very long winded if included 270 docker -H=$MAIN_DOCKER_HOST logs --tail 100 "docker-$COMMITHASH" 271 fi 272 fi 273 274 # Tidy up any temporary files from the CI run 275 if [ ! -z $COMMITHASH ]; then 276 rm -rf $TEMP 277 fi 278 279 # CI Integrity check - ensure we are using the same version of go as present in the Dockerfile 280 GOVER_DOCKERFILE=`grep 'ENV GO_VERSION' Dockerfile | awk '{print $3}'` 281 GOVER_INSTALLED=`go version | awk '{print $3}'` 282 if [ "${GOVER_INSTALLED:2}" != "$GOVER_DOCKERFILE" ]; then 283 #ec=1 # Uncomment to make CI fail once all nodes are updated. 284 echo 285 echo "---------------------------------------------------------------------------" 286 echo "WARN: CI should be using go version $GOVER_DOCKERFILE, but is using ${GOVER_INSTALLED:2}" 287 echo " Please ping #docker-maintainers on IRC to get this CI server updated." 288 echo "---------------------------------------------------------------------------" 289 echo 290 fi 291 292 # Check the Linux box is running a matching version of docker 293 if [ "$uniques" -ne 1 ]; then 294 ec=0 # Uncomment to make CI fail once all nodes are updated. 295 echo 296 echo "---------------------------------------------------------------------------" 297 echo "ERROR: This CI node is not running the same version of docker as the daemon." 298 echo " This is a CI configuration issue." 299 echo "---------------------------------------------------------------------------" 300 echo 301 fi 302 303 # Tell the user how we did. 304 if [ $ec -eq 0 ]; then 305 echo INFO: Completed successfully at `date`. 306 else 307 echo ERROR: Failed with exitcode $ec at `date`. 308 fi 309 exit $ec