#!/usr/bin/env bash # CONFIG ## Default PROGRAM=`basename $0` docker_cmd=`which docker` CURRENT_DIR=$(pwd) GIT_URL="git@github.com:eost/gissmo.git" GIT_BRANCH="dev" # Default Git Branch GIT_DIR_NAME="gissmo" DOCKERFILE_NAME="Dockerfile" POSTGRES_VERSION="9.5-alpine" POSTGRES_PORT=5433 GISSMO_DOCKER_NAME="gissmo" ## User if test -z "$GISSMO_CFG"; then # No Gissmo Launcher configuration file given. Search one. CONFIG_FILENAME="config" # first in XDG directory, otherwise ~/.config one. if test -z $XDG_CONFIG_HOME; then CONFIG_DEFAULT_DIR="${HOME}/.config/gissmo" else CONFIG_DEFAULT_DIR="${XDG_CONFIG_HOME}" fi CONFIG_FILE="${CONFIG_DEFAULT_DIR}/${CONFIG_FILENAME}" if ! test -f ${CONFIG_FILE}; then CONFIG_FILE="${PWD}/${CONFIG_FILENAME}" if ! test -f ${CONFIG_FILE}; then echo "'config' file not found. Use 'config.example' file and copy it to 'config' one either in ${CONFIG_DEFAULT_DIR}/ or ${PWD}/ directory. Then try again!" exit 1 fi fi else # Gissmo Launcher configuration file is given! Check it. CONFIG_FILE=$GISSMO_CFG if ! test -f $CONFIG_FILE; then echo "Configuration file not found: ${CONFIG_FILE}" exit 1 fi fi . ${CONFIG_FILE} || exit 1 ## Composed GISSMO_DIR="${PROJECT_DIR}/${GIT_DIR_NAME}" DOCKERFILE="${GISSMO_DIR}/${DOCKERFILE_NAME}" # Set DJANGO_VOLUME_DIR if ! test -z "$DJANGO_DIR"; then DJANGO_VOLUME_DIR="${GISSMO_DIR}/$DJANGO_DIR" else DJANGO_VOLUME_DIR="${GISSMO_DIR}" fi ## Miscellaneous COMMAND="$1" shift 1; ARGS="$@" red=`tput setaf 9` green=`tput setaf 2` yellow=`tput setaf 3` blue=`tput setaf 4` violet=`tput setaf 5` cyan=`tput setaf 6` white=`tput setaf 7` reset=`tput sgr0` # No Color # METHODS error_and_continue() { echo "${red}ERROR${reset}: $1" } error_and_quit() { error_and_continue "$1" exit 1 } info() { echo "${yellow}INFO${reset}: $1" } not_implemented() { error_and_quit "Not implemented" } show_help() { echo "$PROGRAM COMMAND [arg ...]" echo -e " Where ${green}COMMAND${reset} is one of:" echo -e " - backup Create a compressed postgreSQL database dump in current directory" echo -e " - create Create postgreSQL Docker container" echo -e " - dev [arg ...] Mount Git repository directory AS VOLUME for Gissmo Docker container and launch it in 'development' mode" echo -e " - init Create project directory as python virtual environment, fetch git repository and install Python dependancies" echo -e " - migrate Launch migration command: python3 manage.py migrate" echo -e " - psql Enter PSQL database via psql command" echo -e " - restore dump Restore the given dump" echo -e " - start [arg ...] Launch Gissmo Docker container (created by 'create' command) with a name given in GISSMO_DOCKER_NAME variable. args is optional." echo -e " - stop Stop Gissmo Docker container which name is GISSMO_DOCKER_NAME variable content" echo "" echo "Use README.md file for more explanations." # TODO: Add clean() command with args to: STOP and DELETE Gissmo container, # STOP and DELETE postgreSQL container, DELETE dbdata OR do all these # things into one. } check_command() { # Allowed commands return 0 to continue. Otherwise show help and exit if test $1 == "backup"; then return 0 elif test $1 == "create"; then return 0 elif test $1 == "dev"; then return 0 elif test $1 == "init"; then return 0 elif test $1 == "psql"; then return 0 elif test $1 == "migrate"; then return 0 elif test $1 == "restore"; then return 0 elif test $1 == "start"; then return 0 elif test $1 == "stop"; then return 0 fi error_and_continue "Unknown command." show_help exit 1 } test_docker_cmd() { if test -z "$docker_cmd"; then error_and_quit "Docker command not found. Install docker or fill in the PATH." fi return 0 } test_postgresql_exists() { PSQL_RUNNING=$($docker_cmd inspect --format="{{ .State.Running }}" ${POSTGRES_DOCKER_NAME} 2> /dev/null) if [ $? -eq 1 ]; then error_and_quit "postgreSQL Docker container not found: ${POSTGRES_DOCKER_NAME}. Please launch '$PROGRAM create' first." fi } test_postgresql_launched() { PSQL_RUNNING=$($docker_cmd inspect --format="{{ .State.Running }}" ${POSTGRES_DOCKER_NAME} 2> /dev/null) if test "$PSQL_RUNNING" == "false"; then return 1 fi return 0 } test_create() { test_docker_cmd if test -z "$DB_DIR"; then error_and_quit "No database directory given (DB_DIR in config file)." fi if test -z "$POSTGRES_VERSION"; then error_and_quit "No postgres version given (POSTGRES_VERSION in config file)." fi if test -z "$POSTGRES_DOCKER_NAME"; then error_and_quit "You need a name for your Docker database container (POSTGRES_DOCKER_NAME in config file)." fi } create() { test_create init $docker_cmd run -d -p ${POSTGRES_PORT}:5432 -v "${DB_DIR}:/var/lib/postgresql/data" --name "${POSTGRES_DOCKER_NAME}" "postgres:${POSTGRES_VERSION}" || error_and_quit "Launching database docker container failed." } dev() { initial_start PORT_PARAM=" -p ${GISSMO_DOCKER_PORT}:8000 " GISSMO_DEV_RUNNING_PORT=$(nc -z 127.0.0.1 ${GISSMO_DOCKER_PORT} &> /dev/null; echo $?) if [ $GISSMO_DEV_RUNNING_PORT -eq 0 ]; then PORT_PARAM=" -P " fi $docker_cmd run -it --rm --link ${POSTGRES_DOCKER_NAME}:db ${PORT_PARAM} -v ${DJANGO_VOLUME_DIR}:/opt/gissmo -v ${UPLOAD_DIR}:/data gissmo:${GISSMO_VERSION} ${ARGS:='development'} || error_and_quit "Failed to create and launch ${GISSMO_DOCKER_NAME} container." } test_backup() { # Check postgreSQL Docker container exists and is launched. test_postgresql_launched if [ $? -eq 1 ]; then $docker_cmd start ${POSTGRES_DOCKER_NAME} fi } backup() { # Check all variables are availables test_create # Then check some specific things for dump method test_backup $docker_cmd run -it --rm --volume $PWD/:/tmp/ --link ${POSTGRES_DOCKER_NAME}:db postgres:${POSTGRES_VERSION} bash -c 'exec pg_dump -F c -h "$DB_PORT_5432_TCP_ADDR" -p "$DB_PORT_5432_TCP_PORT" -U postgres postgres > /tmp/gissmo-`date +"%Y.%m.%d.%H%M"`-'${GISSMO_VERSION}'.dump' || error_and_quit "Failed to backup Gissmo database." } init() { # check directory existence if ! test -d "$PROJECT_DIR"; then mkdir -p "$PROJECT_DIR" || error_and_quit "Create ${PROJECT_DIR} failed." info "$PROJECT_DIR created." echo "${PROJECT_DIR} created." virtualenv -p python3 $PROJECT_DIR || error_and_quit "Create ${PROJECT_DIR} python virtual environment failed." info "Python virtual environment initialized." fi cd "$PROJECT_DIR" # On Fedora 23: gcc postgresql-devel python3-devel python-virtualenv git-core python3-pip redhat-rpm-config gmp-devel # On ArchLinux: base-devel postgresql-libs python python-virtualenv git python-pip sudo apt-get install -qq libpq-dev python3-dev python-virtualenv git-core python3-pip || error_and_quit "Dependancies installation failed." info "Dependancies via apt-get checked/installed." if ! test -d "$GISSMO_DIR/.git/"; then git clone -q -b "$GIT_BRANCH" "$GIT_URL" "$GISSMO_DIR" || error_and_quit "Fetch Git repository failed." else GIT_WORK_TREE="${GISSMO_DIR}/" GIT_DIR="${GISSMO_DIR}/.git/" git pull -q origin ${GIT_BRANCH} || error_and_quit "Pull command on Git repository failed." fi info "Git repository state checked." # install pre-commit hook that check code validity and more (only for 1.9 branchs) if ! test -f "${GISSMO_DIR}/.git/hooks/pre-commit"; then if test -f "${GISSMO_DIR}/scripts/git_hooks/pre-commit"; then cp "${GISSMO_DIR}/scripts/git_hooks/pre-commit" "${GISSMO_DIR}/.git/hooks/pre-commit" || error_and_quit "Failed to install pre-commit hook." info "Git repository pre-commit hook installed." fi fi source bin/activate || error_and_quit "Failed entering python virtual environment" cd "$GISSMO_DIR" pip install -q -r requirements.txt || error_and_quit "Python dependancies installation failed." info "Python dependancies checked." deactivate || error_and_quit "Failed exiting python virtual environment." } test_migrate() { test_initial_start } migrate() { test_migrate $docker_cmd run -it --rm --link ${POSTGRES_DOCKER_NAME}:db gissmo:${GISSMO_VERSION} python3 manage.py migrate || error_and_quit "Failed to launch Gissmo migration." } test_restore() { if test -z $ARGS; then error_and_quit "Missing database dump file" fi if ! test -f "$ARGS"; then error_and_quit "File '${ARGS}' not found." fi DUMP_FILE=`basename $ARGS` info "Dump file found: ${DUMP_FILE}" DUMP_DIR="${ARGS%/*}" if [ -z "$DUMP_DIR" ]; then DUMP_DIR="/" fi } psql() { test_postgresql_launched if [ $? -eq 1 ]; then $docker_cmd start ${POSTGRES_DOCKER_NAME} sleep 4 # wait postgreSQL database to be fully launched fi $docker_cmd run -it --link ${POSTGRES_DOCKER_NAME}:db --rm "postgres:${POSTGRES_VERSION}" sh -c 'exec psql -h "$DB_PORT_5432_TCP_ADDR" -p "$DB_PORT_5432_TCP_PORT" -U postgres' || error_and_quit "Failed to connect to postgreSQL Docker container." } restore() { test_create test_restore $docker_cmd stop ${POSTGRES_DOCKER_NAME} && $docker_cmd rm ${POSTGRES_DOCKER_NAME} || error_and_quit "Failed to stop and delete postgreSQL Docker container: ${POSTGRES_DOCKER_NAME}" sudo rm -rf ${DB_DIR} || error_and_quit "Failed to delete this directory: ${DB_DIR}" $docker_cmd run -d -p ${POSTGRES_PORT}:5432 -v "${DB_DIR}:/var/lib/postgresql/data" --name "${POSTGRES_DOCKER_NAME}" "postgres:${POSTGRES_VERSION}" || error_and_quit "Launching database docker container failed." # Wait postgres was initialized until $docker_cmd run --rm --link ${POSTGRES_DOCKER_NAME}:postgres postgres:${POSTGRES_VERSION} pg_isready -U postgres -h postgres; do sleep 2 done RESTORE_COMMAND="$docker_cmd run -it --rm --link ${POSTGRES_DOCKER_NAME}:db -v ${DUMP_DIR}:/backup -e PGHOST=`$docker_cmd inspect -f \"{{ .NetworkSettings.IPAddress }}\" ${POSTGRES_DOCKER_NAME}` -e PGUSER=postgres postgres:${POSTGRES_VERSION} pg_restore -d postgres /backup/${DUMP_FILE}" exec $RESTORE_COMMAND || error_and_quit "Failed to launch this command: ${CMD}" } test_initial_start() { if test -z "$GISSMO_VERSION"; then error_and_quit "No Gissmo version given (GISSMO_VERSION in config file)." fi if ! test -f "$DOCKERFILE"; then error_and_quit "Docker file don't exists: ${DOCKERFILE}" fi if test -z "$UPLOAD_DIR"; then error_and_quit "No Gissmo upload directory given (UPLOAD_DIR in config file)." fi # Build Gissmo Docker images if missing if [[ "$($docker_cmd images -q gissmo:${GISSMO_VERSION} 2> /dev/null)" == "" ]]; then cd "$GISSMO_DIR" info "Building Docker images…" $docker_cmd build -t gissmo:${GISSMO_VERSION} -f ${DOCKERFILE} . || error_and_quit "Failed to build Gissmo Docker container." info "…done." cd "$CURRENT_DIR" fi if test -z "$GISSMO_DOCKER_PORT"; then error_and_quit "No Gissmo Docker container port given (GISSMO_DOCKER_PORT in config file)." fi test_postgresql_exists } initial_start() { test_initial_start # Check postgreSQL Docker container exists and is launched. test_postgresql_launched if [ $? -eq 1 ]; then $docker_cmd start ${POSTGRES_DOCKER_NAME} fi } start() { initial_start # Run existing Docker container, otherwise create a new one GISSMO_RUNNING=$($docker_cmd inspect --format="{{ .State.Running }}" ${GISSMO_DOCKER_NAME} 2> /dev/null) if [ $? -eq 1 ]; then $docker_cmd run -it --rm --link ${POSTGRES_DOCKER_NAME}:db -p ${GISSMO_DOCKER_PORT}:8000 -e SECRET_KEY="abcdefg" --name ${GISSMO_DOCKER_NAME} -v ${UPLOAD_DIR}:/data gissmo:${GISSMO_VERSION} $ARGS || error_and_quit "Failed to create and launch ${GISSMO_DOCKER_NAME} container." else error_and_quit "${GISSMO_DOCKER_NAME} is already launched! If you need another name please set GISSMO_DOCKER_NAME in configuration file." fi } test_stop(){ GISSMO_RUNNING=$($docker_cmd inspect --format="{{ .State.Running }}" ${GISSMO_DOCKER_NAME}) if [ $? -eq 1 ]; then error_and_quit "Gissmo Docker container not found: ${GISSMO_DOCKER_NAME}. Please launch '$PROGRAM launch' first." fi } stop() { $docker_cmd stop $GISSMO_DOCKER_NAME || error_and_quit "Failed to stop $GISSMO_DOCKER_NAME Docker container." info "${GISSMO_DOCKER_NAME} Docker container stopped successfully." } # CHECK CONFIG if test -z $PROJECT_DIR; then error_and_quit "No project directory given." fi if test -z $GIT_BRANCH; then error_and_quit "No git branch given." fi # Don't check repository if INIT COMMAND is given if ! test -d $GIT_REPOSITORY && ! test "$COMMAND" == "init"; then error_and_quit "Repository don't exists: ${GIT_REPOSITORY}" fi if test -z $DOCKERFILE_NAME; then error_and_quit "No docker filename given." fi if ! test -z $COMMAND; then check_command "$COMMAND" $COMMAND else show_help fi exit 0