Saturday, July 12, 2008

Using Capistrano to Bundle Amazon EC2 Images

I've found the following bit of Capistrano script to be useful when tinkering with EC2 images. I can make a change and then bundle the image with just one command: cap admin:bundle

The most difficult part of this script was finding out how to upload files to the remote instance using scp. The rest is fairly straightforward. I am only posting this script because I haven't seen this functionality posted anywhere else.

# capfile for Amazon EC2 Bundling. Normally, a yaml file would be
# hold configuration parameters. I am using environment 
# variables because they are also used by the EC2
# programs - why have the information in two places?

# This script assumes that you are only bundling one
# instance at a time.

# EC2 Instance Hostname to be bundled.
ec2_hostname = ENV['BUNDLE_EC2_HOSTNAME']

# S3 Bucket Name (where the bundle is uploaded)
s3_bucket_name = ENV['BUNDLE_S3_BUCKET_NAME']

# If you are using ElasticFox (and if not, why not?) that
# you created in the KeyPairs tab. Specify the full
# path to the file.
ssh_keypair_file = ENV['BUNDLE_SSH_PRIVATE_KEY_FILESPEC']

# Amazon Web Services Info
amazon_account_id    = ENV['AMAZON_ACCOUNT_ID']
amazon_access_key_id   = ENV['AMAZON_ACCESS_KEY_ID']
amazon_secret_access_key = ENV['AMAZON_SECRET_ACCESS_KEY']

# Amazon EC2 Info
cert_filespec     = ENV['EC2_CERT']
private_key_filespec   = ENV['EC2_PRIVATE_KEY']

# We are only dealing with one EC2 instance.
role :libs, "#{ec2_hostname}"

# I like working with ElasticFox which seems to only
# support using the root user.
set :user, "root"

ssh_options[:keys] = ssh_keypair_file

namespace :admin do

 task :bundle do

  # Copy the certificate and private key to the remote computer.
  upload("#{private_key_filespec}", "/mnt", :via => :scp) 
  upload("#{cert_filespec}", "/mnt", :via => :scp)

  # Extract just the filename from the filespec.
  private_key_filename_start = private_key_filespec.rindex('/') + 1
  private_key_filename_end = private_key_filespec.length
  private_key_filename = private_key_filespec[private_key_filename_start, private_key_filename_end]

  # Extract just the filename from the filespec.
  cert_filename_start = cert_filespec.rindex('/') + 1
  cert_filename_end = cert_filespec.length
  cert_filename = cert_filespec[cert_filename_start, cert_filename_end]

  # Remove any old image.
  run "rm --force /mnt/image /mnt/image.*"

  # Create the EC2 Bundle
  #run "ec2-bundle-vol -d /mnt -c /mnt/#{cert_filename} -k /mnt/#{private_key_filename} -u #{amazon_account_id} -r i386"

  # Upload the EC2 Bundle to S3
  run "ec2-upload-bundle -b #{s3_bucket_name} -m /mnt/image.manifest.xml -a #{amazon_access_key_id} -s #{amazon_secret_access_key}"

  exec "ec2-register #{s3_bucket_name}/image.manifest.xml"

 end

 task :update do
  run "apt-get update"
  run "apt-get upgrade -y"
 end

end
Zemanta Pixie
Post a Comment