module Admiral::Util::OpsWorks

Public Instance Methods

all_availability_zones() click to toggle source
# File lib/admiral-opsworks/util.rb, line 34
def all_availability_zones
  ec2 = AWS::EC2.new
  ec2.availability_zones.map(&:name)
end
attach_ebs_volumes(instance_id, volume_ids) click to toggle source
# File lib/admiral-opsworks/util.rb, line 48
def attach_ebs_volumes(instance_id, volume_ids)
  volume_ids.each do |volume_id|
    puts "[admiral] Attaching EBS volume #{volume_id} to instance #{instance_id}"
    opsworks.assign_volume({:volume_id => volume_id, :instance_id => instance_id})
  end
end
create_instance(stack_id, layer_id, az) click to toggle source
# File lib/admiral-opsworks/util.rb, line 66
def create_instance(stack_id, layer_id, az)
  opsworks.create_instance({:stack_id => stack_id,
                            :layer_ids => [layer_id],
                            :instance_type => ENV['INSTANCE_TYPE'] || 't2.small',
                            :install_updates_on_boot => !ENV['SKIP_INSTANCE_PACKAGE_UPDATES'],
                            :availability_zone => az})
end
detach_ebs_volumes(instance_id) click to toggle source
# File lib/admiral-opsworks/util.rb, line 55
def detach_ebs_volumes(instance_id)
  response = opsworks.describe_volumes(:instance_id => instance_id)
  volume_ids = response[:volumes].map { |v| v[:volume_id] }
  volume_ids.each do |volume_id|
    puts "[admiral] Detaching EBS volume #{volume_id} from instance #{instance_id}"
    opsworks.unassign_volume(:volume_id => volume_id)
  end

  volume_ids
end
get_all_instances(layer_id) click to toggle source
# File lib/admiral-opsworks/util.rb, line 39
def get_all_instances(layer_id)
  response = opsworks.describe_instances({:layer_id => layer_id})
  response[:instances]
end
instance_online?(instance_id) click to toggle source
# File lib/admiral-opsworks/util.rb, line 11
def instance_online?(instance_id)
  response = opsworks.describe_instances(:instance_ids => [instance_id])
  response[:instances].first[:status] == "online"
end
instance_status(instance_id) click to toggle source
# File lib/admiral-opsworks/util.rb, line 16
def instance_status(instance_id)
  begin
    response = opsworks.describe_instances(:instance_ids => [instance_id])
  rescue AWS::OpsWorks::Errors::ResourceNotFoundException
    return "nonexistent"
  end
  response[:instances].first[:status].tap do |status|
    raise "Instance #{instance_id} has a failed status #{status}" if status =~ /fail|error/i
  end
end
opsworks() click to toggle source
# File lib/admiral-opsworks/util.rb, line 7
def opsworks
  AWS::OpsWorks::Client.new(region: 'us-east-1') # opsworks command-and-control is us-east-1 ONLY ;)
end
ssh_to_instance(instance, ssh_key_name, username = 'ec2-user') click to toggle source
# File lib/admiral-opsworks/util.rb, line 44
def ssh_to_instance(instance, ssh_key_name, username = 'ec2-user')
  Kernel.exec "ssh -i ~/.ssh/#{ssh_key_name}.pem #{username}@#{instance[:public_ip]}"
end
update_instances(stack_id, layer_id, count) click to toggle source
# File lib/admiral-opsworks/util.rb, line 74
def update_instances(stack_id, layer_id, count)
  azs = all_availability_zones
  existing_instances = get_all_instances(layer_id)
  count_to_create = count.to_i - existing_instances.size
  new_instances = (1..count_to_create).map do |i|
    instance = create_instance(stack_id, layer_id, azs[(existing_instances.size + i) % azs.size])
    puts "[admiral] Created instance #{instance[:instance_id]}; now starting up."
    opsworks.start_instance(:instance_id => instance[:instance_id])
    instance
  end

  new_instances.each do |instance|
    wait_for_instance(instance[:instance_id], "online")
  end

  puts "Replacing existing instances.." if existing_instances.size > 0

  existing_instances.each do |instance|
    puts "[admiral] Stopping instance #{instance[:hostname]}, id: #{instance[:instance_id]}"
    opsworks.stop_instance({:instance_id => instance[:instance_id]})
    wait_for_instance(instance[:instance_id], "stopped")
    ebs_volume_ids = detach_ebs_volumes(instance[:instance_id])

    puts "[admiral] Creating replacement instance"
    replacement = create_instance(stack_id, layer_id, instance[:availability_zone])
    attach_ebs_volumes(replacement[:instance_id], ebs_volume_ids)

    puts "[admiral] Starting new instance, id: #{replacement[:instance_id]}"
    opsworks.start_instance(:instance_id => replacement[:instance_id])
    wait_for_instance(replacement[:instance_id], "online")

    puts "[admiral] Deleting old instance #{instance[:hostname]}, #{instance[:instance_id]}"
    opsworks.delete_instance(:instance_id => instance[:instance_id])
  end
end
wait_for_instance(instance_id, status) click to toggle source
# File lib/admiral-opsworks/util.rb, line 27
def wait_for_instance(instance_id, status)
  while (ins_status = instance_status(instance_id)) != status
    puts "[admiral] Waiting for #{instance_id} instance to become #{status}. Current status: #{ins_status}"
    sleep 10
  end
end