Created
December 14, 2016 17:46
-
-
Save ejoubaud/e1d7099f7234a70cf49621a9e0300b3d to your computer and use it in GitHub Desktop.
Checks the status and AMI ID of instances in the ASG of a CloudFormation stack (used to test an AMI rotation script)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'aws-sdk' | |
require 'forwardable' | |
DEFAULT_REGION = "us-east-1".freeze | |
STACK_NAMES = ['market-dj'].freeze | |
class Instance | |
extend Forwardable | |
delegate [:image_id] => :ec2_instance_resource | |
delegate [:health_status, :lifecycle_state] => :as_instance_resource | |
attr_reader :instance_id | |
def initialize(instance_id, client_options = { region: DEFAULT_REGION }, ec2_instance_resource: nil, as_instance_resource: nil) | |
@instance_id, @client_options = instance_id, client_options | |
@ec2_instance_resource, @as_instance_resource = ec2_instance_resource, as_instance_resource | |
end | |
private | |
def ec2_instance_resource | |
@ec2_instance_resource ||= ec2_client.describe_instances(instance_ids: [@instance_id]).reservations.first.instances.first | |
end | |
def as_instance_resource | |
@as_instance_resource ||= ec2_client.describe_instances(instance_ids: [@instance_id]).reservations.first.instances.first | |
end | |
def ec2_client | |
@ec2_client ||= Aws::EC2::Client.new(@client_options) | |
end | |
def as_client | |
@as_client ||= Aws::AutoScaling::Client.new(@client_options) | |
end | |
end | |
class Asg | |
def initialize(asg_name, client_options = { region: DEFAULT_REGION }) | |
@asg_name, @client_options = asg_name, client_options | |
end | |
def latest_ami_id | |
@latest_ami_id ||= as_launch_config_resouce.image_id | |
end | |
def instances | |
as_instance_resources = as_asg_resource.instances.group_by(&:instance_id) | |
ec2_instance_resources = ec2_client.describe_instances(instance_ids: as_instance_resources.keys).reservations.flat_map(&:instances).group_by(&:instance_id) | |
as_instance_resources.map do |instance_id, as_instance_resources| | |
as_instance_resource = as_instance_resources.first | |
ec2_instance_resource = ec2_instance_resources[instance_id].first | |
# Passing the resources directly to the Instance allows us to make only 2 queries | |
# (one on the autoscaling client and one on the EC2 client) for all the instances | |
# rather than 2 queries for each instance | |
Instance.new(instance_id, @client_options, as_instance_resource: as_instance_resource, ec2_instance_resource: ec2_instance_resource) | |
end | |
end | |
def instance_statuses | |
instances.map do |i| | |
{ :id => i.instance_id, :health => i.health_status, :state => i.lifecycle_state, :ami => i.image_id } | |
end | |
end | |
private | |
def as_asg_resource | |
as_client.describe_auto_scaling_groups(auto_scaling_group_names: [@asg_name]).auto_scaling_groups.first | |
end | |
def as_launch_config_resource | |
as_client.describe_launch_configurations(launch_configuration_names: [as_asg_resource.launch_configuration_name]).launch_configurations.first | |
end | |
def as_client | |
@as_client ||= Aws::AutoScaling::Client.new(@client_options) | |
end | |
def ec2_client | |
@ec2_client ||= Aws::EC2::Client.new(@client_options) | |
end | |
end | |
class Stack | |
def initialize(stack_name, client_options = { region: DEFAULT_REGION }) | |
@stack_name, @client_options = stack_name, client_options | |
end | |
def asg | |
@asg ||= Asg.new(asg_name, @client_options) | |
end | |
private | |
def asg_name | |
cf_asg_resource.physical_resource_id | |
end | |
def cf_asg_resource | |
@cf_asg_summary ||= cf_client.describe_stack_resources(stack_name: @stack_name, logical_resource_id: 'AutoScalingGroup').stack_resources.first | |
end | |
def cf_client | |
@cf_client ||= ::Aws::CloudFormation::Client.new(@client_options) | |
end | |
end | |
last_state = nil | |
while true do | |
new_state = Stack.new('market-dj').asg.instance_statuses | |
if new_state != last_state | |
p Time.now | |
new_state.each do |i| | |
print "#{i[:id]} #{i[:ami]} #{i[:state]} #{i[:health]}\n" | |
end | |
last_state = new_state | |
end | |
sleep 0.1 | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment