Skip to content

Instantly share code, notes, and snippets.

@ehlertij
Created October 11, 2012 19:55
Show Gist options
  • Save ehlertij/3875094 to your computer and use it in GitHub Desktop.
Save ehlertij/3875094 to your computer and use it in GitHub Desktop.
EY Puma Recipes
#!/bin/bash
# Auto-generated by Chef; your changes will be overwritten!
# Pull in a full environment and include some configuration of said commands.
source /etc/profile
source /data/<%= @app_name %>/shared/config/env
source /data/<%= @app_name %>/shared/config/env.custom
# Ensure that we are running as the root user.
# If not, error exit while notifying the user.
if [[ $(id -u) -eq 0 ]] ; then
echo "ERROR: This script must be run as a user, not as root." 2>&1
exit 1
fi
ACTION="$1"
PORT="${2:-$PORT}" # Take port from env var, but allow override with second argument
fetch_current_pid() {
if [ -z "$PORT" ] ; then
PORT=$baseport
fi
pidfile="${pid_directory}/puma.$PORT.pid"
if [[ -s "$pidfile" ]] ; then
current_pid=$(cat "$pidfile")
process_count=`ps -p ${current_pid} -o comm= | wc -w`
if [[ $process_count = "0" ]]; then
# Remove the pidfile if the process isn't actually running
current_pid=0
cleanup
fi
else
# Try to check if the process is running - if found, provide missing pid file
current_pid="$(ps auwwx | grep ".*[Pp]uma.${PORT}.pid --port ${PORT}" | awk '{print $2}')"
process_count=`echo $current_pid | wc -w`
if [[ $process_count = "1" ]]; then
echo $current_pid > $pidfile
else
current_pid=0
fi
fi
return 0
}
is_running() {
fetch_current_pid
if [[ ${current_pid} == 0 ]] ; then
return 1
fi
if [[ -d "/proc/${current_pid}" ]] ; then
application_name=${application}
process_name="$(readlink /proc/$current_pid/exe)"
process_dir="$((cat /proc/${current_pid}/environ; echo) | tr '\000' '\n' | grep '^PWD=' |sed -e 's/PWD=//')"
fi
return 0
}
cleanup() {
if [ -z "$PORT" ] ; then
PORT=$baseport
fi
pidfile="${pid_directory}/puma.$PORT.pid"
if [[ -s "$pidfile" ]] ; then
echo "Cleaning up pid and socket files"
rm $pidfile && rm $sockets_path/puma*.sock
fi
return 0
}
status() {
if is_running ; then
echo "Puma is running on port $PORT with:"
echo " pid: $current_pid"
echo " name: $process_name"
echo " cwd: $process_dir"
cd ${current_path}
bundle exec pumactl -S ${shared_path}/sockets/puma.$PORT.state stats
else
echo "Puma is not running on port $PORT."
fi
}
start() {
if is_running ; then
echo "ERROR: Puma already running on port $PORT with: "
echo " pid: $current_pid "
echo " name: $process_name "
echo " cwd: $process_dir"
exit 1
fi
if [ -d "${current_path}" ]; then
if [ ! -z "$PORT" ] ; then
echo "Puma is being started for $application port $PORT ..."
cd ${current_path}
# Don't need to use bundler because bundle_stubs is the first entry in the PATH
puma_arguments="--environment ${framework_env} --state ${sockets_path}/puma.$PORT.state --control unix://${sockets_path}/pumactl.$PORT.sock"
nohup bundle exec puma ${puma_arguments} --pidfile ${pid_directory}/puma.$PORT.pid --port $PORT > ${log_directory}/puma.log 2>&1 &
echo "verifying ..."
sleep 2
fetch_current_pid
if [ "$current_pid" = 0 ]; then
echo "ERROR: Process did not seem to start"
exit 1
else
echo " running on pid ${current_pid}."
fi
else
echo "Usage: $0 $1 <port*>"
echo " * PORT environmental variable can also be used to specify the port"
exit 1
fi
fi
}
deploy() {
if is_running ; then
echo "Hot deploying Puma for ${application} on port $PORT (pid: ${current_pid}) ..."
cd ${current_path}
bundle exec pumactl -S ${shared_path}/sockets/puma.$PORT.state restart && echo " hot deploy in progress."
else
start
fi
}
stop() {
if [ -z "$PORT" ] ; then
echo "Usage: $0 $1 <port*>"
echo " * PORT environmental variable can also be used to specify the port"
exit 1
fi
if is_running ; then
echo "Stopping Puma for ${application} on port $PORT (pid: ${current_pid}) ..."
kill ${current_pid} && echo " stopped." && cleanup
else
echo "ERROR: Cannot find a running process for ${application} on port $PORT"
exit 1
fi
}
case "$ACTION" in
deploy)
deploy
;;
stop)
stop
;;
start)
start
;;
status)
status
;;
restart)
deploy
;;
*)
echo "Usage: $0 {start|stop|status|restart|deploy} [<port>]"
exit 1
;;
esac
exit 0
#
# Cookbook Name:: puma
# Recipe:: default
#
# Copyright 2011, Engine Yard, Inc.
#
# All rights reserved - Do Not Redistribute
#
ey_cloud_report "puma" do
message "processing puma"
end
gem_package "puma" do
action :install
version node[:puma][:version]
end
service "nginx" do
action :nothing
supports :status => false, :restart => true
end
base_port = 5000
baseport = base_port
workers = ( node[:puma][:workers] + 1 / node['applications'].size ) - 1
node.apps.each_with_index do |app,index|
port = base_port + index
pid_file = "/var/run/engineyard/#{app.name}/puma-#{port}.pid"
app_path = "/data/#{app.name}"
deploy_file = "#{app_path}/current/REVISION"
log_file = "#{app_path}/shared/log/puma.log"
ssh_username = node.ssh_username
framework_env = node['environment']['framework_env']
restart_resource = "restart-puma-#{app.name}"
solo = node[:instance_role] == 'solo'
execute restart_resource do
command "monit restart #{app.name}"
action :nothing
end
node[:nginx][:version] = node[:passenger3][:nginx_version]
ports = Array.new
(port).upto(port + (workers -1)) do |p|
ports << p
end
# Create sockets directory, used for pumactl files
directory "#{app_path}/shared/sockets" do
owner ssh_username
group ssh_username
mode 0755
recursive true
end
app.vhosts.each do |vhost|
vhost app.name do
dna_vhost vhost
cookbook 'puma'
upstream_ports ports
end
end
directory "/var/run/engineyard/#{app.name}" do
owner ssh_username
group ssh_username
mode 0755
recursive true
end
template "/data/#{app.name}/shared/config/env" do
source "env.erb"
backup 0
owner ssh_username
group ssh_username
mode 0755
cookbook 'puma'
variables(:app_name => app.name,
:app_dir => "#{app_path}/current",
:pid_file => pid_file,
:user => ssh_username,
:deploy_file => deploy_file,
:shared_path => "#{app_path}/shared",
:ports => ports,
:framework_env => framework_env,
:baseport => baseport,
:workers => node[:puma][:workers])
end
file "/data/#{app.name}/shared/config/env.custom" do
owner ssh_username
group ssh_username
mode 0644
action :create_if_missing
end
template "/engineyard/bin/app_#{app.name}" do
source 'app_control.erb'
owner ssh_username
group ssh_username
mode 0755
backup 0
cookbook 'puma'
variables(:app_name => app.name,
:app_dir => "#{app_path}/current",
:pid_file => pid_file,
:deploy_file => deploy_file,
:shared_path => "#{app_path}/shared",
:ports => ports,
:framework_env => framework_env)
end
template "/engineyard/bin/#{app[:name]}_puma" do
source "puma_commands.erb"
owner ssh_username
group ssh_username
mode 0755
backup 0
cookbook 'puma'
variables(:app => app.name,
:shared_path => "#{app_path}/shared",
:ports => ports)
end
logrotate "puma_#{app.name}" do
files log_file
copy_then_truncate
end
managed_template "/etc/monit.d/puma_#{app.name}.monitrc" do
source "puma.monitrc.erb"
owner "root"
group "root"
mode 0666
backup 0
cookbook 'puma'
variables(:app => app.name,
:username => ssh_username,
:pid_file => pid_file,
:ports => ports)
end
end
require_recipe "puma::cleanup_passenger"
namespace(:puma) do
task :start, :roles => :app, :except => { :no_release => true } do
run "sudo monit start all -g #{application}"
end
task :stop, :roles => :app, :except => { :no_release => true } do
run "sudo monit stop all -g #{application}"
end
desc "Restart the application"
task :restart, :roles => :app, :except => { :no_release => true } do
run "/engineyard/bin/#{application}_puma restart"
end
desc "Status of the application"
task :status, :roles => :app, :except => { :no_release => true } do
run "/engineyard/bin/#{application}_puma status"
end
end
DEPLOY_FILE="<%= @deploy_file %>"
application="<%= @app_name %>"
shared_path="/data/${application}/shared"
framework_env="<%= @framework_env %>"
current_path="/data/${application}/current"
baseport="<%= @baseport %>"
workers="<%= @workers %>"
pid_directory="/var/run/engineyard/${application}"
log_directory="/var/log/engineyard/apps/${application}"
PATH="/data/<%= @app_name %>/current/ey_bundler_binstubs:$PATH"
THREADCOUNT="<%= @threads %>"
sockets_path=${shared_path}/sockets
# Monit can take these away; forcing them to stay.
export LANG=en_US.utf8
export SHELL="/bin/bash"
if [ "$APP_USER" = "" ]; then
APP_USER=`stat -c"%U" /data/${application}/current`
fi
INLINEDIR=/tmp/inline_$$; export INLINEDIR
HOME=`eval "dirname ~${APP_USER}/."`; export HOME
USER=$APP_USER; export USER
#!/bin/bash
ACTION="$1"
restart() {
<% @ports.each do |port| %>
/engineyard/bin/app_<%= @app %> deploy <%= port %>
<% end %>
}
status() {
<% @ports.each do |port| %>
/engineyard/bin/app_<%= @app %> status <%= port %>
<% end %>
}
case "$ACTION" in
status)
status
;;
restart)
restart
;;
*)
echo "Usage: $0 {status|restart}"
exit 1
;;
esac
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment