#!/bin/bash
#
# Install a consistent ruby and rails stack with some handy gems
#

# To update the version on this script, either change the file source below
# or make sure the version you want is stored on downloads 
# i.e. when you want to update the version to the latest release
# If your updating the version on downloads, please update the
# RUBY
FILESOURCE="http://downloads.rimuhosting.com"
# Uninitialized variables use option flags to set non-null 
NOAPT=
BFLAG=
USEREE=
NORDOC=
DEBUG=
NOMAGICK=
NOGEMINST=
NOMODPASSENGER=
###
# Function: version
#
function version {
echo <<VERSION "
 $Id: rails.sh 197 2012-02-05 02:33:44Z root $null
 Copyright Rimuhosting.com - Absolutely no warranty
"
VERSION
}

function usage {
		echo <<USAGE "
Usage: $(basename $0) [OPTION...]

Run with no options to install default setup with official Ruby 1.8.7 interpreter. 

Options: 
 -a	Skip apt-get update && upgrade, and the prerequisite package installation.
 -b	Install recent 1.9.2x version of the official Ruby interpreter. 
 -d	Run script with debug logging
 -e	Install Ruby Enterprise Edition (REE)
 -g	Skip installing common gems
 -h	This help message
 -i	Skip ImageMagick installation
 -p	Skip mod-passenger/Apache setup
 -r	Skip installing rdoc files 
 -v	Version message
"
USAGE
}

while getopts 'abdeghiprv' OPTION
do 
		case $OPTION in
				a) NOAPT=1
						;;
				b) BFLAG=1
						;;
				d) DEBUG=1
						;;
		        e) USEREE=1
						;;
			    g) NOGEMINST=1
						;;
				h) usage
				   exit 0;;
				i) NOMAGICK=1
						;;
				r) NORDOC=1
						;;
				p) NOMODPASSENGER=1
						;;
				v) version 
				   exit 0;;
				?) echo "Not a valid option."
						usage
						exit 1
						;;
		esac
done
shift $(($OPTIND - 1))

if [ "$BFLAG" ]; then
		if [ "$USEREE" ]; then
				echo " * Error: This script is not meant to install REE and the official Ruby at the same time"
				echo " * Hint: You can do this if you wanted to though. Suggest you use RVM. "
				exit 1
	    fi
	# Set RUBY 1.9.2.x version here and make sure it's available on downloads
	RUBY_VERSION="1.9.3-p0"
	echo "Installing Ruby version: $RUBY_VERSION"
  else
    # Set RUBY 1.8.7.x version here and make sure it's available on downloads
	RUBY_VERSION="1.8.7-p352"
	echo "Installing Ruby version: $RUBY_VERSION"
fi

if [ "$USEREE" ]; then
		# Set REE version here and make sure it's available on downloads
		unset $RUBY_VERSION
	REE_VERSION="1.8.7-2011.03"
	echo "Installing REE version: $REE_VERSION"
fi

# Option to not install rodoc files
GEMMODG=
if [ "$NORDOC" ]; then 
		GEMMOD="--no-ri --no-rdoc"
fi

RUBY_GEM_VERSION="1.8.15"        # http://rubygems.org/pages/download
IMAGEMAGIC_VERSION="6.6.9-10"    # http://www.imagemagick.org/script/download.php
MOD_RAILS_VERSION="3.1.0"       # http://www.modrails.com/install.html

# test app installation defaults
RAILS_APP_DEPLOYMENT_DIR="/var/www/apps"
RAILS_TEST_APP="testapp"

export LANG=C

# debug so we can make the script less noisy, but still see what happened if needed
[ ! -z "$DEBUG" ] && echo -e "! Debugging mode active, logging extra output to $DEBUG_LOG_FILE\n"

  export DEBUG_LOG_FILE="/dev/null"
if [[ ! -z "$DEBUG" ]]; then
  export DEBUG_LOG_FILE="/root/debug-rails.log"
  echo > "$DEBUG_LOG_FILE"
fi

#detect distro version
if [ -e /etc/redhat-release ]; then
  DISTRO="redhat"
elif [ -e /etc/debian_version ]; then
  DISTRO="debian"
fi

#set apt-get modifier based on distro
if [ $DISTRO == "redhat" ]; then
  APTMOD=" -y "
elif [ $DISTRO == "debian" ]; then
  APTMOD="-y --force-yes"
fi

