ruby_aem_aws 0.9.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ruby_aem_aws/abstract/cloudwatch.rb +81 -0
  3. data/lib/ruby_aem_aws/{component/abstract_component.rb → abstract/component.rb} +4 -2
  4. data/lib/ruby_aem_aws/{component/abstract_grouped_component.rb → abstract/grouped_component.rb} +1 -1
  5. data/lib/ruby_aem_aws/{component/abstract_single_component.rb → abstract/single_component.rb} +1 -1
  6. data/lib/ruby_aem_aws/{component/abstract_snapshot.rb → abstract/snapshot.rb} +1 -1
  7. data/lib/ruby_aem_aws/{component/abstract_stackmanager.rb → abstract/stackmanager.rb} +10 -0
  8. data/lib/ruby_aem_aws/{consolidated_stack.rb → architecture/consolidated_stack.rb} +21 -7
  9. data/lib/ruby_aem_aws/architecture/full_set_stack.rb +141 -0
  10. data/lib/ruby_aem_aws/architecture/stack_manager.rb +44 -0
  11. data/lib/ruby_aem_aws/client/cloudwatch.rb +87 -0
  12. data/lib/ruby_aem_aws/{component/mixins → client}/dynamo_db.rb +0 -0
  13. data/lib/ruby_aem_aws/{component/mixins → client}/s3.rb +1 -1
  14. data/lib/ruby_aem_aws/{component/mixins → client}/sns_topic.rb +0 -0
  15. data/lib/ruby_aem_aws/component/author.rb +16 -8
  16. data/lib/ruby_aem_aws/component/author_dispatcher.rb +19 -16
  17. data/lib/ruby_aem_aws/component/author_primary.rb +14 -11
  18. data/lib/ruby_aem_aws/component/author_publish_dispatcher.rb +14 -12
  19. data/lib/ruby_aem_aws/component/author_standby.rb +14 -12
  20. data/lib/ruby_aem_aws/component/chaos_monkey.rb +16 -13
  21. data/lib/ruby_aem_aws/component/orchestrator.rb +16 -13
  22. data/lib/ruby_aem_aws/component/publish.rb +17 -15
  23. data/lib/ruby_aem_aws/component/publish_dispatcher.rb +19 -16
  24. data/lib/ruby_aem_aws/component/stack_manager_resources.rb +19 -11
  25. data/lib/ruby_aem_aws/error.rb +7 -0
  26. data/lib/ruby_aem_aws/mixins/healthy_count_verifier.rb +148 -0
  27. data/lib/ruby_aem_aws/{component/mixins/healthy_count_verifier.rb → mixins/healthy_resource_verifier.rb} +29 -43
  28. data/lib/ruby_aem_aws/{component/mixins → mixins}/healthy_state_verifier.rb +1 -1
  29. data/lib/ruby_aem_aws/{component/mixins → mixins}/instance_describer.rb +0 -0
  30. data/lib/ruby_aem_aws/mixins/metric_verifier.rb +186 -0
  31. data/lib/ruby_aem_aws/{component/mixins → mixins}/snapshot_verifier.rb +0 -0
  32. data/lib/ruby_aem_aws.rb +60 -19
  33. metadata +21 -18
  34. data/lib/ruby_aem_aws/component/mixins/metric_verifier.rb +0 -43
  35. data/lib/ruby_aem_aws/full_set_stack.rb +0 -69
  36. data/lib/ruby_aem_aws/stack_manager.rb +0 -31
@@ -12,19 +12,18 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require 'aws-sdk'
16
- require_relative 'abstract_single_component'
17
- require_relative 'abstract_snapshot'
18
- require_relative 'mixins/healthy_state_verifier'
19
- require_relative 'mixins/metric_verifier'
15
+ require_relative '../abstract/single_component'
16
+ require_relative '../abstract/snapshot'
17
+ require_relative '../mixins/healthy_state_verifier'
18
+ require_relative '../mixins/metric_verifier'
20
19
  require_relative 'component_descriptor'
21
- require_relative 'mixins/snapshot_verifier'
20
+ require_relative '../mixins/snapshot_verifier'
22
21
 
23
22
  module RubyAemAws
24
23
  module Component
25
24
  # Interface to a single AWS instance running all three AEM components as a consolidated stack.
26
25
  class AuthorPublishDispatcher
27
- attr_reader :descriptor, :ec2_resource, :cloud_watch_client
26
+ attr_reader :descriptor, :ec2_resource, :cloud_watch_client, :cloud_watch_log_client
28
27
  include AbstractSingleComponent
29
28
  include AbstractSnapshot
30
29
  include HealthyStateVerifier
@@ -35,14 +34,17 @@ module RubyAemAws
35
34
  EC2_NAME = 'AuthorPublishDispatcher'.freeze
36
35
 
37
36
  # @param stack_prefix AWS tag: StackPrefix
38
- # @param ec2_resource AWS EC2 resource
39
- # @param cloud_watch_client AWS CloudWatch client
37
+ # @param params Array of AWS Clients and Resource connections:
38
+ # - CloudWatchClient: AWS Cloudwatch Client.
39
+ # - CloudWatchLogsClient: AWS Cloudwatch Logs Client.
40
+ # - Ec2Resource: AWS EC2 Resource connection.
40
41
  # @return new RubyAemAws::Consolidated::AuthorPublishDispatcher instance
41
- def initialize(stack_prefix, ec2_resource, cloud_watch_client)
42
+ def initialize(stack_prefix, params)
42
43
  @descriptor = ComponentDescriptor.new(stack_prefix,
43
44
  EC2Descriptor.new(EC2_COMPONENT, EC2_NAME))
44
- @ec2_resource = ec2_resource
45
- @cloud_watch_client = cloud_watch_client
45
+ @cloud_watch_client = params[:CloudWatchClient]
46
+ @cloud_watch_log_client = params[:CloudWatchLogsClient]
47
+ @ec2_resource = params[:Ec2Resource]
46
48
  end
47
49
  end
48
50
  end
@@ -12,20 +12,19 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require_relative 'abstract_single_component'
16
- require_relative 'abstract_snapshot'
17
- require_relative 'mixins/healthy_state_verifier'
18
- require_relative 'mixins/metric_verifier'
19
- require_relative 'mixins/snapshot_verifier'
15
+ require_relative '../abstract/single_component'
16
+ require_relative '../abstract/snapshot'
17
+ require_relative '../mixins/healthy_state_verifier'
18
+ require_relative '../mixins/metric_verifier'
19
+ require_relative '../mixins/snapshot_verifier'
20
20
 
21
21
  module RubyAemAws
22
22
  module Component
23
23
  # Interface to the AWS instance running the Author-Standby component of a full-set AEM stack.
24
24
  class AuthorStandby
25
- attr_reader :descriptor, :ec2_resource, :cloud_watch_client
25
+ attr_reader :descriptor, :ec2_resource, :cloud_watch_client, :cloud_watch_log_client
26
26
  include AbstractGroupedComponent
27
27
  include AbstractSnapshot
28
- # Can't verify state by count as there's no ASG.
29
28
  include HealthyStateVerifier
30
29
  include MetricVerifier
31
30
  include SnapshotVerifier
@@ -34,14 +33,17 @@ module RubyAemAws
34
33
  EC2_NAME = 'AEM Author - Standby'.freeze
35
34
 
36
35
  # @param stack_prefix AWS tag: StackPrefix
37
- # @param ec2_resource AWS EC2 resource
38
- # @param cloud_watch_client AWS CloudWatch client
36
+ # @param params Array of AWS Clients and Resource connections:
37
+ # - CloudWatchClient: AWS Cloudwatch Client.
38
+ # - CloudWatchLogsClient: AWS Cloudwatch Logs Client.
39
+ # - Ec2Resource: AWS EC2 Resource connection.
39
40
  # @return new RubyAemAws::FullSet::AuthorStandby
40
- def initialize(stack_prefix, ec2_resource, cloud_watch_client)
41
+ def initialize(stack_prefix, params)
41
42
  @descriptor = ComponentDescriptor.new(stack_prefix,
42
43
  EC2Descriptor.new(EC2_COMPONENT, EC2_NAME))
43
- @ec2_resource = ec2_resource
44
- @cloud_watch_client = cloud_watch_client
44
+ @cloud_watch_client = params[:CloudWatchClient]
45
+ @cloud_watch_log_client = params[:CloudWatchLogsClient]
46
+ @ec2_resource = params[:Ec2Resource]
45
47
  end
46
48
 
47
49
  # @return Aws::EC2::Instance
@@ -12,17 +12,17 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require_relative 'abstract_single_component'
16
- require_relative 'abstract_snapshot'
17
- require_relative 'mixins/healthy_state_verifier'
18
- require_relative 'mixins/metric_verifier'
19
- require_relative 'mixins/snapshot_verifier'
15
+ require_relative '../abstract/single_component'
16
+ require_relative '../abstract/snapshot'
17
+ require_relative '../mixins/healthy_state_verifier'
18
+ require_relative '../mixins/metric_verifier'
19
+ require_relative '../mixins/snapshot_verifier'
20
20
 
21
21
  module RubyAemAws
22
22
  module Component
23
23
  # Interface to the AWS instance running the ChaosMonkey component of a full-set AEM stack.
24
24
  class ChaosMonkey
25
- attr_reader :descriptor, :ec2_resource, :asg_client, :cloud_watch_client
25
+ attr_reader :descriptor, :ec2_resource, :asg_client, :cloud_watch_client, :cloud_watch_log_client
26
26
  include AbstractSingleComponent
27
27
  include AbstractSnapshot
28
28
  # Can't verify state by count as there's no ELB.
@@ -34,16 +34,19 @@ module RubyAemAws
34
34
  EC2_NAME = 'AEM Chaos Monkey'.freeze
35
35
 
36
36
  # @param stack_prefix AWS tag: StackPrefix
37
- # @param ec2_resource AWS EC2 resource
38
- # @param asg_client AWS AutoScalingGroup client
39
- # @param cloud_watch_client AWS CloudWatch client
37
+ # @param params Array of AWS Clients and Resource connections:
38
+ # - AutoScalingClient: AWS AutoScalingGroup Client.
39
+ # - CloudWatchClient: AWS Cloudwatch Client.
40
+ # - CloudWatchLogsClient: AWS Cloudwatch Logs Client.
41
+ # - Ec2Resource: AWS EC2 Resource connection.
40
42
  # @return new RubyAemAws::FullSet::ChaosMonkey
41
- def initialize(stack_prefix, ec2_resource, asg_client, cloud_watch_client)
43
+ def initialize(stack_prefix, params)
42
44
  @descriptor = ComponentDescriptor.new(stack_prefix,
43
45
  EC2Descriptor.new(EC2_COMPONENT, EC2_NAME))
44
- @ec2_resource = ec2_resource
45
- @asg_client = asg_client
46
- @cloud_watch_client = cloud_watch_client
46
+ @asg_client = params[:AutoScalingClient]
47
+ @cloud_watch_client = params[:CloudWatchClient]
48
+ @cloud_watch_log_client = params[:CloudWatchLogsClient]
49
+ @ec2_resource = params[:Ec2Resource]
47
50
  end
48
51
 
49
52
  # def terminate_all_instances
@@ -12,17 +12,17 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require_relative 'abstract_single_component'
16
- require_relative 'abstract_snapshot'
17
- require_relative 'mixins/healthy_state_verifier'
18
- require_relative 'mixins/metric_verifier'
19
- require_relative 'mixins/snapshot_verifier'
15
+ require_relative '../abstract/single_component'
16
+ require_relative '../abstract/snapshot'
17
+ require_relative '../mixins/healthy_state_verifier'
18
+ require_relative '../mixins/metric_verifier'
19
+ require_relative '../mixins/snapshot_verifier'
20
20
 
21
21
  module RubyAemAws
22
22
  module Component
23
23
  # Interface to the AWS instance running the Orchestrator component of a full-set AEM stack.
24
24
  class Orchestrator
25
- attr_reader :descriptor, :ec2_resource, :asg_client, :cloud_watch_client
25
+ attr_reader :descriptor, :ec2_resource, :asg_client, :cloud_watch_client, :cloud_watch_log_client
26
26
  include AbstractSingleComponent
27
27
  include AbstractSnapshot
28
28
  # Can't verify state by count as there's no ELB.
@@ -34,16 +34,19 @@ module RubyAemAws
34
34
  EC2_NAME = 'AEM Orchestrator'.freeze
