Add sandbox/deployment.sh

This commit is contained in:
2026-01-13 13:43:25 +00:00
parent 0e250a8ba6
commit 1265673a17

277
sandbox/deployment.sh Normal file
View File

@@ -0,0 +1,277 @@
#!/bin/bash
usage() {
cat <<EOU
Usage: $0 COMMAND -n NODE_NAME -w STACK_NAME -N NODE_SETTINGS.env -P PROJECT_SETTINGS.env -f COMPOSE.yml [-u] [-s SECRETS.env]
COMMAND
check - test composer files syntax and print final config
deploy - deploy to node
run - deploy here without swarm
stop - stop here without swarm
Required arguments:
-f COMPOSE - compose file (multivalue option)
-w STACK_NAME - stack name for swarm. Required for COMMAND=deploy
Optional arguments:
-N SETTINGS - node settings (multivalue option)
-P SETTINGS - product settings (multivalue option)
-n NODE_NAME - node name.
-u - update images from registry on deploy
-s SECRETS.env - path to env file for override secrets versions.
EOU
1>&2; exit 1;
}
COMMAND=$1
shift
commands=('deploy','check','run','stop')
if [[ ! "${commands[@]}" =~ "${COMMAND}" ]]; then
usage
fi
COMPOSERS=()
NODE_NAME=""
NODE_SETTINGS=()
PRODUCT_SETTINGS=()
SECRET_SETTINGS=""
STACK_NAME=""
DO_UPDATE="no"
while getopts ":n:N:P:w:s:f:h:u" o; do
case "${o}" in
n)
NODE_NAME="${OPTARG}"
;;
N)
NODE_SETTINGS+=("${OPTARG}")
;;
P)
PRODUCT_SETTINGS+=("${OPTARG}")
;;
s)
SECRET_SETTINGS="${OPTARG}"
;;
f)
COMPOSERS+=("${OPTARG}")
;;
w)
STACK_NAME=${OPTARG}
;;
u)
DO_UPDATE="yes"
;;
h)
usage
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
if [ "${COMMAND}" == "" ] || [ "${COMPOSERS}" == "" ]; then
echo "Required arguments missing"
usage
fi
# building node settings
if [ -f "$NODE_NAME.env" ]; then
set +a
. "$NODE_NAME.env"
set -a
fi
for NODE_SETTING in "${NODE_SETTINGS[@]}"; do
. $NODE_SETTING
done
# building project settings
bash -c "echo ''> .project.tmp.env"
for PRODUCT_SETTING in "${PRODUCT_SETTINGS[@]}"; do
bash -c "cat $PRODUCT_SETTING >> .project.tmp.env"
done
export PROJECT_SETTINGS=".project.tmp.env"
grep ^CLIENT_API .project.tmp.env | sed 's/^CLIENT_//' > .project.client.tmp.env
grep ^ADMIN_API .project.tmp.env | sed 's/^ADMIN_//' > .project.admin.tmp.env
grep ^I_CLIENT_API .project.tmp.env | sed 's/^I_CLIENT_//' > .project.i_client.tmp.env
grep ^REPORT_GENERATOR .project.tmp.env | sed 's/^REPORT_GENERATOR_//' > .project.renderer.tmp.env
# special default variables
export MYSQL_HOST_DIR=${MYSQL_HOST_DIR:-"/home/dockns-root/mysql_data"}
export DOCKER_REGISTRY=${DOCKER_REGISTRY:-"docker-registry.smarthomedevs.work/issuing"}
export REPLICAS=${REPLICAS:-"1"}
export TAG=${TAG:-"latest"}
export PUBLIC_NODE_IP=${PUBLIC_NODE_IP:-"0.0.0.0"}
# parse secret names from composer
COMPOSER_FILE_ARGS=""
COMPOSER_SWARM_ARGS=""
for COMPOSER in "${COMPOSERS[@]}"; do
COMPOSER_FILE_ARGS+=" -f $COMPOSER"
COMPOSER_SWARM_ARGS+=" -c $COMPOSER"
IFS=$'\n' tag_vars=($(grep "TAG_" $COMPOSER | sed 's/.*\$TAG_/TAG_/'))
for tag_var in "${tag_vars[@]}"; do
if [[ "${!tag_var}" == "" ]]; then
eval "export $tag_var='$TAG'"
fi
done
IFS=$'\n' secret_vars=($(grep "SV_" $COMPOSER | sed 's/.*\.\$//'))
for secret in "${secret_vars[@]}"; do
if [[ "${!secret}" == "" ]]; then
eval "export $secret='0'"
fi
done
done
EXIT=0
# building secret settings
if [ -f "$SECRET_SETTINGS" ]; then
. $SECRET_SETTINGS
fi
if [[ "$COMMAND" == "check" ]]; then
bash -c "docker compose $COMPOSER_FILE_ARGS config"
EXIT=$?
fi
if [[ "$COMMAND" == "deploy" ]]; then
if [ "$STACK_NAME" == "" ]; then
echo ""
echo "STACK_NAME required"
echo ""
usage
fi
if [[ "$DO_UPDATE" == "yes" ]]; then
REGISTRY_AUTH="--with-registry-auth"
else
REGISTRY_AUTH=""
fi
[[ -f "control.sh" ]] && [[ "$NODE_NAME" != "" ]] && eval $(./control.sh $NODE_NAME)
if [[ "$FORCE_DEPLOY" != "1" ]]; then
for cron_part in 'cron' 'schedule'; do
CRON_SERVICE_NAME=$(docker service ls --filter name=${STACK_NAME}_${cron_part} --format '{{.Name}}')
if [[ "$CRON_SERVICE_NAME" != "" ]]; then
break;
fi
done
TASK_SERVICE_NAME=$(docker service ls --filter name=${STACK_NAME}_task_template --format '{{.Name}}')
TASK_CONTAINER_ID=""
if [[ "$TASK_CONTAINER_NAME" != "" ]]; then
TASK_CONTAINER_ID=$(docker ps --filter name="$TASK_SERVICE_NAME" --format '{{.ID}}')
fi
if [[ "$TASK_CONTAINER_ID" != "" ]]; then
docker service scale $CRON_SERVICE_NAME=0 || exit 255
RUNNUNG_TASKS=$(docker exec -it $TASK_CONTAINER_ID ps axuf | grep nameless)
if [[ "$RUNNING_TASKS" != "" ]]; then
echo "Running tasks found! Can't deploy";
exit 255;
fi
fi
if [[ "$CRON_SERVICE_NAME" != "" ]]; then
docker service scale $CRON_SERVICE_NAME=0 || exit 255
fi
if [[ "$TASK_CONTAINER_ID" != "" ]]; then
RUNNUNG_TASKS=$(docker exec -it $TASK_CONTAINER_ID ps axuf | grep nameless)
if [[ "$RUNNING_TASKS" != "" ]]; then
echo "Scheduler is stopped but running tasks found! Can't deploy";
exit 255;
fi
fi
fi
bash -c "docker stack deploy --prune $COMPOSER_SWARM_ARGS $REGISTRY_AUTH $STACK_NAME"
EXIT=$?
if [ $EXIT -ne 0 ]
then
echo "Deploy failed"
exit $EXIT
fi
echo "Waiting for services..."
while true; do
IFS=$'\n' services=($(docker service ls | grep $STACK_NAME | awk '{print $2,$4}'));
if [ $? -ne 0 ]
then
echo "Something went wrong"
exit $?
fi
is_ready=1
all_services=0
bad_services=0
for line in "${services[@]}"
do
all_services=$((all_services+1))
IFS=$' ' service_status=($line)
re="migrate|test_setup"
if ! [[ "${service_status[0]}" =~ $re ]]
then
IFS=$'/' replicas=(${service_status[1]})
if [ ${replicas[0]} -lt ${replicas[1]} ]
then
is_ready=0
bad_services=$((bad_services+1))
fi
fi
done
if [ $is_ready -eq 1 ]
then
break
fi
sleep 5;
echo "Services: $all_services, but $bad_services is not ready yet"
done
echo "Done."
fi
if [[ "$COMMAND" == "run" ]]; then
bash -c "docker compose $COMPOSER_FILE_ARGS down"
if [[ "$DO_UPDATE" == "yes" ]]; then
bash -c "docker compose $COMPOSER_FILE_ARGS pull"
fi
bash -c "docker compose $COMPOSER_FILE_ARGS up -d"
EXIT=$?
fi
if [[ "$COMMAND" == "stop" ]]; then
bash -c "docker compose $COMPOSER_FILE_ARGS down"
EXIT=$?
fi
rm .project*.tmp.env
exit $EXIT