From 7658ba0df3f433235f3ef83aaa0e1b41a1d6166d Mon Sep 17 00:00:00 2001 From: Tim McCormack Date: Wed, 4 Oct 2023 15:21:58 -0400 Subject: [PATCH] feat: Add util for waiting for container startup; use in dbcopyall8 (#1198) `make dev.dbcopyall8` doesn't work unless the mysql containers have been started and are ready to run. This is not the only place we need to wait for a functional check on a container, so in this commit I've gone ahead and started a utility for doing so. This first pass only supports MySQL, but we should at least add Mongo as well, as that's also needed in one of the provisioning scripts. I've moved the _db_copy8_targets from being an order-only prerequisite to being a recursive make call. I'm not sure why the order-only syntax was in use here, but in any case I needed to add in a script call before those targets were called, so it's likely moot. Also: - Drop unneeded `bash -c` wrappers from db copy docker exec calls --- Makefile | 9 ++++++--- provision.sh | 26 ++++---------------------- wait-ready.sh | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 25 deletions(-) create mode 100755 wait-ready.sh diff --git a/Makefile b/Makefile index 82e180c3a3..9010b8e853 100644 --- a/Makefile +++ b/Makefile @@ -461,11 +461,14 @@ dev.dbshell: DB_NAMES_LIST = credentials discovery ecommerce notes registrar xqueue edxapp edxapp_csmh dashboard analytics-api reports reports_v1 _db_copy8_targets = $(addprefix dev.dbcopy8.,$(DB_NAMES_LIST)) -dev.dbcopyall8: | $(_db_copy8_targets) ## Copy data from old mysql 5.7 containers into new mysql8 dbs +dev.dbcopyall8: ## Copy data from old mysql 5.7 containers into new mysql8 dbs + $(MAKE) dev.up.mysql57+mysql80 + ./wait-ready.sh mysql57 mysql80 + $(MAKE) $(_db_copy8_targets) dev.dbcopy8.%: ## Copy data from old mysql 5.7 container into a new 8 db - docker compose exec mysql57 bash -c "mysqldump $*" > .dev/$*.sql - docker compose exec -T mysql80 bash -c "mysql $*" < .dev/$*.sql + docker compose exec mysql57 mysqldump "$*" > .dev/$*.sql + docker compose exec -T mysql80 mysql "$*" < .dev/$*.sql rm .dev/$*.sql dev.dbshell.%: ## Run a SQL shell on the given database. diff --git a/provision.sh b/provision.sh index e22c97f670..0f8eb24f05 100755 --- a/provision.sh +++ b/provision.sh @@ -130,40 +130,22 @@ fi # Ensure the MySQL5 server is online and usable echo "${GREEN}Waiting for MySQL 5.7.${NC}" -until docker compose exec -T mysql57 bash -e -c "mysql -uroot -se \"SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = 'root')\"" &> /dev/null -do - printf "." - sleep 1 -done +./wait-ready.sh mysql57 # Ensure the MySQL8 server is online and usable echo "${GREEN}Waiting for MySQL 8.0.${NC}" -until docker compose exec -T mysql80 bash -e -c "mysql -uroot -se \"SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = 'root')\"" &> /dev/null -do - printf "." - sleep 1 -done +./wait-ready.sh mysql80 # In the event of a fresh MySQL container, wait a few seconds for the server to restart # See https://github.com/docker-library/mysql/issues/245 for why this is necessary. sleep 10 echo "${GREEN}Waiting for MySQL 5.7 to restart.${NC}" -until docker compose exec -T mysql57 bash -e -c "mysql -uroot -se \"SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = 'root')\"" &> /dev/null -do - printf "." - sleep 1 -done - +./wait-ready.sh mysql57 echo -e "${GREEN}MySQL5 ready.${NC}" echo "${GREEN}Waiting for MySQL 8.0 to restart.${NC}" -until docker compose exec -T mysql80 bash -e -c "mysql -uroot -se \"SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = 'root')\"" &> /dev/null -do - printf "." - sleep 1 -done - +./wait-ready.sh mysql80 echo -e "${GREEN}MySQL8 ready.${NC}" # Ensure that the MySQL databases and users are created for all IDAs. diff --git a/wait-ready.sh b/wait-ready.sh new file mode 100755 index 0000000000..1f26c0ef0c --- /dev/null +++ b/wait-ready.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# Wait for the listed services to become ready. +# +# This does not start the containers; that should be performed separately +# via `make dev.up` in order to allow for parallel startup. + +set -eu -o pipefail + +function print_usage { + echo "Usage: $0 service1 service2 ..." +} + +if [[ $# == 0 ]]; then + print_usage + exit 0 +fi + +function wait_db { + container_name="$1" + mysql_probe="SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = 'root')" + until docker compose exec -T "$container_name" mysql -uroot -se "$mysql_probe" &> /dev/null; do + printf "." >&2 + sleep 1 + done + echo >&2 "$container_name is ready" +} + + +for service_name in "$@"; do + case "$service_name" in + mysql*) + wait_db "$service_name" + ;; + # TODO: Add other services... + *) + echo >&2 "Unknown service: $service_name" + exit 1 + ;; + esac +done