test_helpers.bash 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. # Test if requirements are met
  2. (
  3. type docker &>/dev/null || ( echo "docker is not available"; exit 1 )
  4. )>&2
  5. # set a few global variables
  6. SUT_IMAGE=jwilder/nginx-proxy:bats
  7. TEST_FILE=$(basename $BATS_TEST_FILENAME .bats)
  8. # load the Bats stdlib (see https://github.com/sstephenson/bats/pull/110)
  9. DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
  10. export BATS_LIB="${DIR}/lib/bats"
  11. load "${BATS_LIB}/batslib.bash"
  12. # load additional bats helpers
  13. load ${DIR}/lib/helpers.bash
  14. load ${DIR}/lib/docker_helpers.bash
  15. # Define functions specific to our test suite
  16. # run the SUT docker container
  17. # and makes sure it remains started
  18. # and displays the nginx-proxy start logs
  19. #
  20. # $1 container name
  21. # $@ other options for the `docker run` command
  22. function nginxproxy {
  23. local -r container_name=$1
  24. shift
  25. docker_clean $container_name \
  26. && docker run -d \
  27. --label bats-type="nginx-proxy" \
  28. --name $container_name \
  29. -v $DIR/lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro \
  30. "$@" \
  31. $SUT_IMAGE \
  32. && wait_for_nginxproxy_container_to_start $container_name \
  33. && docker logs $container_name
  34. }
  35. # wait until the nginx-proxy container is ready to operate
  36. #
  37. # $1 container name
  38. function wait_for_nginxproxy_container_to_start {
  39. local -r container_name=$1
  40. sleep .5s # give time to eventually fail to initialize
  41. function is_running {
  42. run docker_running_state $container_name
  43. assert_output "true"
  44. }
  45. retry 3 1 is_running
  46. }
  47. # Send a HTTP request to container $1 for path $2 and
  48. # Additional curl options can be passed as $@
  49. #
  50. # $1 container name
  51. # $2 HTTP path to query
  52. # $@ additional options to pass to the curl command
  53. function curl_container {
  54. local -r container=$1
  55. local -r path=$2
  56. shift 2
  57. docker run --label bats-type="curl" appropriate/curl --silent \
  58. --connect-timeout 5 \
  59. --max-time 20 \
  60. "$@" \
  61. http://$(docker_ip $container)${path}
  62. }
  63. # Send a HTTPS request to container $1 for path $2 and
  64. # Additional curl options can be passed as $@
  65. #
  66. # $1 container name
  67. # $2 HTTPS path to query
  68. # $@ additional options to pass to the curl command
  69. function curl_container_https {
  70. local -r container=$1
  71. local -r path=$2
  72. shift 2
  73. docker run --label bats-type="curl" appropriate/curl --silent \
  74. --connect-timeout 5 \
  75. --max-time 20 \
  76. --insecure \
  77. "$@" \
  78. https://$(docker_ip $container)${path}
  79. }
  80. # start a container running (one or multiple) webservers listening on given ports
  81. #
  82. # $1 container name
  83. # $2 container port(s). If multiple ports, provide them as a string: "80 90" with a space as a separator
  84. # $@ `docker run` additional options
  85. function prepare_web_container {
  86. local -r container_name=$1
  87. local -r ports=$2
  88. shift 2
  89. local -r options="$@"
  90. local expose_option=""
  91. IFS=$' \t\n' # See https://github.com/sstephenson/bats/issues/89
  92. for port in $ports; do
  93. expose_option="${expose_option}--expose=$port "
  94. done
  95. ( # used for debugging purpose. Will be display if test fails
  96. echo "container_name: $container_name"
  97. echo "ports: $ports"
  98. echo "options: $options"
  99. echo "expose_option: $expose_option"
  100. )>&2
  101. docker_clean $container_name
  102. # GIVEN a container exposing 1 webserver on ports 1234
  103. run docker run -d \
  104. --label bats-type="web" \
  105. --name $container_name \
  106. $expose_option \
  107. -w /var/www/ \
  108. -v $DIR/web_helpers:/var/www:ro \
  109. $options \
  110. -e PYTHON_PORTS="$ports" \
  111. python:3 bash -c "
  112. trap '[ \${#PIDS[@]} -gt 0 ] && kill -TERM \${PIDS[@]}' TERM
  113. declare -a PIDS
  114. for port in \$PYTHON_PORTS; do
  115. echo starting a web server listening on port \$port;
  116. ./webserver.py \$port &
  117. PIDS+=(\$!)
  118. done
  119. wait \${PIDS[@]}
  120. trap - TERM
  121. wait \${PIDS[@]}
  122. "
  123. assert_success
  124. # THEN querying directly port works
  125. IFS=$' \t\n' # See https://github.com/sstephenson/bats/issues/89
  126. for port in $ports; do
  127. run retry 5 1s docker run --label bats-type="curl" appropriate/curl --silent --fail http://$(docker_ip $container_name):$port/port
  128. assert_output "answer from port $port"
  129. done
  130. }
  131. # stop all containers with the "bats-type" label (matching the optionally supplied value)
  132. #
  133. # $1 optional label value
  134. function stop_bats_containers {
  135. local -r value=$1
  136. if [ -z "$value" ]; then
  137. CIDS=( $(docker ps -q --filter "label=bats-type") )
  138. else
  139. CIDS=( $(docker ps -q --filter "label=bats-type=$value") )
  140. fi
  141. if [ ${#CIDS[@]} -gt 0 ]; then
  142. docker stop ${CIDS[@]} >&2
  143. fi
  144. }
  145. # wait for a docker-gen container to receive a specified event from a
  146. # container with the specified ID/name
  147. #
  148. # $1 docker-gen container name
  149. # $2 event
  150. # $3 ID/name of container to receive event from
  151. function dockergen_wait_for_event {
  152. local -r container=$1
  153. local -r event=$2
  154. local -r other=$3
  155. local -r did=$(docker_id "$other")
  156. docker_wait_for_log "$container" 9 "Received event $event for container ${did:0:12}"
  157. }