if [ $DISTRO == "redhat" ]; then
  RAILS_APP_CONFIG="/etc/httpd/conf.d/railsapps.conf"
  MOD_RAILS_CONFIG="/etc/httpd/conf.d/mod_rails.conf"
elif [ $DISTRO == "debian" ]; then
  RAILS_APP_CONFIG="/etc/apache2/conf.d/railsapps.conf"
  MOD_RAILS_CONFIG="/etc/apache2/conf.d/mod_rails.conf"
fi

# used for detection of caller (ie login shell or another script)
CALLER=$(ps ax | grep "^ *$PPID" | awk '{print $NF}')


####################
# HELPER FUNCTIONS #
####################



##
# view std out and append to log
function echolog {
  echo "$*" | tee -a "$DEBUG_LOG_FILE"
}

##
# download files etc
function download {
  [ -z "$1" ] && return 1 || local name="$1"
  [ -z "$1" ] && return 1 || local version="$2"
  shift; shift
  [ -z "$*" ] && return 1 || local url="$*"
  mkdir -p /usr/local/src
  cd /usr/local/src
  if [ -d /usr/local/src/$name-$version ]; then
    echolog "  ...source for $name already present, skipping the download"
    cd /usr/local/src/$name-$version
    return 0
  fi
  echolog "  ...grabbing source for $name from $url"
  wget -qO - $url | tar xz
  if [ $? -ne 0 ]; then
    echolog "! Error: failed getting $url"
    return 1
  fi
  cd /usr/local/src/$name-$version
  return 0
}

##
# apt-get update
function aptgetupdate {
  echolog "* Performing system update via package manager"
  apt-get update >> "$DEBUG_LOG_FILE" 2>&1
  apt-get $APTMOD upgrade >> "$DEBUG_LOG_FILE" 2>&1
  return 0
}

##
# install prerequisites
function installprereqpackages {
  echolog "* Installing prerequisite packages via package manager"
  if [ $DISTRO == "redhat" ] ; then
    packagelist="make zlib-devel mysql-devel libmysqlclient15-dev readline-devel readline libpng-devel libpng pcre pcre-devel httpd-devel which libtiff-devel libtiff curl-devel curl libcurl-devel libwmf-devel libwmf gd-devel gd libjpeg-devel libjpeg sqlite-devel sqlite freetype-devel openssl-devel gcc-c++"
  elif [ $DISTRO == "debian" ]; then
    packagelist="build-essential zlib1g-dev g++-3.4 libmysqlclient14-dev libreadline5-dev libwmf-bin libmysqlclient15-dev libssl-dev apache2-prefork-dev libfreetype6 libfreetype6-dev libpng12-dev libtiff4 libtiff4-dev libttf2 libcurl4-openssl-dev libyaml-dev"
  fi
  for package in $packagelist; do
    apt-get $APTMOD install "$package" >> "$DEBUG_LOG_FILE" 2>&1
    [ $? -eq 0 ] && echo "     $package"
  done
  return 0
}

##
# install ImageMagik
function installimagemagik {
  echolog "* Installing ImageMagick v${IMAGEMAGIC_VERSION}"
  download ImageMagick ${IMAGEMAGIC_VERSION} "${FILESOURCE}/ImageMagick-${IMAGEMAGIC_VERSION}.tar.gz"
  if [ $? -ne 0 ]; then echolog "! Error: failed downloading imagemagick"; return 1; fi
  echolog "  ...building from source package, please be patient"
  echo -n "     configure" && `./configure  >> "$DEBUG_LOG_FILE" 2>&1` && \
  echo -n ", make" && `make  >> "$DEBUG_LOG_FILE" 2>&1` && \
  echo -n ", install" && `make install >> "$DEBUG_LOG_FILE" 2>&1` && \
  echo ", done"
  if [ $? -ne 0 ]; then echolog "! Error: ImageMagick make install failed"; return 1; fi
  # Not sure if this is requried, probably won't hurt:
  ldconfig /usr/local/lib
}


##
# install ruby-enterprise eddition from http://www.rubyenterpriseedition.com/
# fixme needs testing
function installree {
  echolog "* Installing Ruby Enterprise v$REE_VERSION"
  download ruby-enterprise $REE_VERSION ${FILESOURCE}/ruby-enterprise-$REE_VERSION.tar.gz

  echolog "  ...building from source package, please be patient"
  ./installer --auto=/usr/local >> "$DEBUG_LOG_FILE" 2>&1

  echolog "  ...add link for ruby binary so there'll be a /usr/bin/ruby"
  if [ -e /opt/ruby-enterprise-$REE_VERSION/bin/ -a ! -e /usr/bin/ruby ]; then
    ln -sf /opt/ruby-enterprise-$REE_VERSION/bin/ruby /usr/bin/ruby
  fi
}


