Skip to content

Instantly share code, notes, and snippets.

@jamesu
Created June 23, 2011 21:47
Show Gist options
  • Save jamesu/1043715 to your computer and use it in GitHub Desktop.
Save jamesu/1043715 to your computer and use it in GitHub Desktop.
Deploying chef with capistrano
# Deploying chef with capistrano
# Requires a typical chef config layout, i.e.
# cookbooks/
# nodes/
# roles/
#
# Commands:
# configure:<node> - Upload chef cookbooks, run chef-solo
#
# Roles will automatically be added from nodes/*.json. e.g. if you have
# "nodes/lolcat.json", you can run:
# cap configure:lolcat
#
require 'rubygems'
require 'json'
# Load node data...
ROLE_LIST = {}
NODE_LIST = {}
JSON.create_id = nil
Dir["roles/*.json"].each do |rolefile|
role = JSON.load(File.open(rolefile))
ROLE_LIST[File.basename(rolefile, '.json')] = role
end
Dir["nodes/*.json"].each do |nodefile|
node = JSON.load(File.open(nodefile))
NODE_LIST[File.basename(nodefile, '.json')] = node
end
COMMAND_MATCH = /([^\[]+)\[([^:\]]+)/
def run_list_for(node)
roles = []
recipes = []
node['run_list'].each do |item|
if COMMAND_MATCH =~ item
if $1 == 'recipe'
recipes << $2
elsif $1 == 'role'
roles << $2
data = run_list_for(ROLE_LIST[$2])
roles += data[:roles]
recipes += data[:recipes]
end
end
end
{:roles => roles, :recipes => recipes}
end
def depends_for(recipes)
depends = recipes.map do |r|
metadata = JSON.load File.open("cookbooks/#{r}/metadata.json")
[r, metadata['dependencies'].keys]
end.flatten.uniq
end
def run_list_with_dependencies_for(node)
list = run_list_for(NODE_LIST[node])[:recipes]
depends_for(list)
end
NODE_LIST.keys.each do |node|
role node.to_sym, node
end
NODE_CONFIG = <<-EOS
file_cache_path '/tmp/chef-solo'
cookbook_path '/tmp/chef-solo/cookbooks'
role_path '/tmp/chef-solo/roles'
EOS
# Commands, finally!
namespace :configure do
NODE_LIST.keys.each do |node|
desc "Configure #{node}"
task node.to_sym, :role => node.to_sym do
recipe_list = run_list_with_dependencies_for(node)
run "if [ ! -e /tmp/chef-solo ]; then mkdir /tmp/chef-solo; fi"
recipe_list.each { |r| upload("cookbooks/#{r}", "/tmp/chef-solo/cookbooks/", :via => :scp, :recursive => true) }
upload("roles", "/tmp/chef-solo/roles", :via => :scp, :recursive => true)
upload("nodes/#{node}.json", "/tmp/chef-solo/node.json", :via => :scp)
put(NODE_CONFIG, "/tmp/chef-solo/solo.rb")
sudo "chef-solo -l #{'info'} -c /etc/chef-solo/solo.rb -j /tmp/chef-solo/node.json"
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment