Bump base image
[discourse_docker.git] / launcher
index d45b7133eb04a8751c98cf335a196a1c78cc411e..8d8a1489011174dee6682e42fe89ff554b07172e 100755 (executable)
--- a/launcher
+++ b/launcher
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
 usage () {
   echo "Usage: launcher COMMAND CONFIG [--skip-prereqs] [--docker-args STRING]"
@@ -13,6 +13,7 @@ usage () {
   echo "    run:         Run the given command with the config in the context of the last bootstrapped image"
   echo "    rebuild:     Rebuild a container (destroy old, bootstrap, start new)"
   echo "    cleanup:     Remove all containers that have stopped for > 24 hours"
+  echo "    start-cmd:   Generate docker command used to start container"
   echo
   echo "Options:"
   echo "    --skip-prereqs             Don't check launcher prerequisites"
@@ -24,7 +25,13 @@ usage () {
 
 command=$1
 config=$2
+
+# user_args_argv is assigned once when the argument vector is parsed.
+user_args_argv=""
+# user_args is mutable:  its value may change when templates are parsed.
+# Superset of user_args_argv.
 user_args=""
+
 user_run_image=""
 
 if [[ $command == "run" ]]; then
@@ -43,7 +50,8 @@ while [ ${#} -gt 0 ]; do
     SKIP_MAC_ADDRESS="1"
     ;;
   --docker-args)
-    user_args="$2"
+    user_args_argv="$2"
+    user_args="$user_args_argv"
     shift
     ;;
   --run-image)
@@ -80,8 +88,8 @@ git_rec_version='1.8.0'
 config_file=containers/"$config".yml
 cidbootstrap=cids/"$config"_bootstrap.cid
 local_discourse=local_discourse
-image=discourse/base:2.0.20181031
-docker_path=`which docker.io || which docker`
+image="discourse/base:2.0.20190901-2315"
+docker_path=`which docker.io 2> /dev/null || which docker`
 git_path=`which git`
 
 if [ "${SUPERVISED}" = "true" ]; then
@@ -152,9 +160,9 @@ check_prereqs() {
   fi
 
   # 2. running an approved storage driver?
-  if ! $docker_path info 2> /dev/null | egrep -q '^Storage Driver: (aufs|btrfs|zfs|overlay|overlay2)$'; then
+  if ! $docker_path info 2> /dev/null | egrep -q 'Storage Driver: (aufs|zfs|overlay2)$'; then
     echo "Your Docker installation is not using a supported storage driver.  If we were to proceed you may have a broken install."
-    echo "aufs is the recommended storage driver, although zfs/btrfs/overlay and overlay2 may work as well."
+    echo "aufs is the recommended storage driver, although zfs and overlay2 may work as well."
     echo "Other storage drivers are known to be problematic."
     echo "You can tell what filesystem you are using by running \"docker info\" and looking at the 'Storage Driver' line."
     echo
@@ -222,12 +230,14 @@ check_prereqs() {
     echo "You have less than 5GB of free space on the disk where $safe_folder is located. You will need more space to continue"
     df -h $safe_folder
     echo
-    read -p "Would you like to attempt to recover space by cleaning docker images and containers in the system?(y/N)" -n 1 -r
-    echo
-    if [[ $REPLY =~ ^[Yy]$ ]]
-    then
-      docker system prune
-      echo "If the cleanup was successful, you may try again now"
+    if tty >/dev/null; then
+      read -p "Would you like to attempt to recover space by cleaning docker images and containers in the system?(y/N)" -n 1 -r
+      echo
+      if [[ $REPLY =~ ^[Yy]$ ]]
+      then
+        $docker_path system prune -af
+        echo "If the cleanup was successful, you may try again now"
+      fi
     fi
     exit 1
   fi
@@ -353,7 +363,7 @@ RUBY
       if [ "$i" == "*ERROR." ]; then
         ok=0
       elif [ -n "$i" ]; then
-        env[${#env[@]}]=$(echo $i | sed s/{{config}}/${config}/g)
+        env[${#env[@]}]="${i//\{\{config\}\}/${config}}"
       fi
     done <<< "$raw"
 
@@ -363,11 +373,11 @@ RUBY
       exit 1
     fi
 
+    # labels
     read -r -d '' labels_ruby << 'RUBY'
     require 'yaml'
 
     input=STDIN.readlines.join
-    # default to UTF-8 for the dbs sake
     labels = {}
     input.split('_FILE_SEPERATOR_').each do |yml|
        yml.strip!
@@ -406,34 +416,60 @@ RUBY
       echo "YAML syntax error. Please check your containers/*.yml config files."
       exit 1
     fi
-}
 
-if [ -z $docker_path ]; then
-  install_docker
-fi
+    # expose
+    read -r -d '' ports_ruby << 'RUBY'
+    require 'yaml'
 
-[ "$command" == "cleanup" ] && {
-  echo
-  echo "The following command will"
-  echo "- Delete all docker images for old containers"
-  echo "- Delete all stopped and orphan containers"
-  echo
-  read -p "Are you sure (Y/n): " -n 1 -r && echo
-  if [[ $REPLY =~ ^[Yy]$ || ! $REPLY ]]
-    then
-      space=$(df /var/lib/docker | awk '{ print $4 }' | grep -v Available)
-      echo "Starting Cleanup (bytes free $space)"
+    input=STDIN.readlines.join
+    ports = []
+    input.split('_FILE_SEPERATOR_').each do |yml|
+       yml.strip!
+       begin
+         ports += (YAML.load(yml)['expose'] || [])
+       rescue Psych::SyntaxError => e
+        puts e
+        puts "*ERROR."
+       rescue => e
+        puts yml
+        p e
+       end
+    end
+    puts ports.map { |p| p.to_s.include?(':') ? "-p\n#{p}" : "--expose\n#{p}" }.join("\n")
+RUBY
 
-      STATE_DIR=./.gc-state scripts/docker-gc
+    tmp_input_file=$(mktemp)
 
-      rm -f shared/standalone/log/var-log/*.txt
+    echo "$input" > "$tmp_input_file"
+    raw=`exec cat "$tmp_input_file" | $docker_path run $user_args --rm -i -a stdin -a stdout $image ruby -e "$ports_ruby"`
 
-      space=$(df /var/lib/docker | awk '{ print $4 }' | grep -v Available)
-      echo "Finished Cleanup (bytes free $space)"
+    rm -f "$tmp_input_file"
 
-    else
+    ports=()
+    ok=1
+    while read i; do
+      if [ "$i" == "*ERROR." ]; then
+        ok=0
+      elif [ -n "$i" ]; then
+        ports[${#ports[@]}]=$i
+      fi
+    done <<< "$raw"
+
+    if [ "$ok" -ne 1 ]; then
+      echo "${ports[@]}"
+      echo "YAML syntax error. Please check your containers/*.yml config files."
       exit 1
-  fi
+    fi
+
+   merge_user_args
+}
+
+if [ -z $docker_path ]; then
+  install_docker
+fi
+
+[ "$command" == "cleanup" ] && {
+  $docker_path system prune -a
 
   if [ -d /var/discourse/shared/standalone/postgres_data_old ]; then
     echo
@@ -480,6 +516,7 @@ run_stop() {
        )
      else
        echo "$config was not started !"
+       echo "./discourse-doctor may help diagnose the problem."
        exit 1
   fi
 }
@@ -510,35 +547,43 @@ set_boot_command() {
   fi
 }
 
+merge_user_args() {
+  local docker_args
+
+  docker_args=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
+          "require 'yaml'; puts YAML.load(STDIN.readlines.join)['docker_args']"`
+
+  if [[ -n "$docker_args" ]]; then
+    user_args="$user_args_argv $docker_args"
+  fi
+}
+
 run_start() {
 
-   existing=`$docker_path ps | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
-   echo $existing
-   if [ ! -z $existing ]
+   if [ -z "$START_CMD_ONLY" ]
    then
-     echo "Nothing to do, your container has already started!"
-     exit 0
-   fi
+     existing=`$docker_path ps | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
+     echo $existing
+     if [ ! -z $existing ]
+     then
+       echo "Nothing to do, your container has already started!"
+       exit 0
+     fi
 
-   existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
-   if [ ! -z $existing ]
-   then
-     echo "starting up existing container"
-     (
-       set -x
-       $docker_path start $config
-     )
-     exit 0
+     existing=`$docker_path ps -a | awk '{ print $1, $(NF) }' | grep " $config$" | awk '{ print $1 }'`
+     if [ ! -z $existing ]
+     then
+       echo "starting up existing container"
+       (
+         set -x
+         $docker_path start $config
+       )
+       exit 0
+     fi
    fi
 
    host_run
 
-   ports=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
-         "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| \"-p #{p}\"}.join(' ')"`
-
-   docker_args=`cat $config_file | $docker_path run $user_args --rm -i -a stdout -a stdin $image ruby -e \
-          "require 'yaml'; puts YAML.load(STDIN.readlines.join)['docker_args']"`
-
    set_template_info
    set_volumes
    set_links
@@ -575,9 +620,14 @@ run_start() {
       mac_address="--mac-address $($docker_path run $user_args -i --rm -a stdout -a stderr $image /bin/sh -c "echo $hostname | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'")"
      fi
 
+     if [ ! -z "$START_CMD_ONLY" ] ; then
+       docker_path="true"
+     fi
+
      set -x
+
      $docker_path run --shm-size=512m $links $attach_on_run $restart_policy "${env[@]}" "${labels[@]}" -h "$hostname" \
-        -e DOCKER_HOST_IP="$docker_ip" --name $config -t $ports $volumes $mac_address $docker_args $user_args \
+        -e DOCKER_HOST_IP="$docker_ip" --name $config -t "${ports[@]}" $volumes $mac_address $user_args \
         $run_image $boot_command
 
    )
@@ -660,7 +710,8 @@ run_bootstrap() {
 
     $docker_path rm `cat $cidbootstrap`
     rm $cidbootstrap
-    echo "** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one"
+    echo "** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one."
+    echo "./discourse-doctor may help diagnose the problem."
     exit 1
   fi
 
@@ -703,6 +754,12 @@ case "$command" in
       exit 0
       ;;
 
+  start-cmd)
+    START_CMD_ONLY="1"
+    run_start
+    exit 0;
+    ;;
+
   start)
       run_start
       exit 0
@@ -714,9 +771,9 @@ case "$command" in
 
         git remote update
 
-        LOCAL=$(git rev-parse @)
+        LOCAL=$(git rev-parse HEAD)
         REMOTE=$(git rev-parse @{u})
-        BASE=$(git merge-base @ @{u})
+        BASE=$(git merge-base HEAD @{u})
 
         if [ $LOCAL = $REMOTE ]; then
           echo "Launcher is up-to-date"