##
# install ruby & dev libraries
function installruby {
  echolog "* Installing Ruby v$RUBY_VERSION"
  download ruby $RUBY_VERSION "${FILESOURCE}/ruby-$RUBY_VERSION.tar.gz"
  if [ $? -ne 0 ]; then echolog "! Error: failed downloading ruby"; return 1; fi

  echolog "  ...building from source package, please be patient"
  echo -n "     configure" && `./configure >> "$DEBUG_LOG_FILE" 2>&1` && \
  echo -n ", make" && `make  >> "$DEBUG_LOG_FILE" 2>&1` && \
  echo -n ", test" && `make test  >> "$DEBUG_LOG_FILE" 2>&1` && \
  echo -n ", install" && `make install >> "$DEBUG_LOG_FILE" 2>&1` && \
  echo ", done"
  if [ $? -ne 0 ]; then echolog "! Error: Ruby build failed"; return 1; fi

  echolog "  ...add link for ruby binary so there'll be a /usr/bin/ruby"
  if [ -e /usr/local/bin/ruby -a ! -e /usr/bin/ruby ]; then
    ln -sf /usr/local/bin/ruby /usr/bin/ruby
  fi

  echolog "  ...building readline against newly installed ruby"
  # doing this voodoo to prevent errors like:
  # /usr/local/lib/ruby/1.8/irb/completion.rb:10:in `require’: no such file to load—readline (LoadError)
  cd /usr/local/src/ruby-$RUBY_VERSION/ext/readline
  if [ $? -ne 0 ]; then echolog "! Error: no /usr/local/src/ruby-$VERSION_ACTUAL/ext/readline dir"; return 1; fi
  echo -n "     conf" && ruby extconf.rb >> "$DEBUG_LOG_FILE" 2>&1
  if [ $? -ne 0 ]; then echo; echolog "! Error: readline extconf.rb failed"; return 1; fi
  echo -n ", make" && `make clean  >> "$DEBUG_LOG_FILE" 2>&1` && \
  echo -n ", install" && `make install >> "$DEBUG_LOG_FILE" 2>&1` && \
  echo ", done"
  if [ $? -ne 0 ]; then echolog "! Error: readline build failed"; return 1; fi
  return 0
}

##
# install ruby gem
function installrubygems {
  echolog "* Installing Ruby Gems v$RUBY_GEM_VERSION"
  download rubygems $RUBY_GEM_VERSION ${FILESOURCE}/rubygems-$RUBY_GEM_VERSION.tgz
  if [ $? -ne 0 ]; then echolog "! Error: failed downloading rubygems"; return 1; fi
  echolog "  ...running setup for rubygems"
  ruby setup.rb >> "$DEBUG_LOG_FILE" 2>&1
  if [ $? -ne 0 ]; then echolog "! Error: Rubygems install failed"; return 1; fi
  return 0
}

##
# install commonly used gems
function installcommongems() {
  echolog "* Installing commonly used Ruby Gems"
  # Making an option for w/ or w/out rdoc
  
  if [ -n "$NORDOC" ]; then
		echo " * Not installing Rdoc files"
  else 
  echolog "  ...force reinstalling rdoc to make later gem builds sane (eg rails)"
  echolog "  ...force reinstalling rdoc to make later gem builds sane (eg rails)"
  # ref http://railsforum.com/viewtopic.php?id=41111
  gem install rdoc-data >> "$DEBUG_LOG_FILE" 2>&1
  rdoc-data --install >> "$DEBUG_LOG_FILE" 2>&1
  gem rdoc --all --overwrite >> "$DEBUG_LOG_FILE" 2>&1
  fi

  echolog "  ...reinstalling assorted handy gems"
  GEM_LIST="rails capistrano rmagick sqlite3 psych"
  for gem in $GEM_LIST; do
    gem install $GEMMOD --include-dependencies $gem >> "$DEBUG_LOG_FILE" 2>&1
    [ $? -ne 0 ] && echolog "! Error: failed to install gem '$gem'" || echolog "     $gem"
  done

  echolog "  ...do mysql gem last to improve sanity of build"
  if [ $DISTRO == "redhat" ]; then
    gem install $GEMMOD mysql -- --with-mysql-config=/usr/bin/mysql_config >> "$DEBUG_LOG_FILE" 2>&1
  elif [ $DISTRO == "debian" ]; then
    gem install mysql >> "$DEBUG_LOG_FILE" 2>&1
  fi

  echolog "  ...install mod_rails (passenger)"
  gem install $GEMMOD passenger --include-dependencies -v "$MOD_RAILS_VERSION"  >> "$DEBUG_LOG_FILE" 2>&1

  echolog "  ...compile mod_rails apache module"
  passenger-install-apache2-module -a >> $DEBUG_LOG_FILE 2>&1
  return 0
}

##
# create deployment environment
function createdeployenv {
  echolog "* Configuring mod_rails/Apache"

  echolog "  ...disable apache default vhost/welcome screen"
  if [ $DISTRO == "redhat" ]; then
    [ -r /etc/httpd/conf.d/welcome.conf ] && mv -f /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.bak
  elif [ $DISTRO == "debian" ]; then
    a2dissite default >> "$DEBUG_LOG_FILE" 2>&1
    [ -e /etc/apache2/sites-enabled/000-default ] && rm -f /etc/apache2/sites-enabled/000-default
  fi

  echolog "  ...add basic passenger config"
  echo "LoadModule passenger_module /usr/local/lib/ruby/gems/1.8/gems/passenger-$MOD_RAILS_VERSION/ext/apache2/mod_passenger.so
PassengerRoot /usr/local/lib/ruby/gems/1.8/gems/passenger-$MOD_RAILS_VERSION
PassengerRuby /usr/local/bin/ruby
RailsEnv production
#Tune these to suit your application
PassengerMaxPoolSize 2
PassengerMaxInstancesPerApp 2
PassengerPoolIdleTime 600" > $MOD_RAILS_CONFIG

  echolog "  ...create app deployment directory" # FIXME?
  mkdir -p $RAILS_APP_DEPLOYMENT_DIR

  echolog "  ...create '$RAILS_TEST_APP' rails app"
  cd $RAILS_APP_DEPLOYMENT_DIR
  rails new "$RAILS_TEST_APP" -f >> "$DEBUG_LOG_FILE" 2>&1

  echolog "  ...fixing correct permissions for apache"
  if [[ "$DISTRO" == "redhat" ]]; then
    chown -R apache $RAILS_APP_DEPLOYMENT_DIR
  elif [[ "$DISTRO" == "debian" ]]; then
    chown -R www-data $RAILS_APP_DEPLOYMENT_DIR
  fi

  echolog "  ...restart apache"
  initcmd="service httpd"
  [ -e /etc/init/apache2 ] && initcmd="service apache2"
  [ -e /etc/init.d/apache2 ] && initcmd="/etc/init.d/apache2"
  $initcmd restart >> "$DEBUG_LOG_FILE" 2>&1
}

function footer {
  [[ "$CALLER" == "-bash" ]] || return 0
  ipaddr="$(ifconfig eth0 | grep "inet addr:" | awk '{print $2}' | cut -d: -f2)"
  echolog "* Ruby is now installed. Point your apache site to the appropriate"
  echolog "  DocumentRoot (eg ${RAILS_APP_DEPLOYMENT_DIR})"
  exit 0
}

####################
#    EXECUTION     #
####################

version
# APT update and install prereq packages
if [ -z "$NOAPT" ]; then
aptgetupdate
installprereqpackages
else
		echo " * Skipping Updates and installing Prereqs"
fi
# IMAGEMAGICK build
if [ -z "$NOMAGICK" ]; then
installimagemagik
else
		echo " * Skipping ImageMagick install"
fi
# Regular Ruby or REE
[ -z "$USEREE" ] && installruby || installree
# If your installing REE then you won't need this:
if [ -z "$USEREE" ]; then
 	installrubygems 
 else
 	echo " * Skipping GEM install, REE provides it"
fi
# Common Gems? 
if [ -z "$NOGEMINST" ]; then
installcommongems
else 
		echo " * Skipping adding some common Gems"
fi
# This function needs to be renamed to setupmodpassenger (with Apache)
if [ -z "$NOMODPASSENGER" ]; then
createdeployenv
else 
		echo " * Skipping mod-passenger setup"
fi
footer

exit 0

