Class: MinimalPipeline::Ec2

Inherits:
Object
  • Object
show all
Defined in:
lib/minimal_pipeline/ec2.rb

Overview

# 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')

Instance Method Summary collapse

Constructor Details

#initializeEc2

Initializes a `Ec2` client Requires environment variables `AWS_REGION` or `region` to be set.


20
21
22
23
24
25
# 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

Instance Method Details

#copy_image(image_id, image_name, kms_key_id = nil) ⇒ String

Copy an AMI

The new image will be encrypted. You can optionally copy across regions

Parameters:

  • image_id (String)

    The AMI ID to copy

  • image_name (String)

    The name of the new image

  • kms_key_id (String) (defaults to: nil)

    Non-default KMS key ID to use for encryption

Returns:

  • (String)

    The newly created AMI ID


145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# 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

#copy_snapshot(snapshot_id, kms_key_id = nil, encrypted = true) ⇒ String

Create a copy of an existing snapshot

Parameters:

  • snapshot_id (String)

    The ID of the snapshot to copy

  • kms_key_id (String) (defaults to: nil)

    The ID of the KMS key. Omit to use default

  • encrypted (Boolean) (defaults to: true)

    Whether or not the volume is encrypted

Returns:

  • (String)

    The ID of the newly created snapshot


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 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_snapshots_in_new_account(block_device_mappings, kms_key_id = nil) ⇒ Array

Copy the snapshots from the original account into the new one

Parameters:

  • block_device_mappings (Array)

    Block device mappings with snapshots

  • kms_key_id (String) (defaults to: nil)

    The ID of the KMS key. Omit to use default

Returns:

  • (Array)

    Block device mappings with updated snapshot ids


123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/minimal_pipeline/ec2.rb', line 123

def (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_snapshots_for_account(ami_id, account_id, kms_key_id = nil) ⇒ Array

Prepare volume snapshots of an AMI for a new account

Parameters:

  • ami_id (String)

    The ID of the AMI to prepare

  • account_id (String)

    The ID of the AWS account to prepare

  • kms_key_id (String) (defaults to: nil)

    The ID of the KMS key. Omit to use default

Returns:

  • (Array)

    Block device mappings discovered from the AMI


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/minimal_pipeline/ec2.rb', line 79

def (ami_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'
    (new_snapshot_id, )
    puts "new snapshot has been modified for the #{} account"
    mapping.ebs.snapshot_id = new_snapshot_id
    new_mappings << mapping.to_hash
    puts '==========================================='
  end

  new_mappings
end

#register_ami(block_device_mappings, ami_name, ena_support: false) ⇒ String

Register a new AMI based on block device mappings Currently only supports x86_64 HVM

Parameters:

  • block_device_mappings (Array)

    Block device mappings with snapshots

  • ami_name (String)

    The name of the AMI to create

Returns:

  • (String)

    The AMI ID of the newly created AMI


105
106
107
108
109
110
111
112
113
114
115
116
# 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

#unlock_ami_for_account(snapshot_id, account_id) ⇒ Object

Update permissions to grant access to an AMI on another account

Parameters:

  • snapshot_id (String)

    The ID of the snapshot to adjust

  • account_id (String)

    The AWS account to grant access to


64
65
66
67
68
69
70
71
# File 'lib/minimal_pipeline/ec2.rb', line 64

def (snapshot_id, )
  @client.modify_snapshot_attribute(
    attribute: 'createVolumePermission',
    operation_type: 'add',
    snapshot_id: snapshot_id,
    user_ids: []
  )
end

#wait_for_image(image_id) ⇒ Object

Block processing until new image is ready

Parameters:

  • image_id (String)

    The ID of the new image


165
166
167
168
169
170
171
# 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

#wait_for_snapshot(snapshot_id) ⇒ Object

Block processing until new snapshot is ready

Parameters:

  • snapshot_id (String)

    The ID of the new snapshot


30
31
32
33
34
35
36
# 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