35
35
 
36
36
  # @param stack_prefix AWS tag: StackPrefix
37
- # @param ec2_resource AWS EC2 resource
38
- # @param asg_client AWS AutoScalingGroup client
39
- # @param cloud_watch_client AWS CloudWatch client
37
+ # @param params Array of AWS Clients and Resource connections:
38
+ # - AutoScalingClient: AWS AutoScalingGroup Client.
39
+ # - CloudWatchClient: AWS Cloudwatch Client.
40
+ # - CloudWatchLogsClient: AWS Cloudwatch Logs Client.
41
+ # - Ec2Resource: AWS EC2 Resource connection.
40
42
  # @return new RubyAemAws::FullSet::Orchestrator
41
- def initialize(stack_prefix, ec2_resource, asg_client, cloud_watch_client)
43
+ def initialize(stack_prefix, params)
42
44
  @descriptor = ComponentDescriptor.new(stack_prefix,
43
45
  EC2Descriptor.new(EC2_COMPONENT, EC2_NAME))
44
- @ec2_resource = ec2_resource
45
- @asg_client = asg_client
46
- @cloud_watch_client = cloud_watch_client
46
+ @asg_client = params[:AutoScalingClient]
47
+ @cloud_watch_client = params[:CloudWatchClient]
48
+ @cloud_watch_log_client = params[:CloudWatchLogsClient]
49
+ @ec2_resource = params[:Ec2Resource]
47
50
  end
48
51
 
49
52
  # def terminate_all_instances
@@ -12,21 +12,20 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require_relative 'abstract_grouped_component'
16
- require_relative 'abstract_snapshot'
17
- require_relative 'mixins/healthy_state_verifier'
18
- require_relative 'mixins/metric_verifier'
19
- require_relative 'mixins/snapshot_verifier'
15
+ require_relative '../abstract/grouped_component'
16
+ require_relative '../abstract/snapshot'
17
+ require_relative '../mixins/healthy_resource_verifier'
18
+ require_relative '../mixins/metric_verifier'
19
+ require_relative '../mixins/snapshot_verifier'
20
20
 
21
21
  module RubyAemAws
22
22
  module Component
23
23
  # Interface to the AWS instance running the Publish component of a full-set AEM stack.
24
24
  class Publish
25
- attr_reader :descriptor, :ec2_resource, :cloud_watch_client, :asg_client
25
+ attr_reader :descriptor, :ec2_resource, :cloud_watch_client, :asg_client, :cloud_watch_log_client
26
26
  include AbstractGroupedComponent
27
27
  include AbstractSnapshot
28
- # Can't verify state by count as there's no ELB.
29
- include HealthyStateVerifier
28
+ include HealthyResourceVerifier
30
29
  include MetricVerifier
31
30
  include SnapshotVerifier
32
31
 
@@ -34,16 +33,19 @@ module RubyAemAws
34
33
  EC2_NAME = 'AEM Publish'.freeze
35
34
 
36
35
  # @param stack_prefix AWS tag: StackPrefix
37
- # @param ec2_resource AWS EC2 resource
38
- # @param asg_client AWS AutoScalingGroup client
39
- # @param cloud_watch_client AWS CloudWatch client
36
+ # @param params Array of AWS Clients and Resource connections:
37
+ # - AutoScalingClient: AWS AutoScalingGroup Client.
38
+ # - CloudWatchClient: AWS Cloudwatch Client.
39
+ # - CloudWatchLogsClient: AWS Cloudwatch Logs Client.
40
+ # - Ec2Resource: AWS EC2 Resource connection.
40
41
  # @return new RubyAemAws::FullSet::AuthorPrimary
41
- def initialize(stack_prefix, ec2_resource, asg_client, cloud_watch_client)
42
+ def initialize(stack_prefix, params)
42
43
  @descriptor = ComponentDescriptor.new(stack_prefix,
43
44
  EC2Descriptor.new(EC2_COMPONENT, EC2_NAME))
