Skip to content

Instantly share code, notes, and snippets.

@hemalvarambhia
Created November 6, 2014 07:46
Show Gist options
  • Save hemalvarambhia/aa5b5954da7b97fc767d to your computer and use it in GitHub Desktop.
Save hemalvarambhia/aa5b5954da7b97fc767d to your computer and use it in GitHub Desktop.
One of the recipes in the legacy chef repo shown at the November London Chef Users Meetup.
# Determine which apps require the 'app' tier to be set up on this node:
tier_apps = ai_stack.apps_for_tier(node, 'app')
# Initialize an array to store user names that will later be added to the
# "sshlogin" group:
sshlogin_users = []
# Perform configuration required by all apps:
unless tier_apps.empty?
# Ensure all dependencies necessary to build Ruby are present:
include_recipe 'build-essential'
# Install packages useful for apps that use the asset pipeline functionality.
include_recipe 'ai_stack::asset_pipeline'
ruby_dependencies = %w{
openssl libreadline6 libreadline6-dev zlib1g zlib1g-dev libssl-dev libyaml-dev
libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libc6-dev libncurses5-dev
}
ruby_dependencies.each { |name| package(name) }
# Ensure PostgreSQL client libraries are installed:
include_recipe 'postgresql::client'
package 'libpq-dev'
# Ensure runit is installed:
include_recipe 'runit'
# Ensure mercurial is installed:
include_recipe 'mercurial'
# Include the logrotate recipe:
include_recipe 'logrotate'
end
# Configure apps which run on this node:
tier_apps.each do |app_name, tiers|
spec = data_bag_item('ai_apps', app_name)
user_name = spec['user']
user_home = "/home/#{user_name}"
# Create a user for the app:
user(user_name) do
home user_home
shell "/bin/bash"
supports :manage_home => true
end
# Generate an SSH key:
execute("ssh-keygen") do
command %Q{ssh-keygen -q -t rsa -f #{user_home}/.ssh/id_rsa -P ""}
user user_name
group user_name
cwd user_home
creates "#{user_home}/.ssh/id_rsa.pub"
end
# Create an authorized_keys file populated with developer SSH keys:
template "#{user_home}/.ssh/authorized_keys" do
source "authorized_keys.erb"
owner user_name
group user_name
mode "0644"
variables(:ssh_keys => search(:ssh_keys, '*:*'))
end
# Add any extra package repositories
if spec['package_repositories']
spec['package_repositories'].each do |repo|
apt_repository repo[:name] do
uri repo[:uri]
distribution repo[:distribution] # e.g. lucid
components repo[:components] # e.g. ["main"]
keyserver repo[:keyserver]
key repo[:key]
end
end
end
# Install any OS packages required by the application:
if spec['packages']
spec['packages'].each { |package_name| package(package_name) }
end
# Add the app user to any required groups:
if spec['groups']
spec['groups'].each do |group_name|
group(group_name) do
action :modify
members [user_name]
append true
end
end
end
package("curl") do
not_if "test -f #{user_home}/.rvm"
end
package("git-core") do
not_if "test -f #{user_home}/.rvm"
end
# Install RVM:
bash("install rvm for #{app_name}") do
code "bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)"
user user_name
group user_name
cwd user_home
creates "#{user_home}/.rvm"
environment({"HOME" => user_home})
end
# Alter the user's .bashrc file so that RVM is loaded correctly in interactive and non-interactive shells:
cookbook_file("#{user_home}/.bashrc") do
source "bashrc"
owner user_name
group user_name
mode "0644"
action :create
end
# Create a $HOME/bin directory:
directory "#{user_home}/bin" do
owner user_name
group user_name
mode "0755"
end
# Install the rvm_wrapper.sh script in the $HOME/bin directory:
rvm_wrapper = "#{user_home}/bin/rvm_wrapper.sh"
template(rvm_wrapper) do
source "rvm_wrapper.sh.erb"
owner user_name
group user_name
mode "0755"
variables(:user_home => user_home)
end
# Install the required Ruby versions:
ruby_versions = spec['ruby']
default_ruby_version = ruby_versions.first
##
# NOTE jruby installs seem to be a bit flakey
##
ruby_versions.each do |ruby_version|
bash("rvm install for #{ruby_version}") do
user user_name
group user_name
code "#{rvm_wrapper} rvm install #{ruby_version}"
##
# This line seems to cause problems when there are two users with the
# same ruby version. The second one is assumed to be installed to the
# user but it is actually installed to the other user
#
# However you will get a spurious message about reinstalling ruby
#
##
# not_if "#{rvm_wrapper} rvm list | grep #{ruby_version}", :user => user_name
end
# Create an RVM wrapper script for bundler:
bash("rvm bundler wrapper for #{ruby_version}") do
user user_name
code "#{rvm_wrapper} rvm wrapper #{ruby_version} #{app_name} bundle"
creates "#{user_home}/.rvm/bin/#{app_name}_bundle"
end
end
# Set the default Ruby version to the first version given:
bash("rvm default to #{default_ruby_version}") do
user user_name
group user_name
code "#{rvm_wrapper} rvm --default use #{default_ruby_version}"
not_if "#{rvm_wrapper} rvm list default | grep #{default_ruby_version}", :user => user_name
end
# Gems, if installed, will be installed against the default version of ruby
if spec['gems']
# Install gems manually for applications that don't manage their dependencies
# using Bundler:
spec['gems'].each do |name, version_and_source|
version, source = version_and_source
# Use rubygems.org as the default gem source:
source ||= 'http://rubygems.org'
bash("gem install #{name}") do
user user_name
code "#{rvm_wrapper} gem install #{name} --version #{version} --source #{source}"
not_if "#{rvm_wrapper} gem list | grep #{name} | grep #{version}", :user => user_name
end
end
else
# Install the Bundler gem:
bash("gem install bundler") do
user user_name
code "#{rvm_wrapper} gem install bundler"
not_if "#{rvm_wrapper} gem list | grep bundler", :user => user_name
end
end
# Create a service directory for the app user:
user_service_dir = "#{user_home}/service"
directory(user_service_dir) do
owner user_name
group user_name
mode "0755"
end
# Create a new runsvdir service for the app service directory:
runsvdir_path = "/etc/sv/runsvdir-#{user_name}"
directory(runsvdir_path) do
owner "root"
group "root"
mode "0755"
end
# Create a run script for the runsvdir service:
template(File.join(runsvdir_path, "run")) do
source "runsvdir.erb"
owner "root"
group "root"
mode "0755"
variables(:user_name => user_name, :service_dir => "#{user_home}/service")
end
# And tell runit about the runsvdir service:
link("/etc/service/#{File.basename(runsvdir_path)}") { to runsvdir_path }
# Create a directory for the application to live in:
app_path = "#{user_home}/#{spec['id']}"
directory(app_path) do
owner user_name
group user_name
mode "0755"
end
# Create an app "shared" directory:
shared_path = "#{app_path}/shared"
directory(shared_path) do
owner user_name
group user_name
mode "0755"
end
# Create a database.yml file:
template("#{shared_path}/database.yml") do
source "database.yml.erb"
owner user_name
group user_name
mode "0755"
variables(:data => spec)
end
# Configure logrotate:
package "dbus"
logrotate_app "app-#{user_name}-logs" do
cookbook "logrotate"
path "#{shared_path}/log/*.log"
frequency "daily"
rotate 30
create "644 #{user_name} #{user_name}"
dateext
end
# Any application running it's "app" tier on this node should also be part of the sshlogin group:
sshlogin_users << user_name
end
# Allow application users to login via SSH (for deployment):
group "sshlogin" do
members sshlogin_users
append true
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment