run.sh 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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. psmdb-*)
  103. # Percona Server for MongoDB is still "mongo"
  104. variant='psmdb'
  105. ;;
  106. esac
  107. testRepo="$repo"
  108. if [ -z "$keepNamespace" ]; then
  109. testRepo="${testRepo##*/}"
  110. fi
  111. if [ -n "${testAlias[$repo:$variant]}" ]; then
  112. testRepo="${testAlias[$repo:$variant]}"
  113. elif [ -n "${testAlias[$repo]}" ]; then
  114. testRepo="${testAlias[$repo]}"
  115. fi
  116. explicitVariant=
  117. if [ \
  118. "${explicitTests[:$variant]}" \
  119. -o "${explicitTests[$repo:$variant]}" \
  120. -o "${explicitTests[$testRepo:$variant]}" \
  121. ]; then
  122. explicitVariant=1
  123. fi
  124. testCandidates=()
  125. if [ -z "$explicitVariant" ]; then
  126. testCandidates+=( "${globalTests[@]}" )
  127. fi
  128. testCandidates+=(
  129. ${imageTests[:$variant]}
  130. )
  131. if [ -z "$explicitVariant" ]; then
  132. testCandidates+=(
  133. ${imageTests[$testRepo]}
  134. )
  135. fi
  136. testCandidates+=(
  137. ${imageTests[$testRepo:$variant]}
  138. )
  139. if [ "$testRepo" != "$repo" ]; then
  140. if [ -z "$explicitVariant" ]; then
  141. testCandidates+=(
  142. ${imageTests[$repo]}
  143. )
  144. fi
  145. testCandidates+=(
  146. ${imageTests[$repo:$variant]}
  147. )
  148. fi
  149. tests=()
  150. for t in "${testCandidates[@]}"; do
  151. if [ ${#argTests[@]} -gt 0 -a -z "${argTests[$t]}" ]; then
  152. # skipping due to -t
  153. continue
  154. fi
  155. if [ \
  156. ! -z "${globalExcludeTests[${testRepo}_$t]}" \
  157. -o ! -z "${globalExcludeTests[${testRepo}:${variant}_$t]}" \
  158. -o ! -z "${globalExcludeTests[:${variant}_$t]}" \
  159. -o ! -z "${globalExcludeTests[${repo}_$t]}" \
  160. -o ! -z "${globalExcludeTests[${repo}:${variant}_$t]}" \
  161. -o ! -z "${globalExcludeTests[:${variant}_$t]}" \
  162. ]; then
  163. # skipping due to exclude
  164. continue
  165. fi
  166. tests+=( "$t" )
  167. done
  168. currentTest=0
  169. totalTest="${#tests[@]}"
  170. for t in "${tests[@]}"; do
  171. (( currentTest+=1 ))
  172. echo -ne "\t'$t' [$currentTest/$totalTest]..."
  173. # run test against dockerImage here
  174. # find the script for the test
  175. scriptDir="${testPaths[$t]}"
  176. if [ -d "$scriptDir" ]; then
  177. script="$scriptDir/run.sh"
  178. if [ -x "$script" -a ! -d "$script" ]; then
  179. # TODO dryRun logic
  180. if output="$("$script" $dockerImage)"; then
  181. if [ -f "$scriptDir/expected-std-out.txt" ] && ! d="$(echo "$output" | diff -u "$scriptDir/expected-std-out.txt" - 2>/dev/null)"; then
  182. echo 'failed; unexpected output:'
  183. echo "$d"
  184. didFail=1
  185. else
  186. echo 'passed'
  187. fi
  188. else
  189. echo 'failed'
  190. didFail=1
  191. fi
  192. else
  193. echo "skipping"
  194. echo >&2 "error: $script missing, not executable or is a directory"
  195. didFail=1
  196. continue
  197. fi
  198. else
  199. echo "skipping"
  200. echo >&2 "error: unable to locate test '$t'"
  201. didFail=1
  202. continue
  203. fi
  204. done
  205. done
  206. if [ "$didFail" ]; then
  207. exit 1
  208. fi