#!/bin/bash usage() { cat <&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