diff --git a/kickstart.sh b/kickstart.sh index 5069010..e2f70d8 100755 --- a/kickstart.sh +++ b/kickstart.sh @@ -1,21 +1,45 @@ #!/bin/bash # -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -# DO NOT EDIT THIS FILE! CHANGES WILL BE OVERWRITTEN ON UPDATE -# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# DO NOT EDIT THIS FILE! CHANGES WILL BE OVERWRITTEN ON UPDATE +# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # -# Ready to use development containers. Just run ./kickstart.sh to start -# a development environment for this project. +# Ready to use development containers. Just run ./kickstart.sh to start a development +# environment for this project. # # Config-File: .kick.yml +# Website....: https://infracamp.org/getting-started/ +# Author.....: Matthias Leuffen # -# Kickstart home: https://github.com/c7lab/kickstart -# -# Author: Matthias Leuffen -# +################################################################################################ +### DON'T CHANGE ANY VARIABLES HERE --- see ~/.kickstartconfig or ./.kickstartconfig instead ### +################################################################################################ + +## +KICKSTART_DOCKER_OPTS="" + +# Optinal parameters for docker run (e.g. -v /some/host/path:/path) +KICKSTART_DOCKER_RUN_OPTS="" + +# External Port bindings +KICKSTART_PORTS="80:80/tcp;4000:4000/tcp;4100:4100/tcp;4200:4200/tcp;4000:4000/udp" + +# 1 = Don't try to download the images from the internet +OFFLINE_MODE=0 + +# Specify the container name by yourself (switch of auto-detection) +CONTAINER_NAME= + +# The image (e.g. infracamp/kickstart-flavor-base:testing) specified in .kick.yml from:-section +FROM_IMAGE= + +############################ +### CODE BELOW ### +############################ # Error Handling. +set -o errtrace trap 'on_error $LINENO' ERR; PROGNAME=$(basename $0) PROGPATH="$( cd "$(dirname "$0")" ; pwd -P )" # The absolute path to kickstart.sh @@ -27,25 +51,48 @@ function on_error () { +KICKSTART_HOST_IP=$(hostname -i | awk '{print $1;}') +if [ "$KICKSTART_HOST_IP" == "" ] +then + # Workaround for systems not supporting hostname -i (MAC) + # See doc/workaround-plattforms.md for more about this + KICKSTART_HOST_IP=$(host `hostname`|awk '{print $NF}') +fi; + + + + + + CONTAINER_NAME=${PWD##*/} +if test -t 1; then + # see if it supports colors... + ncolors=$(tput colors) + if test -n "$ncolors" && test $ncolors -ge 8; then + export COLOR_NC='\e[0m' # No Color + export COLOR_WHITE='\e[1;37m' + export COLOR_BLACK='\e[0;30m' + export COLOR_BLUE='\e[0;34m' + export COLOR_LIGHT_BLUE='\e[1;34m' + export COLOR_GREEN='\e[0;32m' + export COLOR_LIGHT_GREEN='\e[1;32m' + export COLOR_CYAN='\e[0;36m' + export COLOR_LIGHT_CYAN='\e[1;36m' + export COLOR_RED='\e[0;31m' + export COLOR_LIGHT_RED='\e[1;31m' + export COLOR_PURPLE='\e[0;35m' + export COLOR_LIGHT_PURPLE='\e[1;35m' + export COLOR_BROWN='\e[0;33m' + export COLOR_YELLOW='\e[1;33m' + export COLOR_GRAY='\e[0;30m' + export COLOR_LIGHT_GRAY='\e[0;37m' + fi; +fi; + + +KICKSTART_CACHE_DIR="$HOME/.kick_cache" +mkdir -p $KICKSTART_CACHE_DIR -export COLOR_NC='\e[0m' # No Color -export COLOR_WHITE='\e[1;37m' -export COLOR_BLACK='\e[0;30m' -export COLOR_BLUE='\e[0;34m' -export COLOR_LIGHT_BLUE='\e[1;34m' -export COLOR_GREEN='\e[0;32m' -export COLOR_LIGHT_GREEN='\e[1;32m' -export COLOR_CYAN='\e[0;36m' -export COLOR_LIGHT_CYAN='\e[1;36m' -export COLOR_RED='\e[0;31m' -export COLOR_LIGHT_RED='\e[1;31m' -export COLOR_PURPLE='\e[0;35m' -export COLOR_LIGHT_PURPLE='\e[1;35m' -export COLOR_BROWN='\e[0;33m' -export COLOR_YELLOW='\e[1;33m' -export COLOR_GRAY='\e[0;30m' -export COLOR_LIGHT_GRAY='\e[0;37m' if [ "$DEV_CONTAINER_NAME" != "" ] then @@ -74,11 +121,30 @@ _KICKSTART_CURRENT_VERSION="1.2.0" # KICKSTART_WIN_PATH="" -# Publish ports - separated by semikolon (define it in .kickstartconfig) -KICKSTART_PORTS="80:80/tcp;4000:4000/tcp;4100:4100/tcp;4200:4200/tcp;4000:4000/udp" +if [ ! -f "$PROGPATH/.kick.yml" ] +then + echo -e $COLOR_RED "[ERR] Missing $PROGPATH/.kick.yml file." $COLOR_NC + ask_user "Do you want to create a new .kick.yml-file?" + echo "# Kickstart container config file - see https://gitub.com/infracamp/kickstart" > $PROGPATH/.kick.yml + echo "# Run ./kickstart.sh to start a development-container for this project" >> $PROGPATH/.kick.yml + echo "version: 1" >> $PROGPATH/.kick.yml + echo 'from: "infracamp/kickstart-flavor-base"' >> $PROGPATH/.kick.yml + echo "File created. See $_KICKSTART_DOC_URL for more information"; + echo "" + echo "You can now run ./kickstart.sh to start the container" + sleep 2 + exit 6 +fi + -KICKSTART_DOCKER_OPTS="" -KICKSTART_DOCKER_RUN_OPTS="" + +# Parse .kick.yml for line from: "docker/container:version" +FROM_IMAGE=`cat $PROGPATH/.kick.yml | grep "^from:" | tr -d '"' | awk '{print $2}'` +if [ "$FROM_IMAGE" == "" ] +then + echo -e $COLOR_RED "[ERR] .kick.yml file does not include 'from:' - directive." $COLOR_NC + exit 2 +fi; if [ -e "$HOME/.kickstartconfig" ] then @@ -94,37 +160,45 @@ then . $PROGPATH/.kickstartconfig fi - +terminal="-it" +if [ ! -t 1 ] +then + # Switch to non-interactive terminal (ci-build etc) + terminal="-t" +fi; _usage() { - echo -e $COLOR_NC "Usage: $0 [] + echo -e $COLOR_NC "Usage: $0 [] [] COMMANDS: - $0 [dev|] - Run kick and start bash inside container (development mode) + $0 :[command] [command2...] + Execute kick and return (development mode) - $0 run - Execute kick and return (unit-testing) + $0 ci-build + Build the service and push to gitlab registry (gitlab_ci_runner) - $0 build - Build a standalone container + $0 skel list|install [name] + List / Install a skeleton project (see http://github.com/infracamp/kickstart-skel) - $0 test - Execute kick test + $0 skel upgrade + Upgrade to the latest kickstart version - $0 --ci-build - Build the service and push to gitlab registry (gitlab_ci_runner) + $0 wakeup + Try to start a previous image with same container name (faster startup) EXAMPLES $0 Just start a shell inside the container (default development usage) - $0 run test Execute commands defined in section 'test' of .kick.yml + $0 :test Execute commands defined in section 'test' of .kick.yml + $0 :debug Execute the container in debug-mode (don't execute kick-commands) ARGUMENTS + -h Show this help -t --tag= Run container with this tag (development) -u --unflavored Run the container whithout running any scripts (develpment) - --upgrade Search / Install new kickstart version + --offline Do not pull images nor ask for version upgrades + --no-tty Disable interactive tty " exit 1 @@ -149,11 +223,11 @@ _print_header() { +-------------------------------------------------------------------------------------------------------+ | Infracamp's Kickstart - DEVELOPER MODE | | Version: $_KICKSTART_CURRENT_VERSION -| Flavour: $USE_PIPF_VERSION (defined in 'from:'-section of .kick.yml)" +| Flavour: $FROM_IMAGE (defined in 'from:'-section of .kick.yml)" - KICKSTART_NEWEST_VERSION=`curl -s "$_KICKSTART_VERSION_URL"` + KICKSTART_NEWEST_VERSION=`curl -s "$_KICKSTART_VERSION_URL"` || true if [ "$KICKSTART_NEWEST_VERSION" != "$_KICKSTART_CURRENT_VERSION" ] then echo "| " @@ -172,14 +246,20 @@ _print_header() { run_shell() { echo -e $COLOR_CYAN; - - - if [ `docker ps | grep $CONTAINER_NAME | wc -l` -gt 0 ] + if [ `docker ps | grep "$CONTAINER_NAME\$" | wc -l` -gt 0 ] then echo "[kickstart.sh] Container '$CONTAINER_NAME' already running" echo "Starting shell... (please press enter)" echo ""; - docker exec -it --user user -e "DEV_TTYID=[SUB]" $CONTAINER_NAME /bin/bash + + shellarg="/bin/bash" + if [ "$ARGUMENT" != "" ] + then + shellarg="kick $ARGUMENT" + fi; + + docker exec $terminal --user user -e "DEV_TTYID=[SUB]" $CONTAINER_NAME $shellarg + echo -e $COLOR_CYAN; echo "<=== [kickstart.sh] Leaving container." echo -e $COLOR_NC @@ -189,16 +269,17 @@ run_shell() { echo "[kickstart.s] Another container is already running!" docker ps echo "" - read -r -p "Your choice: (i)gnore, (s)hell, (k)ill, (a)bort?:" choice + read -r -p "Your choice: (i)gnore/run anyway, (s)hell, (k)ill, (a)bort?:" choice case "$choice" in i|I) + run_container return 0; ;; s|S) echo "===> [kickstart.sh] Opening new shell: " echo -e $COLOR_NC - docker exec -it --user user -e "DEV_TTYID=[SUB]" `docker ps | grep "/kickstart/" | cut -d" " -f1` /bin/bash + docker exec $terminal --user user -e "DEV_TTYID=[SUB]" `docker ps | grep "/kickstart/" | cut -d" " -f1` /bin/bash echo -e $COLOR_CYAN; echo "<=== [kickstart.sh] Leaving container." @@ -263,40 +344,16 @@ _ci_build() { DOCKER_OPT_PARAMS=$KICKSTART_DOCKER_RUN_OPTS; -if [ -e "$HOME/.ssh" ] -then - echo "Mounting $HOME/.ssh..." - DOCKER_OPT_PARAMS="$DOCKER_OPT_PARAMS -v $HOME/.ssh:/home/user/.ssh"; -fi - -if [ -e "$HOME/.gitconfig" ] -then - echo "Mounting $HOME/.gitconfig..." - DOCKER_OPT_PARAMS="$DOCKER_OPT_PARAMS -v $HOME/.gitconfig:/home/user/.gitconfig"; -fi - -if [ -e "$HOME/.bash_history" ] -then - echo "Mounting $HOME/.bash_history..." - DOCKER_OPT_PARAMS="$DOCKER_OPT_PARAMS -v $HOME/.bash_history:/home/user/.bash_history"; -fi - -if [ -e "$PROGPATH/.env" ] -then - echo "Adding docker environment from $PROGPATH/.env (Development only)" - DOCKER_OPT_PARAMS="$DOCKER_OPT_PARAMS --env-file $PROGPATH/.env"; -fi -# Ports to be exposed -IFS=';' read -r -a _ports <<< "$KICKSTART_PORTS" -for _port in "${_ports[@]}" -do - DOCKER_OPT_PARAMS="$DOCKER_OPT_PARAMS -p $_port" -done run_container() { - echo -e $COLOR_GREEN"Loading container '$USE_PIPF_VERSION'..." - docker pull "$USE_PIPF_VERSION" + echo -e $COLOR_GREEN"Loading container '$FROM_IMAGE'..." + if [ "$OFFLINE_MODE" == "0" ] + then + docker pull "$FROM_IMAGE" + else + echo -e $COLOR_RED "OFFLINE MODE! Not pulling image from registy. " $COLOR_NC + fi; if [ "$KICKSTART_WIN_PATH" != "" ] then @@ -305,20 +362,45 @@ run_container() { PROGPATH="${PROGPATH/\/mnt\/c\//$KICKSTART_WIN_PATH}" fi - docker rm $CONTAINER_NAME + docker rm $CONTAINER_NAME || true echo -e $COLOR_WHITE "==> [$0] STARTING CONTAINER (docker run): Running container in dev-mode..." $COLOR_NC - cmd="docker $KICKSTART_DOCKER_OPTS run -it \ + + + _STACKFILE="$PROGPATH/.kick-stack.yml" + if [ -e "$_STACKFILE" ]; then + _STACK_NETWORK_NAME=$CONTAINER_NAME + + echo "Startin in stack mode... (network: '$_STACK_NETWORK_NAME')" + _NETWORKS=$(docker network ls | grep $_STACK_NETWORK_NAME | wc -l) + echo nets: $_NETWORKS + if [ $_NETWORKS -eq 0 ]; then + docker swarm init + docker network create --attachable -d overlay $_STACK_NETWORK_NAME + fi; + + docker stack deploy --prune -c $_STACKFILE $CONTAINER_NAME + DOCKER_OPT_PARAMS="$DOCKER_OPT_PARAMS --network $_STACK_NETWORK_NAME" + fi; + + + dev_uid=$UID + if [ ! -t 1 ] + then + # Switch to non-interactive terminal (ci-build etc) + dev_uid=1000 + fi; + + cmd="docker $KICKSTART_DOCKER_OPTS run $terminal \ -v \"$PROGPATH/:/opt/\" \ -e \"DEV_CONTAINER_NAME=$CONTAINER_NAME\" \ -e \"DEV_TTYID=[MAIN]\" \ - -e \"DEV_UID=$UID\" \ - -e \"LINES=$LINES\" \ - -e \"COLUMNS=$COLUMNS\" \ + -e \"DEV_UID=$dev_uid\" \ + -e \"DOCKER_HOST_IP=$KICKSTART_HOST_IP\" \ -e \"TERM=$TERM\" \ -e \"DEV_MODE=1\" \ $DOCKER_OPT_PARAMS \ --name $CONTAINER_NAME \ - $USE_PIPF_VERSION $ARGUMENT" + $FROM_IMAGE $ARGUMENT" echo [exec] $cmd eval $cmd @@ -336,39 +418,26 @@ run_container() { } -if [ ! -f "$PROGPATH/.kick.yml" ] -then - echo -e $COLOR_RED "[ERR] Missing $PROGPATH/.kick.yml file." $COLOR_NC - ask_user "Do you want to create a new .kick.yml-file?" - echo "# Kickstart container config file - see https://gitub.com/c7lab/kickstart" > $PROGPATH/.kick.yml - echo "# Run ./kickstart.sh to start a development-container for this project" >> $PROGPATH/.kick.yml - echo "version: 1" >> $PROGPATH/.kick.yml - echo 'from: "infracamp/kickstart-flavor-gaia"' >> $PROGPATH/.kick.yml - echo "File created. See $_KICKSTART_DOC_URL for more information"; - echo "" - sleep 2 -fi - - - -# Parse .kick.yml for line from: "docker/container:version" -USE_PIPF_VERSION=`cat $PROGPATH/.kick.yml | sed -n 's/from\: "\(.\+\)\"/\1/p'` - -if [ "$USE_PIPF_VERSION" == "" ] -then - echo -e $COLOR_RED "[ERR] .kick.yml file does not include 'from:' - directive." $COLOR_NC - exit 2 -fi; +ARGUMENT=""; # Parse the command parameters ARGUMENT=""; while [ "$#" -gt 0 ]; do case "$1" in -t) USE_PIPF_VERSION="-t $2"; shift 2;; - --tag=*) USE_PIPF_VERSION="-t ${1#*=}"; shift 1;; + --tag=*) + USE_PIPF_VERSION="-t ${1#*=}"; shift 1;; + + --offline) + OFFLINE_MODE=1; shift 1;; - --upgrade) + --no-tty) + echo "Disabling interactive terminal" + terminal="" + shift 1;; + + upgrade|--upgrade) echo "Checking for updates from $_KICKSTART_UPGRADE_URL..." curl "$_KICKSTART_RELEASE_NOTES_URL" @@ -385,32 +454,91 @@ while [ "$#" -gt 0 ]; do --on-after-upgrade) exit 0;; - --skel) - ask_user "Do you want to overwrite existing files with skeleton?" - curl https://codeload.github.com/infracamp/kickstart-skel/tar.gz/master | tar -xzv --strip-components=2 kickstart-skel-master/$2/ -C ./ + wakeup) + docker start -ai $CONTAINER_NAME + exit 0;; + + skel) + if [ "$2" == "install" ] + then + ask_user "Do you want to overwrite existing files with skeleton?" + curl https://codeload.github.com/infracamp/kickstart-skel/tar.gz/master | tar -xzv --strip-components=2 kickstart-skel-master/$3/ -C ./ + exit 0; + fi; + + if [ "$2" == "" ] || [ "$2" == "list" ] + then + echo "------ List of available skeleton projects -------" + curl https://raw.githubusercontent.com/infracamp/kickstart-skel/master/skel.index.txt + echo "" + echo "--------------------------------------------------" + echo "Install a skeleton: $0 skel install " + echo ""; + else + echo "Unknown command: Available: $0 --skel list|install " + exit 1 + fi exit 0;; - --ci-build) + ci-build|--ci-build) _ci_build $2 $3 exit0;; - -h|--help) + help|-h|--help) _usage exit 0;; --tag) echo "$1 requires an argument" >&2; exit 1;; - -*) echo "unknown option: $1" >&2; exit 1;; + :*) + ARGUMENT="${1:1} ${@:2}" + break;; - *) break; + -*) echo "unknown option: $1" >&2; exit 1;; + *) + echo "invalid command: $1 - see $0 help for more information" >&2; exit 2;; esac done -ARGUMENT=$@; +if [ -e "$HOME/.ssh" ] +then + echo "Mounting $HOME/.ssh..." + DOCKER_OPT_PARAMS="$DOCKER_OPT_PARAMS -v $HOME/.ssh:/home/user/.ssh"; +fi + +if [ -e "$HOME/.gitconfig" ] +then + echo "Mounting $HOME/.gitconfig..." + DOCKER_OPT_PARAMS="$DOCKER_OPT_PARAMS -v $HOME/.gitconfig:/home/user/.gitconfig"; +fi + +if [ -e "$HOME/.bash_history" ] +then + echo "Mounting $HOME/.bash_history..." + DOCKER_OPT_PARAMS="$DOCKER_OPT_PARAMS -v $HOME/.bash_history:/home/user/.bash_history"; +fi + +if [ -e "$PROGPATH/.env" ] +then + echo "Adding docker environment from $PROGPATH/.env (Development only)" + DOCKER_OPT_PARAMS="$DOCKER_OPT_PARAMS --env-file $PROGPATH/.env"; +fi + +# Ports to be exposed +IFS=';' read -r -a _ports <<< "$KICKSTART_PORTS" +for _port in "${_ports[@]}" +do + DOCKER_OPT_PARAMS="$DOCKER_OPT_PARAMS -p $_port" +done + +DOCKER_OPT_PARAMS="$DOCKER_OPT_PARAMS -v $KICKSTART_CACHE_DIR:/mnt/.kick_cache" + + + _print_header if [ `docker ps | grep "/kickstart/" | wc -l` -gt 0 ] then run_shell fi; -run_container \ No newline at end of file +run_container