run.sh 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #!/usr/bin/env bash
  2. ## This script runs CT (and necessary dependencies) in docker container(s)
  3. set -euo pipefail
  4. # ensure dir
  5. cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")/../.."
  6. help() {
  7. echo
  8. echo "-h|--help: To display this usage info"
  9. echo "--app lib_dir/app_name: For which app to run start docker-compose, and run common tests"
  10. echo "--suites SUITE1,SUITE2: Comma separated SUITE names to run. e.g. apps/emqx/test/emqx_SUITE.erl"
  11. echo "--console: Start EMQX in console mode but do not run test cases"
  12. echo "--attach: Attach to the Erlang docker container without running any test case"
  13. echo "--stop: Stop running containers for the given app"
  14. echo "--only-up: Only start the testbed but do not run CT"
  15. echo "--keep-up: Keep the testbed running after CT"
  16. }
  17. WHICH_APP='novalue'
  18. CONSOLE='no'
  19. KEEP_UP='no'
  20. ONLY_UP='no'
  21. SUITES=''
  22. ATTACH='no'
  23. STOP='no'
  24. while [ "$#" -gt 0 ]; do
  25. case $1 in
  26. -h|--help)
  27. help
  28. exit 0
  29. ;;
  30. --app)
  31. WHICH_APP="$2"
  32. shift 2
  33. ;;
  34. --only-up)
  35. ONLY_UP='yes'
  36. shift 1
  37. ;;
  38. --keep-up)
  39. KEEP_UP='yes'
  40. shift 1
  41. ;;
  42. --attach)
  43. ATTACH='yes'
  44. shift 1
  45. ;;
  46. --stop)
  47. STOP='yes'
  48. shift 1
  49. ;;
  50. --console)
  51. CONSOLE='yes'
  52. shift 1
  53. ;;
  54. --suites)
  55. SUITES="$2"
  56. shift 2
  57. ;;
  58. *)
  59. echo "unknown option $1"
  60. exit 1
  61. ;;
  62. esac
  63. done
  64. if [ "${WHICH_APP}" = 'novalue' ]; then
  65. echo "must provide --app arg"
  66. help
  67. exit 1
  68. fi
  69. ERLANG_CONTAINER='erlang'
  70. DOCKER_CT_ENVS_FILE="${WHICH_APP}/docker-ct"
  71. case "${WHICH_APP}" in
  72. lib-ee*)
  73. ## ensure enterprise profile when testing lib-ee applications
  74. export PROFILE='emqx-enterprise'
  75. ;;
  76. *)
  77. export PROFILE="${PROFILE:-emqx}"
  78. ;;
  79. esac
  80. if [ -f "$DOCKER_CT_ENVS_FILE" ]; then
  81. # shellcheck disable=SC2002
  82. CT_DEPS="$(cat "$DOCKER_CT_ENVS_FILE" | xargs)"
  83. fi
  84. CT_DEPS="${ERLANG_CONTAINER} ${CT_DEPS:-}"
  85. FILES=( )
  86. for dep in ${CT_DEPS}; do
  87. case "${dep}" in
  88. erlang)
  89. FILES+=( '.ci/docker-compose-file/docker-compose.yaml' )
  90. ;;
  91. toxiproxy)
  92. FILES+=( '.ci/docker-compose-file/docker-compose-toxiproxy.yaml' )
  93. ;;
  94. influxdb)
  95. FILES+=( '.ci/docker-compose-file/docker-compose-influxdb-tcp.yaml'
  96. '.ci/docker-compose-file/docker-compose-influxdb-tls.yaml' )
  97. ;;
  98. mongo)
  99. FILES+=( '.ci/docker-compose-file/docker-compose-mongo-single-tcp.yaml'
  100. '.ci/docker-compose-file/docker-compose-mongo-single-tls.yaml' )
  101. ;;
  102. mongo_rs_sharded)
  103. FILES+=( '.ci/docker-compose-file/docker-compose-mongo-replicaset-tcp.yaml'
  104. '.ci/docker-compose-file/docker-compose-mongo-sharded-tcp.yaml' )
  105. ;;
  106. redis)
  107. FILES+=( '.ci/docker-compose-file/docker-compose-redis-single-tcp.yaml'
  108. '.ci/docker-compose-file/docker-compose-redis-single-tls.yaml'
  109. '.ci/docker-compose-file/docker-compose-redis-sentinel-tcp.yaml'
  110. '.ci/docker-compose-file/docker-compose-redis-sentinel-tls.yaml' )
  111. ;;
  112. redis_cluster)
  113. FILES+=( '.ci/docker-compose-file/docker-compose-redis-cluster-tcp.yaml'
  114. '.ci/docker-compose-file/docker-compose-redis-cluster-tls.yaml' )
  115. ;;
  116. mysql)
  117. FILES+=( '.ci/docker-compose-file/docker-compose-mysql-tcp.yaml'
  118. '.ci/docker-compose-file/docker-compose-mysql-tls.yaml' )
  119. ;;
  120. pgsql)
  121. FILES+=( '.ci/docker-compose-file/docker-compose-pgsql-tcp.yaml'
  122. '.ci/docker-compose-file/docker-compose-pgsql-tls.yaml' )
  123. ;;
  124. kafka)
  125. # Kafka container generates root owned ssl files
  126. # the files are shared with EMQX (with a docker volume)
  127. NEED_ROOT=yes
  128. FILES+=( '.ci/docker-compose-file/docker-compose-kafka.yaml' )
  129. ;;
  130. *)
  131. echo "unknown_ct_dependency $dep"
  132. exit 1
  133. ;;
  134. esac
  135. done
  136. F_OPTIONS=""
  137. for file in "${FILES[@]}"; do
  138. F_OPTIONS="$F_OPTIONS -f $file"
  139. done
  140. ORIG_UID_GID="$UID:$UID"
  141. if [[ "${NEED_ROOT:-}" == 'yes' ]]; then
  142. export UID_GID='root:root'
  143. else
  144. # Passing $UID to docker-compose to be used in erlang container
  145. # as owner of the main process to avoid git repo permissions issue.
  146. # Permissions issue happens because we are mounting local filesystem
  147. # where files are owned by $UID to docker container where it's using
  148. # root (UID=0) by default, and git is not happy about it.
  149. export UID_GID="$ORIG_UID_GID"
  150. fi
  151. if [ "$STOP" = 'no' ]; then
  152. # shellcheck disable=2086 # no quotes for F_OPTIONS
  153. docker-compose $F_OPTIONS up -d --build --remove-orphans
  154. fi
  155. # /emqx is where the source dir is mounted to the Erlang container
  156. # in .ci/docker-compose-file/docker-compose.yaml
  157. TTY=''
  158. if [[ -t 1 ]]; then
  159. TTY='-t'
  160. fi
  161. echo "Fixing file owners and permissions for $UID_GID"
  162. # rebar and hex cache directory need to be writable by $UID
  163. docker exec -i $TTY -u root:root "$ERLANG_CONTAINER" bash -c "mkdir -p /.cache && chown $UID_GID /.cache && chown -R $UID_GID /emqx"
  164. # need to initialize .erlang.cookie manually here because / is not writable by $UID
  165. docker exec -i $TTY -u root:root "$ERLANG_CONTAINER" bash -c "openssl rand -base64 16 > /.erlang.cookie && chown $UID_GID /.erlang.cookie && chmod 0400 /.erlang.cookie"
  166. restore_ownership() {
  167. if [[ "$ORIG_UID_GID" != "$UID_GID" ]]; then
  168. docker exec -i $TTY -u root:root "$ERLANG_CONTAINER" bash -c "chown -R $ORIG_UID_GID /emqx"
  169. fi
  170. }
  171. if [ "$ONLY_UP" = 'yes' ]; then
  172. exit 0
  173. fi
  174. set +e
  175. if [ "$STOP" = 'yes' ]; then
  176. # shellcheck disable=2086 # no quotes for F_OPTIONS
  177. docker-compose $F_OPTIONS down --remove-orphans
  178. elif [ "$ATTACH" = 'yes' ]; then
  179. docker exec -it "$ERLANG_CONTAINER" bash
  180. restore_ownership
  181. elif [ "$CONSOLE" = 'yes' ]; then
  182. docker exec -e PROFILE="$PROFILE" -i $TTY "$ERLANG_CONTAINER" bash -c "make run"
  183. restore_ownership
  184. else
  185. docker exec -e PROFILE="$PROFILE" -i $TTY -e EMQX_CT_SUITES="$SUITES" "$ERLANG_CONTAINER" bash -c "BUILD_WITHOUT_QUIC=1 make ${WHICH_APP}-ct"
  186. RESULT=$?
  187. restore_ownership
  188. if [ $RESULT -ne 0 ]; then
  189. LOG='_build/test/logs/docker-compose.log'
  190. echo "Dumping docker-compose log to $LOG"
  191. # shellcheck disable=2086 # no quotes for F_OPTIONS
  192. docker-compose $F_OPTIONS logs --no-color --timestamps > "$LOG"
  193. fi
  194. if [ "$KEEP_UP" != 'yes' ]; then
  195. # shellcheck disable=2086 # no quotes for F_OPTIONS
  196. docker-compose $F_OPTIONS down
  197. fi
  198. exit $RESULT
  199. fi