44
- @ec2_resource = ec2_resource
45
- @asg_client = asg_client
46
- @cloud_watch_client = cloud_watch_client
45
+ @asg_client = params[:AutoScalingClient]
46
+ @cloud_watch_client = params[:CloudWatchClient]
47
+ @cloud_watch_log_client = params[:CloudWatchLogsClient]
48
+ @ec2_resource = params[:Ec2Resource]
47
49
  end
48
50
 
49
51
  def terminate_all_instances
@@ -12,20 +12,20 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require_relative 'abstract_grouped_component'
16
- require_relative 'abstract_snapshot'
17
- require_relative 'mixins/healthy_count_verifier'
18
- require_relative 'mixins/metric_verifier'
19
- require_relative 'mixins/snapshot_verifier'
15
+ require_relative '../abstract/grouped_component'
16
+ require_relative '../abstract/snapshot'
17
+ require_relative '../mixins/healthy_resource_verifier'
18
+ require_relative '../mixins/metric_verifier'
19
+ require_relative '../mixins/snapshot_verifier'
20
20
 
21
21
  module RubyAemAws
22
22
  module Component
23
23
  # Interface to the AWS instance running the PublishDispatcher component of a full-set AEM stack.
24
24
  class PublishDispatcher
25
- attr_reader :descriptor, :ec2_resource, :asg_client, :elb_client, :cloud_watch_client
25
+ attr_reader :descriptor, :ec2_resource, :asg_client, :elb_client, :cloud_watch_client, :cloud_watch_log_client
26
26
  include AbstractGroupedComponent
27
27
  include AbstractSnapshot
28
- include HealthyCountVerifier
28
+ include HealthyResourceVerifier
29
29
  include MetricVerifier
30
30
  include SnapshotVerifier
31
31
 
@@ -35,19 +35,22 @@ module RubyAemAws
35
35
  ELB_NAME = 'AEM Publish Dispatcher Load Balancer'.freeze
36
36
 
37
37
  # @param stack_prefix AWS tag: StackPrefix
38
- # @param ec2_resource AWS EC2 resource
39
- # @param asg_client AWS AutoScalingGroup client
40
- # @param elb_client AWS ELB client
41
- # @param cloud_watch_client AWS CloudWatch client
38
+ # @param params Array of AWS Clients and Resource connections:
39
+ # - AutoScalingClient: AWS AutoScalingGroup Client.
40
+ # - CloudWatchClient: AWS Cloudwatch Client.
41
+ # - CloudWatchLogsClient: AWS Cloudwatch Logs Client.
42
+ # - Ec2Resource: AWS EC2 Resource connection.
43
+ # - ElbClient: AWS ElasticLoadBalancer Client.
42
44
  # @return new RubyAemAws::FullSet::PublishDispatcher
43
- def initialize(stack_prefix, ec2_resource, asg_client, elb_client, cloud_watch_client)
45
+ def initialize(stack_prefix, params)
44
46
  @descriptor = ComponentDescriptor.new(stack_prefix,
45
47
  EC2Descriptor.new(EC2_COMPONENT, EC2_NAME),
46
48
  ELBDescriptor.new(ELB_ID, ELB_NAME))
47
- @ec2_resource = ec2_resource
48
- @asg_client = asg_client
49
- @elb_client = elb_client
50
- @cloud_watch_client = cloud_watch_client
49
+ @asg_client = params[:AutoScalingClient]
50
+ @cloud_watch_client = params[:CloudWatchClient]
51
+ @cloud_watch_log_client = params[:CloudWatchLogsClient]
52
+ @ec2_resource = params[:Ec2Resource]
53
+ @elb_client = params[:ElbClient]
51
54
  end
52
55
 
53
56
  def terminate_all_instances
@@ -12,29 +12,37 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require_relative 'abstract_stackmanager'
16
- require_relative 'mixins/sns_topic'
17
- require_relative 'mixins/dynamo_db'
18
- require_relative 'mixins/s3'
15
+ require_relative '../abstract/stackmanager'
16
+ require_relative '../client/sns_topic'
17
+ require_relative '../client/dynamo_db'
18
+ require_relative '../client/s3'
19
+ require_relative '../mixins/metric_verifier'
19
20
 
20
21
  module RubyAemAws
21
22
  module Component
22
23
  # Interface to the AWS StackManager to send out commands
23
24
  class StackManagerResources
