setup.sh 11 KB

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