class MinimalPipeline::Ec2
# For Account 1: ec2 = MinimalPipeline::Ec2.new
block_device_mappings = ec2.prepare_snapshots_for_account('ami-id',
'account-id')
# Promote AMI via SQS sqs = MinimalPipeline::Sqs.new
sqs.send_message('queue-name', block_device_mappings.to_json)
# For Account 2, after getting block_device_mappings ec2 = MinimalPipeline::Ec2.new
new_mappings = ec2.copy_snapshots_in_new_account(block_device_mappings) ec2.register_ami(new_mappings, 'ami-name')
Public Class Methods
Initializes a `Ec2` client Requires environment variables `AWS_REGION` or `region` to be set.
# File lib/minimal_pipeline/ec2.rb, line 20 def initialize raise 'You must set env variable AWS_REGION or region.' \ if ENV['AWS_REGION'].nil? && ENV['region'].nil? @region = ENV['AWS_REGION'] || ENV['region'] @client = Aws::EC2::Client.new(region: 'us-east-1') end
Public Instance Methods
Copy an AMI
The new image will be encrypted. You can optionally copy across regions
@param image_id [String] The AMI ID to copy @param image_name [String] The name of the new image @param kms_key_id [String] Non-default KMS key ID to use for encryption @return [String] The newly created AMI ID
# File lib/minimal_pipeline/ec2.rb, line 145 def copy_image(image_id, image_name, kms_key_id = nil) params = { name: image_name, encrypted: true, source_image_id: image_id, source_region: @region } params['kms_key_id'] = kms_key_id if kms_key_id response = @client.copy_image(params) new_image_id = response.image_id wait_for_image(new_image_id) new_image_id end
Create a copy of an existing snapshot
@param snapshot_id [String] The ID of the snapshot to copy @param kms_key_id [String] The ID of the KMS key. Omit to use default @param encrypted [Boolean] Whether or not the volume is encrypted @return [String] The ID of the newly created snapshot
# File lib/minimal_pipeline/ec2.rb, line 44 def copy_snapshot(snapshot_id, kms_key_id = nil, encrypted = true) params = { encrypted: encrypted, source_region: @region, source_snapshot_id: snapshot_id } params[:kms_key_id] = kms_key_id if kms_key_id new_snapshot_id = @client.copy_snapshot(params).snapshot_id puts "new snapshot ID: #{new_snapshot_id}" wait_for_snapshot(new_snapshot_id) new_snapshot_id end
Copy the snapshots from the original account into the new one
@param block_device_mappings [Array] Block device mappings with snapshots @param kms_key_id [String] The ID of the KMS key. Omit to use default @return [Array] Block device mappings with updated snapshot ids
# File lib/minimal_pipeline/ec2.rb, line 123 def copy_snapshots_in_new_account(block_device_mappings, kms_key_id = nil) new_mappings = [] block_device_mappings.each do |mapping| snapshot_id = mapping['ebs']['snapshot_id'] new_snapshot_id = copy_snapshot(snapshot_id, kms_key_id) mapping['ebs']['snapshot_id'] = new_snapshot_id mapping['ebs'].delete('encrypted') new_mappings << mapping end new_mappings end
Prepare volume snapshots of an AMI for a new account
@param ami_id [String] The ID of the AMI to prepare @param account_id [String] The ID of the AWS account to prepare @param kms_key_id [String] The ID of the KMS key. Omit to use default @return [Array] Block device mappings discovered from the AMI
# File lib/minimal_pipeline/ec2.rb, line 79 def prepare_snapshots_for_account(ami_id, account_id, kms_key_id = nil) images = @client.describe_images(image_ids: [ami_id]) block_device_mappings = images.images[0].block_device_mappings new_mappings = [] block_device_mappings.each do |mapping| snapshot_id = mapping.ebs.snapshot_id puts "old snapshot ID: #{snapshot_id}" new_snapshot_id = copy_snapshot(snapshot_id, kms_key_id) puts 'modifying new snapshot attribute' unlock_ami_for_account(new_snapshot_id, account_id) puts "new snapshot has been modified for the #{account_id} account" mapping.ebs.snapshot_id = new_snapshot_id new_mappings << mapping.to_hash puts '===========================================' end new_mappings end
Register a new AMI based on block device mappings Currently only supports x86_64 HVM
@param block_device_mappings [Array] Block device mappings with snapshots @param ami_name [String] The name of the AMI to create @return [String] The AMI ID of the newly created AMI
# File lib/minimal_pipeline/ec2.rb, line 105 def register_ami(block_device_mappings, ami_name, ena_support: false) response = @client.register_image( architecture: 'x86_64', block_device_mappings: block_device_mappings, ena_support: ena_support, name: ami_name, root_device_name: '/dev/sda1', virtualization_type: 'hvm' ) response.image_id end
Update permissions to grant access to an AMI on another account
@param snapshot_id [String] The ID of the snapshot to adjust @param account_id [String] The AWS account to grant access to
# File lib/minimal_pipeline/ec2.rb, line 64 def unlock_ami_for_account(snapshot_id, account_id) @client.modify_snapshot_attribute( attribute: 'createVolumePermission', operation_type: 'add', snapshot_id: snapshot_id, user_ids: [account_id] ) end
Block processing until new image is ready
@param image_id [String] The ID of the new image
# File lib/minimal_pipeline/ec2.rb, line 165 def wait_for_image(image_id) puts "waiting on new image #{image_id} to be available" @client.wait_until(:image_available, image_ids: [image_id]) puts "New image #{image_id} is available" rescue Aws::Waiters::Errors::WaiterFailed => error puts "failed waiting for image to be available: #{error.message}" end
Block processing until new snapshot is ready
@param snapshot_id [String] The ID of the new snapshot
# File lib/minimal_pipeline/ec2.rb, line 30 def wait_for_snapshot(snapshot_id) puts "waiting on new snapshot #{snapshot_id} to be ready" @client.wait_until(:snapshot_completed, snapshot_ids: [snapshot_id]) puts "New snapshot #{snapshot_id} is ready" rescue Aws::Waiters::Errors::WaiterFailed => error puts "failed waiting for snapshot to be ready: #{error.message}" end