24
- attr_reader :dynamodb_client, :s3_client, :s3_resource
25
+ attr_reader :dynamodb_client, :s3_client, :s3_resource, :cloud_watch_client, :cloud_watch_log_client
25
26
  include AbstractStackManager
26
27
  include DynamoDB
28
+ include MetricVerifier
27
29
  include SNSTopic
28
30
  include S3Access
29
31
 
30
32
  # @param dynamodb_client AWS DynamoDB client connection
31
- # @param s3_client AWS S3 client connection
32
- # @param s3_resource AWS S3 client connection
33
+ # @param params Array of AWS Clients and Resource connections:
34
+ # - CloudWatchClient: AWS Cloudwatch Client.
35
+ # - CloudWatchLogsClient: AWS Cloudwatch Logs Client.
36
+ # - DynamoDBClient: AWS DynamoDB Client.
37
+ # - S3Client: AWS S3 Client.
38
+ # - S3Resource: AWS S3 Resource connection.
33
39
  # @return new RubyAemAws::StackManager::StackManagerResources
34
- def initialize(dynamodb_client, s3_client, s3_resource)
35
- @dynamodb_client = dynamodb_client
36
- @s3_client = s3_client
37
- @s3_resource = s3_resource
40
+ def initialize(params)
41
+ @dynamodb_client = params[:DynamoDBClient]
42
+ @s3_client = params[:S3Client]
43
+ @s3_resource = params[:S3Resource]
44
+ @cloud_watch_client = params[:CloudWatchLogsClient]
45
+ @cloud_watch_log_client = params[:CloudWatchLogsClient]
38
46
  end
39
47
 
40
48
  # @param topicarn AWS SNS-Topic ARN
@@ -27,6 +27,13 @@ module RubyAemAws
27
27
  end
28
28
  end
29
29
 
30
+ # Raise this when ASG is misconfigured.
31
+ class ASGMisconfiguration < StandardError
32
+ def initialize(msg = 'ASG misconfigured')
33
+ super
34
+ end
35
+ end
36
+
30
37
  # Raise this when a unknown Response received.
31
38
  class UnknownResponse < StandardError
32
39
  def initialize(msg = 'Unknown response code')
