run.sh 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #!/bin/bash
  2. set -e
  3. dir="$(dirname "$(readlink -f "$BASH_SOURCE")")"
  4. self="$(basename "$0")"
  5. usage() {
  6. cat <<EOUSAGE
  7. usage: $self [-t test ...] image:tag [...]
  8. ie: $self debian:stretch
  9. $self -t utc python:3
  10. $self -t utc python:3 -t python-hy
  11. This script processes the specified Docker images to test their running
  12. environments.
  13. EOUSAGE
  14. }
  15. # arg handling
  16. opts="$(getopt -o 'ht:c:?' --long 'dry-run,help,test:,config:,keep-namespace' -- "$@" || { usage >&2 && false; })"
  17. eval set -- "$opts"
  18. declare -A argTests=()
  19. declare -a configs=()
  20. dryRun=
  21. keepNamespace=
  22. while true; do
  23. flag=$1
  24. shift
  25. case "$flag" in
  26. --dry-run) dryRun=1 ;;
  27. --help|-h|'-?') usage && exit 0 ;;
  28. --test|-t) argTests["$1"]=1 && shift ;;
  29. --config|-c) configs+=("$(readlink -f "$1")") && shift ;;
  30. --keep-namespace) keepNamespace=1 ;;
  31. --) break ;;
  32. *)
  33. {
  34. echo "error: unknown flag: $flag"
  35. usage
  36. } >&2
  37. exit 1
  38. ;;
  39. esac
  40. done
  41. if [ $# -eq 0 ]; then
  42. usage >&2
  43. exit 1
  44. fi
  45. # declare configuration variables
  46. declare -a globalTests=()
  47. declare -A testAlias=()
  48. declare -A imageTests=()
  49. declare -A globalExcludeTests=()
  50. declare -A explicitTests=()
  51. # if there are no user-specified configs, use the default config
  52. if [ ${#configs} -eq 0 ]; then
  53. configs+=("$dir/config.sh")
  54. fi
  55. # load the configs
  56. declare -A testPaths=()
  57. for conf in "${configs[@]}"; do
  58. . "$conf"
  59. # Determine the full path to any newly-declared tests
  60. confDir="$(dirname "$conf")"
  61. for testName in ${globalTests[@]} ${imageTests[@]}; do
  62. [ "${testPaths[$testName]}" ] && continue
  63. if [ -d "$confDir/tests/$testName" ]; then
  64. # Test directory found relative to the conf file
  65. testPaths[$testName]="$confDir/tests/$testName"
  66. elif [ -d "$dir/tests/$testName" ]; then
  67. # Test directory found in the main tests/ directory
  68. testPaths[$testName]="$dir/tests/$testName"
  69. fi
  70. done
  71. done
  72. didFail=
  73. for dockerImage in "$@"; do
  74. echo "testing $dockerImage"
  75. if ! docker inspect "$dockerImage" &> /dev/null; then
  76. echo $'\timage does not exist!'
  77. didFail=1
  78. continue
  79. fi
  80. repo="${dockerImage%:*}"
  81. tagVar="${dockerImage#*:}"
  82. #version="${tagVar%-*}"
  83. variant="${tagVar##*-}"
  84. case "$tagVar" in
  85. *onbuild*)
  86. # "maven:onbuild-alpine" is still onbuild
  87. # ONCE ONBUILD, ALWAYS ONBUILD
  88. variant='onbuild'
  89. ;;
  90. *fpm-*)
  91. # lolPHP
  92. variant='fpm'
  93. ;;
  94. *alpine*)
  95. # "alpine3.4", "alpine3.6", "nginx:alpine-perl", etc are still "alpine" variants
  96. variant='alpine'
  97. ;;
  98. slim-*|*-slim-*)
  99. # "slim-jessie" is still "slim"
  100. variant='slim'
  101. ;;
  102. esac
  103. testRepo="$repo"
  104. if [ -z "$keepNamespace" ]; then
  105. testRepo="${testRepo##*/}"
  106. fi
  107. [ -z "${testAlias[$repo]}" ] || testRepo="${testAlias[$repo]}"
  108. explicitVariant=
  109. if [ \
  110. "${explicitTests[:$variant]}" \
  111. -o "${explicitTests[$repo:$variant]}" \
  112. -o "${explicitTests[$testRepo:$variant]}" \
  113. ]; then
  114. explicitVariant=1
  115. fi
  116. testCandidates=()
  117. if [ -z "$explicitVariant" ]; then
  118. testCandidates+=( "${globalTests[@]}" )
  119. fi
  120. testCandidates+=(
  121. ${imageTests[:$variant]}
  122. )
  123. if [ -z "$explicitVariant" ]; then
  124. testCandidates+=(
  125. ${imageTests[$testRepo]}
  126. )
  127. fi
  128. testCandidates+=(
  129. ${imageTests[$testRepo:$variant]}
  130. )
  131. if [ "$testRepo" != "$repo" ]; then
  132. if [ -z "$explicitVariant" ]; then
  133. testCandidates+=(
  134. ${imageTests[$repo]}
  135. )
  136. fi
  137. testCandidates+=(
  138. ${imageTests[$repo:$variant]}
  139. )
  140. fi
  141. tests=()
  142. for t in "${testCandidates[@]}"; do
  143. if [ ${#argTests[@]} -gt 0 -a -z "${argTests[$t]}" ]; then
  144. # skipping due to -t
  145. continue
  146. fi
  147. if [ \
  148. ! -z "${globalExcludeTests[${testRepo}_$t]}" \
  149. -o ! -z "${globalExcludeTests[${testRepo}:${variant}_$t]}" \
  150. -o ! -z "${globalExcludeTests[:${variant}_$t]}" \
  151. -o ! -z "${globalExcludeTests[${repo}_$t]}" \
  152. -o ! -z "${globalExcludeTests[${repo}:${variant}_$t]}" \
  153. -o ! -z "${globalExcludeTests[:${variant}_$t]}" \
  154. ]; then
  155. # skipping due to exclude
  156. continue
  157. fi
  158. tests+=( "$t" )
  159. done
  160. currentTest=0
  161. totalTest="${#tests[@]}"
  162. for t in "${tests[@]}"; do
  163. (( currentTest+=1 ))
  164. echo -ne "\t'$t' [$currentTest/$totalTest]..."
  165. # run test against dockerImage here
  166. # find the script for the test
  167. scriptDir="${testPaths[$t]}"
  168. if [ -d "$scriptDir" ]; then
  169. script="$scriptDir/run.sh"
  170. if [ -x "$script" -a ! -d "$script" ]; then
  171. # TODO dryRun logic
  172. if output="$("$script" $dockerImage)"; then
  173. if [ -f "$scriptDir/expected-std-out.txt" ] && ! d="$(echo "$output" | diff -u "$scriptDir/expected-std-out.txt" - 2>/dev/null)"; then
  174. echo 'failed; unexpected output:'
  175. echo "$d"
  176. didFail=1
  177. else
  178. echo 'passed'
  179. fi
  180. else
  181. echo 'failed'
  182. didFail=1
  183. fi
  184. else
  185. echo "skipping"
  186. echo >&2 "error: $script missing, not executable or is a directory"
  187. didFail=1
  188. continue
  189. fi
  190. else
  191. echo "skipping"
  192. echo >&2 "error: unable to locate test '$t'"
  193. didFail=1
  194. continue
  195. fi
  196. done
  197. done
  198. if [ "$didFail" ]; then
  199. exit 1
  200. fi