run.sh 4.7 KB

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