@@ -0,0 +1,148 @@
1
+ # Copyright 2018 Shine Solutions
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require_relative '../constants'
16
+
17
+ module RubyAemAws
18
+ # Mixin for checking health of a component via ELB 'healthy' count vs ASG desired_capacity.
19
+ # Add this to a component to make it capable of determining its own health.
20
+ module HealthyCountVerifier
21
+ # Aggregate health_states considered healthy.
22
+ # @return health_state is ready or scaling.
23
+ def healthy?
24
+ %i[ready scaling].include? health_state
25
+ end
26
+
27
+ # Provides detail of the state of the instances comprising the component.
28
+ # @return one of:
29
+ # - no_asg: AutoScalingGroup could not be located (by StackPrefix and Component tags).
30
+ # - no_elb: ElasticLoadBalancer could not be located (by StackPrefix and aws:cloudformation:logical-id tags).
31
+ # - misconfigured: AutoScalingGroup.desired_capacity is less than 1.
32
+ # - recovering: ELB running instance count is less than AutoScalingGroup.desired_capacity.
33
+ # - scaling: ELB running instance count is more than AutoScalingGroup.desired_capacity.
34
+ # - ready: ELB running instance count is equal to AutoScalingGroup.desired_capacity.
35
+ def health_state
36
+ asg = find_auto_scaling_group(asg_client)
37
+ return :no_asg if asg.nil?
38
+
39
+ # Debug:
40
+ # unless asg.nil?
41
+ # puts("ASG: #{asg} #{asg.auto_scaling_group_name} (#{asg.desired_capacity})")
42
+ # asg.instances.each do |i|
43
+ # puts(" Instance #{i.instance_id}: #{i.health_status}")
44
+ # end
45
+ # end
46
+
47
+ elb = find_elb(elb_client)
48
+ return :no_elb if elb.nil?
49
+
50
+ elb_running_instances = 0
51
+ get_instances_state_from_elb(elb).each do |i|
52
+ elb_running_instances += 1 if i[:state] == RubyAemAws::Constants::INSTANCE_STATE_HEALTHY
53
+ end
54
+
55
+ desired_capacity = asg.desired_capacity
56
+
57
+ return :misconfigured if desired_capacity < 1
58
+ return :recovering if elb_running_instances < desired_capacity
59
+ return :scaling if elb_running_instances > desired_capacity
60
+ :ready
61
+ end
62
+
63
+ # @return true, if all EC2 instances within the ELB are running
64
+ def wait_until_healthy
65
+ raise ELBMisconfiguration if health_state.eql?(:misconfigured)
66
+ sleep 60 while health_state.eql?(:recovering) || health_state.eql?(:scaling)
67
+ return true if health_state.eql?(:ready)
68
+ end
69
+
70
+ private
71
+
72
+ # @return AutoScalingGroup by StackPrefix and Component tags.
73
+ def find_auto_scaling_group(asg_client)
74
+ autoscaling_groups = asg_client.describe_auto_scaling_groups(max_records: 50)
75
+ find_auto_scaling_group = find_auto_scaling_group_name(autoscaling_groups)
76
+
77
+ return find_auto_scaling_group unless find_auto_scaling_group.nil?
78
+
79
+ until autoscaling_groups.next_token.nil?
80
+ autoscaling_groups = asg_client.describe_auto_scaling_groups(max_records: 50, next_token: autoscaling_groups.next_token)
81
+ find_auto_scaling_group = find_auto_scaling_group_name(autoscaling_groups)
82
+ return find_auto_scaling_group unless find_auto_scaling_group.nil?
83
+ end
84
+ return nil if find_auto_scaling_group.nil?
85
+ end
86
+
87
+ def find_auto_scaling_group_name(autoscaling_groups)
88
+ autoscaling_groups.auto_scaling_groups.each do |autoscaling_group|
89
+ asg_matches_stack_prefix = false
90
+ asg_matches_component = false
91
+ tags = autoscaling_group.tags
92
+ tags.each do |tag|
93
+ if tag.key == 'StackPrefix' && tag.value == descriptor.stack_prefix
94
+ asg_matches_stack_prefix = true
95
+ break if asg_matches_component
96
+ next
97
+ end
98
+ if tag.key == 'Component' && tag.value == descriptor.ec2.component
99
+ asg_matches_component = true
100
+ break if asg_matches_stack_prefix
101
+ end
102
+ end
103
+ return autoscaling_group if asg_matches_stack_prefix && asg_matches_component
104
+ end
105
+ nil
106
+ end
107
+
108
+ # @return ElasticLoadBalancer by StackPrefix and logical-id tags.
109
+ def find_elb(elb_client)
110
+ elbs = elb_client.describe_load_balancers.load_balancer_descriptions
111
+ elbs.each do |elb|
112
+ elb_matches_stack_prefix = false
113
+ elb_matches_logical_id = false
114
+ tag_descriptions = elb_client.describe_tags(load_balancer_names: [elb.load_balancer_name]).tag_descriptions
115
+ next if tag_descriptions.empty?
116
+
117
+ tags = tag_descriptions[0].tags
118
+ tags.each do |tag|
119
+ if tag.key == 'StackPrefix' && tag.value == descriptor.stack_prefix
120
+ elb_matches_stack_prefix = true
121
+ break if elb_matches_logical_id
122
+ next
123
+ end
124
+ if tag.key == 'aws:cloudformation:logical-id' && tag.value == descriptor.elb.id
125
+ elb_matches_logical_id = true
126
+ break if elb_matches_stack_prefix
127
+ end
128
+ end
129
+ return elb if elb_matches_stack_prefix && elb_matches_logical_id
130
+ end
131
+ nil
132
+ end
133
+
134
+ def get_instances_state_from_elb(elb)
135
+ stack_prefix_instances = []
136
+ elb.instances.each do |i|
137
+ instance = get_instance_by_id(i.instance_id)
138
+ next if instance.nil?
139
+ instance.tags.each do |tag|
140
+ next if tag.key != 'StackPrefix'
141
+ break if tag.value != descriptor.stack_prefix
142
+ stack_prefix_instances.push(id: i.instance_id, state: instance.state.name)
143
+ end
144
+ end
145
+ stack_prefix_instances
146
+ end
147
+ end
148
+ end