run.sh 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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 "--console: Start EMQX in console mode but do not run test cases"
  11. echo "--attach: Attach to the Erlang docker container without running any test case"
  12. echo "--stop: Stop running containers for the given app"
  13. echo "--only-up: Only start the testbed but do not run CT"
  14. echo "--keep-up: Keep the testbed running after CT"
  15. echo "--ci: Set this flag in GitHub action to enforce no tests are skipped"
  16. echo "--" If any, all args after '--' are passed to rebar3 ct
  17. echo " otherwise it runs the entire app's CT"
  18. }
  19. if command -v docker-compose; then
  20. DC='docker-compose'
  21. else
  22. DC='docker compose'
  23. fi
  24. WHICH_APP='novalue'
  25. CONSOLE='no'
  26. KEEP_UP='no'
  27. ONLY_UP='no'
  28. ATTACH='no'
  29. STOP='no'
  30. IS_CI='no'
  31. while [ "$#" -gt 0 ]; do
  32. case $1 in
  33. -h|--help)
  34. help
  35. exit 0
  36. ;;
  37. --app)
  38. WHICH_APP="$2"
  39. shift 2
  40. ;;
  41. --only-up)
  42. ONLY_UP='yes'
  43. shift 1
  44. ;;
  45. --keep-up)
  46. KEEP_UP='yes'
  47. shift 1
  48. ;;
  49. --attach)
  50. ATTACH='yes'
  51. shift 1
  52. ;;
  53. --stop)
  54. STOP='yes'
  55. shift 1
  56. ;;
  57. --console)
  58. CONSOLE='yes'
  59. shift 1
  60. ;;
  61. --ci)
  62. IS_CI='yes'
  63. shift 1
  64. ;;
  65. --)
  66. shift 1
  67. REBAR3CT="$*"
  68. shift $#
  69. ;;
  70. *)
  71. echo "unknown option $1"
  72. exit 1
  73. ;;
  74. esac
  75. done
  76. if [ "${WHICH_APP}" = 'novalue' ]; then
  77. echo "must provide --app arg"
  78. help
  79. exit 1
  80. fi
  81. if [[ "${WHICH_APP}" == lib-ee* && (-z "${PROFILE+x}" || "${PROFILE}" != emqx-enterprise) ]]; then
  82. echo 'You are trying to run an enterprise test case without the emqx-enterprise profile.'
  83. echo 'This will most likely not work.'
  84. echo ''
  85. echo 'Run "export PROFILE=emqx-enterprise" and "make" to fix this'
  86. exit 1
  87. fi
  88. ERLANG_CONTAINER='erlang'
  89. DOCKER_CT_ENVS_FILE="${WHICH_APP}/docker-ct"
  90. case "${WHICH_APP}" in
  91. lib-ee*)
  92. ## ensure enterprise profile when testing lib-ee applications
  93. export PROFILE='emqx-enterprise'
  94. ;;
  95. *)
  96. export PROFILE="${PROFILE:-emqx}"
  97. ;;
  98. esac
  99. if [ -f "$DOCKER_CT_ENVS_FILE" ]; then
  100. # shellcheck disable=SC2002
  101. CT_DEPS="$(cat "$DOCKER_CT_ENVS_FILE" | xargs)"
  102. fi
  103. CT_DEPS="${ERLANG_CONTAINER} ${CT_DEPS:-}"
  104. FILES=( )
  105. for dep in ${CT_DEPS}; do
  106. case "${dep}" in
  107. erlang)
  108. FILES+=( '.ci/docker-compose-file/docker-compose.yaml' )
  109. ;;
  110. toxiproxy)
  111. FILES+=( '.ci/docker-compose-file/docker-compose-toxiproxy.yaml' )
  112. ;;
  113. influxdb)
  114. FILES+=( '.ci/docker-compose-file/docker-compose-influxdb-tcp.yaml'
  115. '.ci/docker-compose-file/docker-compose-influxdb-tls.yaml' )
  116. ;;
  117. mongo)
  118. FILES+=( '.ci/docker-compose-file/docker-compose-mongo-single-tcp.yaml'
  119. '.ci/docker-compose-file/docker-compose-mongo-single-tls.yaml' )
  120. ;;
  121. mongo_rs_sharded)
  122. FILES+=( '.ci/docker-compose-file/docker-compose-mongo-replicaset-tcp.yaml'
  123. '.ci/docker-compose-file/docker-compose-mongo-sharded-tcp.yaml' )
  124. ;;
  125. redis)
  126. FILES+=( '.ci/docker-compose-file/docker-compose-redis-single-tcp.yaml'
  127. '.ci/docker-compose-file/docker-compose-redis-single-tls.yaml'
  128. '.ci/docker-compose-file/docker-compose-redis-sentinel-tcp.yaml'
  129. '.ci/docker-compose-file/docker-compose-redis-sentinel-tls.yaml' )
  130. ;;
  131. redis_cluster)
  132. FILES+=( '.ci/docker-compose-file/docker-compose-redis-cluster-tcp.yaml'
  133. '.ci/docker-compose-file/docker-compose-redis-cluster-tls.yaml' )
  134. ;;
  135. mysql)
  136. FILES+=( '.ci/docker-compose-file/docker-compose-mysql-tcp.yaml'
  137. '.ci/docker-compose-file/docker-compose-mysql-tls.yaml' )
  138. ;;
  139. pgsql)
  140. FILES+=( '.ci/docker-compose-file/docker-compose-pgsql-tcp.yaml'
  141. '.ci/docker-compose-file/docker-compose-pgsql-tls.yaml' )
  142. ;;
  143. kafka)
  144. # Kafka container generates root owned ssl files
  145. # the files are shared with EMQX (with a docker volume)
  146. NEED_ROOT=yes
  147. FILES+=( '.ci/docker-compose-file/docker-compose-kafka.yaml' )
  148. ;;
  149. tdengine)
  150. FILES+=( '.ci/docker-compose-file/docker-compose-tdengine-restful.yaml' )
  151. ;;
  152. *)
  153. echo "unknown_ct_dependency $dep"
  154. exit 1
  155. ;;
  156. esac
  157. done
  158. F_OPTIONS=""
  159. for file in "${FILES[@]}"; do
  160. F_OPTIONS="$F_OPTIONS -f $file"
  161. done
  162. ORIG_UID_GID="$UID:$UID"
  163. if [[ "${NEED_ROOT:-}" == 'yes' ]]; then
  164. export UID_GID='root:root'
  165. else
  166. # Passing $UID to docker-compose to be used in erlang container
  167. # as owner of the main process to avoid git repo permissions issue.
  168. # Permissions issue happens because we are mounting local filesystem
  169. # where files are owned by $UID to docker container where it's using
  170. # root (UID=0) by default, and git is not happy about it.
  171. export UID_GID="$ORIG_UID_GID"
  172. fi
  173. # /emqx is where the source dir is mounted to the Erlang container
  174. # in .ci/docker-compose-file/docker-compose.yaml
  175. TTY=''
  176. if [[ -t 1 ]]; then
  177. TTY='-t'
  178. fi
  179. function restore_ownership {
  180. if ! sudo chown -R "$ORIG_UID_GID" . >/dev/null 2>&1; then
  181. docker exec -i $TTY -u root:root "$ERLANG_CONTAINER" bash -c "chown -R $ORIG_UID_GID /emqx" >/dev/null 2>&1 || true
  182. fi
  183. }
  184. restore_ownership
  185. trap restore_ownership EXIT
  186. if [ "$STOP" = 'no' ]; then
  187. # some left-over log file has to be deleted before a new docker-compose up
  188. rm -f '.ci/docker-compose-file/redis/*.log'
  189. # shellcheck disable=2086 # no quotes for F_OPTIONS
  190. $DC $F_OPTIONS up -d --build --remove-orphans
  191. fi
  192. echo "Fixing file owners and permissions for $UID_GID"
  193. # rebar and hex cache directory need to be writable by $UID
  194. docker exec -i $TTY -u root:root "$ERLANG_CONTAINER" bash -c "mkdir -p /.cache && chown $UID_GID /.cache && chown -R $UID_GID /emqx/.git /emqx/.ci /emqx/_build/default/lib"
  195. # need to initialize .erlang.cookie manually here because / is not writable by $UID
  196. 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"
  197. if [ "$ONLY_UP" = 'yes' ]; then
  198. exit 0
  199. fi
  200. set +e
  201. if [ "$STOP" = 'yes' ]; then
  202. # shellcheck disable=2086 # no quotes for F_OPTIONS
  203. $DC $F_OPTIONS down --remove-orphans
  204. elif [ "$ATTACH" = 'yes' ]; then
  205. docker exec -it "$ERLANG_CONTAINER" bash
  206. elif [ "$CONSOLE" = 'yes' ]; then
  207. docker exec -e PROFILE="$PROFILE" -i $TTY "$ERLANG_CONTAINER" bash -c "make run"
  208. else
  209. if [ -z "${REBAR3CT:-}" ]; then
  210. docker exec -e IS_CI="$IS_CI" -e PROFILE="$PROFILE" -i $TTY "$ERLANG_CONTAINER" bash -c "BUILD_WITHOUT_QUIC=1 make ${WHICH_APP}-ct"
  211. else
  212. docker exec -e IS_CI="$IS_CI" -e PROFILE="$PROFILE" -i $TTY "$ERLANG_CONTAINER" bash -c "./rebar3 ct $REBAR3CT"
  213. fi
  214. RESULT=$?
  215. restore_ownership
  216. if [ $RESULT -ne 0 ]; then
  217. LOG='_build/test/logs/docker-compose.log'
  218. echo "Dumping docker-compose log to $LOG"
  219. # shellcheck disable=2086 # no quotes for F_OPTIONS
  220. $DC $F_OPTIONS logs --no-color --timestamps > "$LOG"
  221. fi
  222. if [ "$KEEP_UP" != 'yes' ]; then
  223. # shellcheck disable=2086 # no quotes for F_OPTIONS
  224. $DC $F_OPTIONS down
  225. fi
  226. exit $RESULT
  227. fi