add test that ensures bootstrap can not run when postgres is running
[discourse_docker.git] / launcher
index 189942b6579604716fdcc51ba36cb10c96ffae3b..7b107a1974a41a3b0331c4f790f1b4a4a8bf80d9 100755 (executable)
--- a/launcher
+++ b/launcher
-#/bin/bash
+#!/bin/bash
 
 command=$1
 config=$2
-config_file=shared/config/"$config"/conf.yml
+config_file=containers/"$config".yml
 cidfile=cids/"$config".cid
 cidbootstrap=cids/"$config"_boostrap.cid
-
+local_discourse=local_discourse
 image=samsaffron/discourse
+docker_path=`which docker`
 
-[ $# -ne 2 ] && {
+docker_ip=`/sbin/ifconfig | \
+                grep -B1 "inet addr" | \
+                awk '{ if ( $1 == "inet" ) { print $2 } else if ( $2 == "Link" ) { printf "%s:" ,$1 } }' | \
+                grep docker0 | \
+                awk -F: '{ print $3 }';`
+
+
+usage () {
   echo "Usage: launcher COMMAND CONFIG"
   echo "Commands:"
   echo "    start:      Start/initialize a container"
   echo "    stop:       Stop a running container"
   echo "    restart:    Restart a container"
   echo "    destroy:    Stop and remove a container"
-  echo "    shell:      Start a bash shell in a running container"
+  echo "    ssh:        Start a bash shell in a running container"
   echo "    logs:       Docker logs for container"
-  echo "    bootstrap:  Bootstrap a container for the config base on an image"
+  echo "    bootstrap:  Bootstrap a container for the config based on a template"
   exit 1
 }
 
+install_docker() {
+
+  echo "Docker is not installed, make sure you are running on the 3.8 kernel"
+  echo "The best supported Docker release is Ubuntu 12.04.03 for it run the following"
+  echo
+  echo "sudo apt-get update"
+  echo "sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring"
+  echo "sudo reboot"
+  echo
+
+  echo "sudo sh -c \"wget -qO- https://get.docker.io/gpg | apt-key add -\""
+  echo "sudo sh -c \"echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list\""
+  echo "sudo apt-get update"
+  echo "sudo apt-get install lxc-docker"
+
+  exit 1
+}
+
+set_volumes() {
+  volumes=`cat $config_file | docker run -rm -i -a stdout -a stdin $image ruby -e \
+        "require 'yaml'; puts YAML.load(STDIN.readlines.join)['volumes'].map{|v| '-v ' << v['volume']['host'] << ':' << v['volume']['guest'] << ' '}.join"`
+}
+
+set_template_info() {
+
+    templates=`cat $config_file | docker run -rm -i -a stdin -a stdout $image ruby -e \
+      "require 'yaml'; puts YAML.load(STDIN.readlines.join)['templates']"`
+
+
+    arrTemplates=(${templates// / })
+    config_data=$(cat $config_file)
+
+    input="hack: true"
+
+
+    for template in "${arrTemplates[@]}"
+    do
+      [ ! -z $template ] && {
+        input="$input _FILE_SEPERATOR_ $(cat $template)"
+      }
+    done
+
+    # we always want our config file last so it takes priority
+    input="$input _FILE_SEPERATOR_ $config_data"
+
+    read -r -d '' env_ruby << 'RUBY'
+    require 'yaml'
+
+    input=STDIN.readlines.join
+    env = {}
+    input.split('_FILE_SEPERATOR_').each do |yml|
+       yml.strip!
+       begin
+         env.merge!(YAML.load(yml)['env'] || {})
+       rescue => e
+        puts yml
+        p e
+       end
+    end
+    puts env.map{|k,v| "-e #{k}=#{v}" }.join(" ")
+RUBY
+
+    env=`exec echo "$input" | docker run -rm -i -a stdin -a stdout $image ruby -e "$env_ruby"`
+    echo "Calculated ENV: $env"
+}
+
+[ -z $docker_path ] && {
+  install_docker
+}
+
+
+[ $# -ne 2 ] && {
+  usage
+}
+
 if [ ! -e $config_file ]
   then
     echo "Config file was not found, ensure $config_file exists"
     exit 1
 fi
 
-if [ "$command" == "bootstrap" ]
-  then
-  docker run -cidfile $cidbootstrap -i -t -v `pwd`/shared:/shared samsaffron/discourse /shared/pups/bin/pups /$config_file
-  docker commit `cat $cidbootstrap` samsaffron/discourse $config
-  docker rm `cat $cidbootstrap`
-  rm $cidbootstrap
-fi
+case "$command" in
+  bootstrap)
 
-if [ "$command" == "shell" ]
-  then
+      set_template_info
 
-    if [ ! -e $cidfile ]
-       then
-         echo "No cid found"
-         exit 1
-       else
-         docker attach `cat $cidfile`
-         exit 0
-    fi
-fi
+      base_image=`cat $config_file | docker run -rm -i -a stdin -a stdout $image ruby -e \
+        "require 'yaml'; puts YAML.load(STDIN.readlines.join)['base_image']"`
 
-if [ "$command" == "stop" ]
-  then
+      update_pups=`cat $config_file | docker run -rm -i -a stdin -a stdout $image ruby -e \
+        "require 'yaml'; puts YAML.load(STDIN.readlines.join)['update_pups']"`
 
-    if [ ! -e $cidfile ]
-       then
-         echo "No cid found"
-         exit 1
-       else
-         docker stop -t 10 `cat $cidfile`
-         exit 0
-    fi
-fi
+      if [[ ! X"" = X"$base_image" ]]; then
+        image=$base_image
+      fi
 
-if [ "$command" == "logs" ]
-  then
+      set_volumes
 
-    if [ ! -e $cidfile ]
-       then
-         echo "No cid found"
-         exit 1
-       else
-         docker logs `cat $cidfile`
-         exit 0
-    fi
-fi
+      rm -f $cidbootstrap
 
-if [ "$command" == "start" ]
-  then
+      run_command="cd /pups &&"
+      if [[ ! "false" =  $update_pups ]]; then
+        run_command="$run_command git pull &&"
+      fi
+      run_command="$run_command /pups/bin/pups --stdin"
 
-    if [ ! -e $cidfile ]
-       then
-         echo "No cid found, creating a new container"
-         docker run -cidfile $cidfile -p 22 -p 80 -p 3000 -d -v `pwd`/shared:/shared samsaffron/discourse:$config /usr/bin/runsvdir -P /etc/service
-         exit 0
-       else
-         echo "cid found, ensuring container is started"
-         docker start `cat $cidfile`
-         exit 0
-    fi
-fi
+      (exec echo "$input" | docker run $env -e DOCKER_HOST_IP=$docker_ip -cidfile $cidbootstrap -i -a stdin -a stdout -a stderr $volumes $image \
+         /bin/bash -c "$run_command") \
+         || (docker rm `cat $cidbootstrap` && rm $cidbootstrap)
 
+      [ ! -e $cidbootstrap ] && echo "FAILED TO BOOTSTRAP" && exit 1
 
-if [ "$command" == "destroy" ]
-  then
-    if [ -e $cidfile ]
-      then
-        echo "destroying container $cidfile"
-        docker stop -t 10 `cat $cidfile`
-        docker rm `cat $cidfile` && rm $cidfile
-        exit 0
-      else
-        echo "nothing to destroy cidfile does not exist"
-        exit 1
-    fi
-fi
+      sleep 5
+
+      docker commit `cat $cidbootstrap` $local_discourse/$config || echo 'FAILED TO COMMIT'
+      docker rm `cat $cidbootstrap` && rm $cidbootstrap
+
+      echo "Successfully bootstrapped, to startup use ./launcher start $config"
+      exit 0
+      ;;
+
+  ssh)
+      if [ ! -e $cidfile ]
+         then
+           echo "No cid found"
+           exit 1
+         else
+           cid="`cat $cidfile`"
+           address="`docker port $cid 22`"
+           split=(${address//:/ })
+           exec ssh root@${split[0]} -p ${split[1]}
+      fi
+      ;;
+
+  stop)
+      if [ ! -e $cidfile ]
+         then
+           echo "No cid found"
+           exit 1
+         else
+           docker stop -t 10 `cat $cidfile`
+           exit 0
+      fi
+      ;;
+
+  logs)
+
+      if [ ! -e $cidfile ]
+         then
+           echo "No cid found"
+           exit 1
+         else
+           docker logs `cat $cidfile`
+           exit 0
+      fi
+      ;;
+
+  start)
+
+      if [ ! -e $cidfile ]
+         then
+           echo "No cid found, creating a new container"
+           ports=`cat $config_file | docker run -rm -i -a stdout -a stdin $image ruby -e \
+                  "require 'yaml'; puts YAML.load(STDIN.readlines.join)['expose'].map{|p| '-p ' << p.to_s << ' '}.join"`
+
+           set_template_info
+           set_volumes
+
+           existing=`docker ps -a | awk '{ print $1, $(NF) }' | grep "$config$" | awk '{ print $1 }'`
+           if [ ! -z $existing ]
+           then
+             echo "Found an existing container by its name, recovering cidfile, please rerun"
+             echo $existing > $cidfile
+             exit 1
+           fi
+
+           docker run $env -e DOCKER_HOST_IP=$docker_ip -name $config -cidfile $cidfile $ports \
+                      -d $volumes $local_discourse/$config /usr/bin/runsvdir -P /etc/service
+
+           exit 0
+         else
+           cid=`cat $cidfile`
+
+           if [ -z $cid ]
+           then
+             echo "Detected empty cid file, deleting, please re-run"
+             rm $cidfile
+             exit 1
+           fi
+
+           found=`docker ps -q -a -notrunc | grep $cid`
+           if [ -z $found ]
+           then
+             echo "Invalid cid file, deleting, please re-run"
+             rm $cidfile
+             exit 1
+           fi
+
+           echo "cid found, ensuring container is started"
+           docker start `cat $cidfile`
+           exit 0
+      fi
+      ;;
+
+
+  destroy)
+      if [ -e $cidfile ]
+        then
+          echo "destroying container $cidfile"
+          docker stop -t 10 `cat $cidfile`
+          docker rm `cat $cidfile` && rm $cidfile
+          exit 0
+        else
+          echo "nothing to destroy cidfile does not exist"
+          exit 1
+      fi
+      ;;
+esac
+
+usage