diff --git a/lib/aws-missing-tools/aws-ha-release/aws-ha-release.rb b/lib/aws-missing-tools/aws-ha-release/aws-ha-release.rb index 52678a0..09d1dc7 100755 --- a/lib/aws-missing-tools/aws-ha-release/aws-ha-release.rb +++ b/lib/aws-missing-tools/aws-ha-release/aws-ha-release.rb @@ -94,9 +94,11 @@ class AwsHaRelease end def instances_inservice?(load_balancer) - load_balancer.instances.health.each do |health| - unless health[:state] == 'InService' - puts "Instance #{health[:instance].id} is currently #{health[:state]} on load balancer #{load_balancer.name}." + return false if load_balancer.instances.count != @group.desired_capacity + + load_balancer.instances.health.each do |instance_health| + unless instance_health[:state] == 'InService' + puts "Instance #{instance_health[:instance].id} is currently #{instance_health[:state]} on load balancer #{load_balancer.name}." return false end diff --git a/spec/aws-missing-tools/aws-ha-release/aws-ha-release_spec.rb b/spec/aws-missing-tools/aws-ha-release/aws-ha-release_spec.rb index 34e3bf1..4dbe0e2 100644 --- a/spec/aws-missing-tools/aws-ha-release/aws-ha-release_spec.rb +++ b/spec/aws-missing-tools/aws-ha-release/aws-ha-release_spec.rb @@ -14,6 +14,10 @@ describe 'aws-ha-release' do let(:as) { AWS::FakeAutoScaling.new } + let(:instance_one) { AWS::FakeEC2::Instance.new } + + let(:instance_two) { AWS::FakeEC2::Instance.new } + before do AWS::AutoScaling.stub(:new).and_return(as) IO.any_instance.stub(:puts) @@ -71,47 +75,82 @@ describe 'aws-ha-release' do describe 'determining if instances are in service' do before do @group = as.groups.create opts[:as_group_name] + @group.update(desired_capacity: 2) @aws_ha_release = AwsHaRelease.new(opts) end it 'checks all instances across a given load balancer' do - load_balancer = AWS::FakeELB::LoadBalancer.new 'test_load_balancer_01' + load_balancer = AWS::FakeELB::LoadBalancer.new 'test_load_balancer_01', [ + { + instance: instance_one, + healthy: true + }, + { + instance: instance_two, + healthy: false + } + ] expect(@aws_ha_release.instances_inservice?(load_balancer)).to eq false - load_balancer.instances.health[1] = { - instance: AWS::FakeEC2::Instance.new, - description: 'N/A', - state: 'InService', - reason_code: 'N/A' - } - + load_balancer.instances.make_instance_healthy(instance_two) expect(@aws_ha_release.instances_inservice?(load_balancer)).to eq true end it 'checks all instances across an array of load balancers' do - load_balancers = [AWS::FakeELB::LoadBalancer.new('test_load_balancer_01'), AWS::FakeELB::LoadBalancer.new('test_load_balancer_02')] + load_balancers = [ + AWS::FakeELB::LoadBalancer.new('test_load_balancer_01', [ + { + instance: instance_one, + healthy: true + }, + { + instance: instance_two, + healthy: false + } + ]), AWS::FakeELB::LoadBalancer.new('test_load_balancer_02', [ + { + instance: instance_one, + healthy: true + }, + { + instance: instance_two, + healthy: false + } + ]) + ] expect(@aws_ha_release.all_instances_inservice?(load_balancers)).to eq false - load_balancers[0].instances.health[1] = { - instance: AWS::FakeEC2::Instance.new, - description: 'N/A', - state: 'InService', - reason_code: 'N/A' - } - + load_balancers[0].instances.make_instance_healthy(instance_two) expect(@aws_ha_release.all_instances_inservice?(load_balancers)).to eq false - load_balancers[1].instances.health[1] = { - instance: AWS::FakeEC2::Instance.new, - description: 'N/A', - state: 'InService', - reason_code: 'N/A' - } - + load_balancers[1].instances.make_instance_healthy(instance_two) expect(@aws_ha_release.all_instances_inservice?(load_balancers)).to eq true end + + it 'requires the number of inservice instances to match the desired capacity' do + load_balancer = AWS::FakeELB::LoadBalancer.new 'test_load_balancer_01', [ + { + instance: instance_one, + healthy: true + }, + { + instance: instance_two, + healthy: true + } + ] + + @group.update(desired_capacity: 3) + + expect(@aws_ha_release.instances_inservice?(load_balancer)).to eq false + + instance_three = AWS::FakeEC2::Instance.new + load_balancer.instances.register instance_three + load_balancer.instances.make_instance_healthy(instance_three) + + expect(@aws_ha_release.instances_inservice?(load_balancer)).to eq true + end end describe '#deregister_instance' do @@ -121,11 +160,26 @@ describe 'aws-ha-release' do end it 'deregisters an instance across all load balancers' do - instance_one = AWS::FakeEC2::Instance.new - instance_two = AWS::FakeEC2::Instance.new - - elb_one = AWS::FakeELB::LoadBalancer.new 'test_load_balancer_01' - elb_two = AWS::FakeELB::LoadBalancer.new 'test_load_balancer_02' + elb_one = AWS::FakeELB::LoadBalancer.new 'test_load_balancer_01', [ + { + instance: instance_one, + healthy: true + }, + { + instance: instance_two, + healthy: true + } + ] + elb_two = AWS::FakeELB::LoadBalancer.new 'test_load_balancer_02', [ + { + instance: instance_one, + healthy: true + }, + { + instance: instance_two, + healthy: true + } + ] elb_one.instances.register instance_one elb_one.instances.register instance_two diff --git a/spec/support/fake_elb.rb b/spec/support/fake_elb.rb index 669920f..faba21c 100644 --- a/spec/support/fake_elb.rb +++ b/spec/support/fake_elb.rb @@ -4,14 +4,11 @@ module AWS end class LoadBalancer - attr_reader :name + attr_reader :name, :instances - def initialize(name, options = {}) + def initialize(name, instances_and_healths) @name = name - end - - def instances - @instances ||= InstanceCollection.new + @instances ||= InstanceCollection.new(instances_and_healths) end end @@ -21,7 +18,15 @@ module AWS end class InstanceCollection < Array - def initialize + attr_reader :health + + def initialize(instances_and_healths) + @health = [] + + instances_and_healths.each do |instance_and_health| + self << instance_and_health[:instance] + instance_and_health[:healthy] ? make_instance_healthy(instance_and_health[:instance]) : make_instance_unhealthy(instance_and_health[:instance]) + end end def register(*instances) @@ -34,21 +39,40 @@ module AWS end end - def health - @health ||= [ - { - instance: AWS::FakeEC2::Instance.new, - description: 'N/A', - state: 'InService', - reason_code: 'N/A' - }, - { - instance: AWS::FakeEC2::Instance.new, - description: 'Instance has failed at least the UnhealthyThreshold number of health checks consecutively.', - state: 'OutOfService', - reason_code: 'Instance' - } - ] + def make_instance_healthy(instance) + opts = { + instance: instance, + description: 'N/A', + state: 'InService', + reason_code: 'N/A' + } + + @health.each_with_index do |health, i| + if health[:instance] == instance + @health[i] = opts + return + end + end + + @health << opts + end + + def make_instance_unhealthy(instance) + opts = { + instance: instance, + description: 'Instance has failed at least the UnhealthyThreshold number of health checks consecutively.', + state: 'OutOfService', + reason_code: 'Instance' + } + + @health.each_with_index do |health, i| + if health[:instance] == instance + @health[i] = opts + return + end + end + + @health << opts end end end