Skip to content

Instantly share code, notes, and snippets.

@xionon
Last active January 4, 2016 16:39
Show Gist options
  • Save xionon/8649178 to your computer and use it in GitHub Desktop.
Save xionon/8649178 to your computer and use it in GitHub Desktop.
Use rake and knife-solo to cook or bootstrap multiple EC2 instances. Automatically load EC2 IP addresses via the SDK
source 'https://rubygems.org'
gem 'rake'
gem 'aws-sdk'
gem 'dotenv'
gem 'chef'
gem 'librarian-chef'
gem 'knife-solo'
gem 'knife-solo_data_bag'
# Rather than running knife solo cook for each individual instance, this script loads the instance IPs via the AWS SDK and
# shells out to knife solo. For less than 5 total instances, this seems to make sense.
#
# We'll be using the same tags that cap-ec2 uses: Name, Roles, and Stage. We'll also have a Bootstrapped tag,
# which should default to false. Make sure you set that on new instances!
require 'aws-sdk'
require 'dotenv/tasks'
AWS.config(
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
)
ENVIRONMENT = ENV['ENVIRONMENT'].to_s != '' ? ENV['ENVIRONMENT'] : 'beta'
def ec2
@ec2 ||= AWS::EC2.new
end
def running_instances
@running_instances ||= ec2.instances.filter('instance-state-name', 'running').tagged("Stage").tagged_values(ENVIRONMENT)
end
def make_opts(hash)
hash.inject([]) do |m, kv|
m << "--#{kv[0]} '#{kv[1]}'"
m
end.join ' '
end
def default_opts(instance)
# We use the Roles tag to determine what chef roles should be applied
roles = instance.tags["Roles"].split(',')
run_list = roles.map {|r| "role[#{r.strip}]" }.join(",")
# Use your own ssh key to connect
make_opts('identity-file' => '/full/path/to/public.pem',
'environment' => ENVIRONMENT,
# role[solo] is optional, nice to have a shared config role, though
. 'run-list' => "role[solo],#{run_list}")
end
desc "Cook all the EC2 instances"
task :cook do
running_instances.each do |instance|
sh "knife solo cook ec2-user@#{instance.ip_address} #{default_opts(instance)}"
end
end
# knife solo bootstrap is a fairly slow task, because it installs chef omnibus.
desc "Bootstrap apps"
task :bootstrap do
running_instances.tagged("Bootstrapped").tagged_values("false").each do |instance|
sh "knife solo bootstrap ec2-user@#{instance.ip_address} #{default_opts(instance)}"
instance.tags["Bootstrapped"] = true
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment