Skip to content

Instantly share code, notes, and snippets.

@joenoon
Created June 8, 2011 01:21
Show Gist options
  • Save joenoon/1013595 to your computer and use it in GitHub Desktop.
Save joenoon/1013595 to your computer and use it in GitHub Desktop.
quick hack to use vagrant's familiar chef-solo integration to provision a remote server instead of a vm
require 'rubygems'
require 'vagrant'
module Vagrant
class SSH
def rsync(opts={})
if Mario::Platform.windows?
raise Errors::SSHUnavailableWindows, :key_path => env.config.ssh.private_key_path,
:ssh_port => port(opts)
end
raise Errors::SSHUnavailable if !Kernel.system("which ssh > /dev/null 2>&1")
options = {}
options[:port] = port(opts)
[:host, :username, :private_key_path].each do |param|
options[param] = opts[param] || env.config.ssh.send(param)
end
check_key_permissions(options[:private_key_path])
# Command line options
command_options = ["-p #{options[:port]}", "-o UserKnownHostsFile=/dev/null",
"-o StrictHostKeyChecking=no", "-o IdentitiesOnly=yes",
"-i #{options[:private_key_path]}", "-o LogLevel=ERROR"]
command_options << "-o ForwardAgent=yes" if env.config.ssh.forward_agent
if env.config.ssh.forward_x11
# Both are required so that no warnings are shown regarding X11
command_options << "-o ForwardX11=yes"
command_options << "-o ForwardX11Trusted=yes"
end
unless opts[:local_path]
raise "rsync needs a :local_path"
end
unless opts[:remote_path]
raise "rsync needs a :remote_path"
end
if opts[:flags].nil?
raise "rsync needs :flags (or set to false)"
end
opts[:flags] ||= ""
env.ui.info "Ensuring #{opts[:remote_path]} on remote"
execute do |ssh|
ssh.exec!("mkdir -p #{opts[:remote_path]}")
end
l = opts[:local_path]
r = "#{options[:username]}@#{options[:host]}:#{opts[:remote_path]}"
cmd = %Q{rsync #{opts[:flags]} -e "ssh #{command_options.join(" ")}" #{l} #{r}}.strip
env.ui.info "rsyncing #{l} to #{r}"
env.ui.info "rsync command: #{cmd}"
system cmd
end
end
end
class ChefSoloRsync < Vagrant::Provisioners::ChefSolo
class Config < Vagrant::Provisioners::ChefSolo::Config
end
def share_cookbook_folders
host_cookbook_paths.each_with_index do |cookbook, i|
vm.ssh.rsync :flags => "-rlpt --delete", :local_path => "#{cookbook}/.", :remote_path => cookbook_path(i)
end
end
def share_role_folders
host_role_paths.each_with_index do |role, i|
vm.ssh.rsync :flags => "-rlpt --delete", :local_path => "#{role}/.", :remote_path => role_path(i)
end
end
def share_data_bags_folders
host_data_bag_paths.each_with_index do |data_bag, i|
vm.ssh.rsync :flags => "-rlpt --delete", :local_path => "#{data_bag}/.", :remote_path => data_bag_path(i)
end
end
end
def deploy(cwd)
env = Vagrant::Environment.new(:cwd => cwd)
env.ui = Vagrant::UI::Shell.new(env, Thor::Base.shell.new)
env.load!
env.vms.each_pair do |key, vm|
env.vm = vm
# custom for my purposes
vm.ssh.execute do |ssh|
ssh.sudo! %Q{
if [ ! -e /etc/chef_bootstap_complete ]; then
apt-get remove -y dovecot-postfix postfix dovecot-common dovecot-imapd dovecot-pop3d dovecot-postfix apache2 apache2-mpm-prefork apache2-utils apache2.2-bin apache2.2-common libapache2-mod-php5
apt-get autoremove
apt-get clean
apt-get update
apt-get install -y rsync keychain ruby build-essential libopenssl-ruby ruby-dev rubygems
touch /etc/profile.d/keychain.sh
echo 'keychain --inherit any-once id_rsa id_dsa > /dev/null 2>&1' | tee /etc/profile.d/keychain.sh
echo '. ~/.keychain/`uname -n`-sh > /dev/null 2>&1' | tee -a /etc/profile.d/keychain.sh
chmod 755 /etc/profile.d/keychain.sh
gembin=$(gem environment gemdir)/bin
echo 'export PATH=$PATH'":$gembin" | tee /etc/profile.d/system-gempath.sh
chmod 755 /etc/profile.d/system-gempath.sh
source /etc/profile.d/system-gempath.sh
gem install chef --no-ri --no-rdoc
touch /etc/chef_bootstap_complete
fi
}.strip do |channel, type, data|
env.ui.info("#{data}: #{type}")
end
end
env.config.vm.provisioners.each do |provisioner|
instance = provisioner.provisioner.new(Vagrant::Action::Environment.new(env), provisioner.config)
instance.prepare
instance.provision!
end
end
end
# Example Vagrantfile:
#
# Vagrant::Config.run do |config|
# # The ssh details to your remote server
# config.ssh.port = 22
# config.ssh.username = "root"
# config.ssh.private_key_path = "~/.ssh/id_rsa"
# config.ssh.host = "33.33.33.33"
# config.ssh.forward_agent = true
# # provision config just like :chef_solo, except cookbooks get rsynced to server
# config.vm.provision ChefSoloRsync do |chef|
# chef.log_level = :debug
# chef.cookbooks_path = %w( ../../cookbooks . )
# chef.json.merge!({...})
# chef.add_recipe ...
# end
# end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment