tass 0.1.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 (27) hide show
  1. checksums.yaml +7 -0
  2. data/bin/tass +97 -0
  3. data/lib/tapjoy/autoscaling_bootstrap/AWS/Autoscaling/group.rb +61 -0
  4. data/lib/tapjoy/autoscaling_bootstrap/AWS/Autoscaling/launch_config.rb +45 -0
  5. data/lib/tapjoy/autoscaling_bootstrap/AWS/autoscaling.rb +45 -0
  6. data/lib/tapjoy/autoscaling_bootstrap/AWS/cloudwatch.rb +41 -0
  7. data/lib/tapjoy/autoscaling_bootstrap/AWS/ec2.rb +23 -0
  8. data/lib/tapjoy/autoscaling_bootstrap/AWS/elb.rb +55 -0
  9. data/lib/tapjoy/autoscaling_bootstrap/alerts/monitoring.rb +38 -0
  10. data/lib/tapjoy/autoscaling_bootstrap/alerts/scaling.rb +75 -0
  11. data/lib/tapjoy/autoscaling_bootstrap/alerts.rb +7 -0
  12. data/lib/tapjoy/autoscaling_bootstrap/audit.rb +49 -0
  13. data/lib/tapjoy/autoscaling_bootstrap/autoscaling/config.rb +38 -0
  14. data/lib/tapjoy/autoscaling_bootstrap/autoscaling/group.rb +113 -0
  15. data/lib/tapjoy/autoscaling_bootstrap/autoscaling/policy.rb +37 -0
  16. data/lib/tapjoy/autoscaling_bootstrap/autoscaling.rb +6 -0
  17. data/lib/tapjoy/autoscaling_bootstrap/autoscaling_group.rb +59 -0
  18. data/lib/tapjoy/autoscaling_bootstrap/aws.rb +7 -0
  19. data/lib/tapjoy/autoscaling_bootstrap/cloudwatch.rb +29 -0
  20. data/lib/tapjoy/autoscaling_bootstrap/configure_autoscaler.rb +40 -0
  21. data/lib/tapjoy/autoscaling_bootstrap/elb.rb +56 -0
  22. data/lib/tapjoy/autoscaling_bootstrap/errors/elb.rb +48 -0
  23. data/lib/tapjoy/autoscaling_bootstrap/errors.rb +30 -0
  24. data/lib/tapjoy/autoscaling_bootstrap/launch_configuration.rb +42 -0
  25. data/lib/tapjoy/autoscaling_bootstrap/version.rb +11 -0
  26. data/lib/tapjoy/autoscaling_bootstrap.rb +165 -0
  27. metadata +182 -0
@@ -0,0 +1,113 @@
1
+ module Tapjoy
2
+ module AutoscalingBootstrap
3
+ module Autoscaling
4
+ # Class for Autoscaling groups
5
+ class Group
6
+
7
+ # Initialize the class
8
+ def initialize
9
+ @scaler_name = Tapjoy::AutoscalingBootstrap.scaler_name
10
+ @config_name = Tapjoy::AutoscalingBootstrap.config_name
11
+ @elb_name = Tapjoy::AutoscalingBootstrap.elb_name
12
+ @create_elb = Tapjoy::AutoscalingBootstrap.create_elb
13
+ end
14
+
15
+ # Create autoscaling group
16
+ def create(config:, aws_env:, user_data:)
17
+ if exists
18
+ begin
19
+ zero_autoscale_group
20
+ rescue Aws::AutoScaling::Errors::ValidationError => err
21
+ abort("Cannot remove existing AS group #{@scaler_name}. Error: #{err}")
22
+ end
23
+ else
24
+ "Scaling group #{@scaler_name} does not exist, continuing..."
25
+ end
26
+
27
+ Tapjoy::AutoscalingBootstrap.config.create(config, aws_env,
28
+ user_data)
29
+
30
+ puts "Creating scaling group: #{@scaler_name}"
31
+ Tapjoy::AutoscalingBootstrap::AWS::Autoscaling::Group.create(**config)
32
+ create_termination_notification(config)
33
+ end
34
+
35
+ # Check if autoscale group exists
36
+ def exists
37
+ !Tapjoy::AutoscalingBootstrap::AWS::Autoscaling::Group.describe.nil?
38
+ end
39
+
40
+ # Encode user data into required base64 form
41
+ def encode_user_data(user_data)
42
+ Base64.encode64("#{user_data}")
43
+ end
44
+
45
+ # Create tags array to pass to autoscaling group
46
+ def generate_tags(tags)
47
+ tag_array = Array.new
48
+ return [] if tags.nil? || tags.empty?
49
+ tags.each do |t|
50
+ return [] if t.nil?
51
+ t.each_pair do |key, value|
52
+ tag_array << {
53
+ resource_id: @scaler_name,
54
+ resource_type: 'auto-scaling-group',
55
+ key: key.to_s,
56
+ value: value,
57
+ propagate_at_launch: true,
58
+ }
59
+ end
60
+ end
61
+ tag_array
62
+ end
63
+
64
+ private
65
+
66
+ # Clear out existing autoscaling group
67
+ def zero_autoscale_group
68
+ Tapjoy::AutoscalingBootstrap::AWS::Autoscaling::Group.resize
69
+
70
+ wait_for_asg_to_quiet
71
+
72
+ Tapjoy::AutoscalingBootstrap::AWS::Autoscaling::Group.delete
73
+
74
+ wait_for_asg_to_delete
75
+
76
+ abort("#{@scaler_name} still exists") if exists
77
+ end
78
+
79
+ # Create termination notification for Chef
80
+ def create_termination_notification(misc_config)
81
+ puts 'Create termination notification'
82
+ begin
83
+ Tapjoy::AutoscalingBootstrap::AWS::Autoscaling.put_notification_configuration(
84
+ **misc_config)
85
+ rescue Aws::AutoScaling::Errors::ValidationError => err
86
+ STDERR.puts "Cannot create notification: #{err}"
87
+ end
88
+ end
89
+
90
+ # Wait for ASG activities to settle before proceeding
91
+ def wait_for_asg_to_quiet
92
+ 5.times do |tries|
93
+ puts "Waiting for scaling activities to settle (#{tries + 1} of 5)..."
94
+ as_group_size=Tapjoy::AutoscalingBootstrap::AWS::Autoscaling::Group.describe[:instances].length
95
+
96
+ break if as_group_size.eql?(0)
97
+
98
+ Tapjoy::AutoscalingBootstrap::Base.new.aws_wait(tries)
99
+ end
100
+ end
101
+
102
+ # Wait for ASG to be deleted
103
+ def wait_for_asg_to_delete
104
+ 5.times do |tries|
105
+ puts "Waiting for auto scaling group to remove itself (#{tries + 1} of 5)..."
106
+ break unless exists
107
+ Tapjoy::AutoscalingBootstrap::Base.new.aws_wait(tries)
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,37 @@
1
+ module Tapjoy
2
+ module AutoscalingBootstrap
3
+ module Autoscaling
4
+ # Class for Autoscaling policies
5
+ class Policy
6
+
7
+ # Initialize the class
8
+ def initialize
9
+ @scaler_name = Tapjoy::AutoscalingBootstrap.scaler_name
10
+ @group = Tapjoy::AutoscalingBootstrap.group
11
+ end
12
+
13
+ # Create autoscaling policy
14
+ def create(policy, scale)
15
+ return unless Tapjoy::AutoscalingBootstrap.group.exists
16
+ Tapjoy::AutoscalingBootstrap::AWS::Autoscaling.put_scaling_policy(
17
+ policy_name: policy, **scale)
18
+ end
19
+
20
+ # Delete scaling policies
21
+ def delete(policy)
22
+ return unless @group.exists
23
+
24
+ if Tapjoy::AutoscalingBootstrap::AWS::Autoscaling.describe_policies(
25
+ policy: policy)[0].length > 0
26
+
27
+ puts "Deleting policy: #{policy}"
28
+ Tapjoy::AutoscalingBootstrap::AWS::Autoscaling.delete_policy(
29
+ policy: policy)
30
+ else
31
+ STDERR.puts "'#{policy}' doesn't exist. Skipping..."
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,6 @@
1
+ module Tapjoy
2
+ module AutoscalingBootstrap
3
+ module Autoscaling
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,59 @@
1
+ module Tapjoy
2
+ module AutoscalingBootstrap
3
+ # This class is the central launching point for new autoscaling group creation
4
+ class AutoscalingGroup
5
+ # Initialize the class
6
+ def create(opts, new_config, aws_env, user_data,
7
+
8
+ # ELB Parameters
9
+ elb_health_target: "#{new_config[:instance_protocol]}:#{new_config[:instance_port]}/healthz",
10
+ elb_protocol: new_config[:instance_protocol],
11
+ elb_name: "#{new_config[:name].gsub('_','-')}-discovery"
12
+ )
13
+
14
+ if new_config[:create_elb]
15
+ new_config.merge!({
16
+ elb_health_target: elb_health_target,
17
+ elb_protocol: elb_protocol,
18
+ elb_name: elb_name
19
+ })
20
+
21
+ Tapjoy::AutoscalingBootstrap::ELB.new.create(new_config, aws_env)
22
+ else
23
+ puts "\nNo ELB required"
24
+ end
25
+
26
+ Tapjoy::AutoscalingBootstrap::ConfigureAutoscalers.new(**new_config,
27
+ aws_env: aws_env, user_data: user_data, misc_config: new_config)
28
+
29
+ scaler_name = Tapjoy::AutoscalingBootstrap.scaler_name
30
+ config_name = Tapjoy::AutoscalingBootstrap.config_name
31
+
32
+ if new_config[:autoscale]
33
+ new_config.merge!({
34
+ alarm_low_scale: "#{new_config[:human_name]} - Scale Down - Low CPU Utilization",
35
+ alarm_high_scale: "#{new_config[:human_name]} - Scale Up - High CPU Utilization",
36
+ policy_up: "#{new_config[:name]}-up-policy",
37
+ policy_down: "#{new_config[:name]}-down-policy"
38
+ })
39
+ Tapjoy::AutoscalingBootstrap::Alerts::Scaling.new(new_config)
40
+ end
41
+
42
+ if new_config[:alerts]
43
+ monitoring_alerts = Tapjoy::AutoscalingBootstrap::Alerts::Monitoring.new
44
+ monitoring_alert_config = {
45
+ alarm_low_alert: "#{new_config[:human_name]} - ALARM - Extremely Low CPU Utilization",
46
+ alarm_high_alert: "#{new_config[:human_name]} - ALARM - Extremely High CPU Utilization",
47
+ notification: "#{new_config[:sns_base_arn]}:General-NOC-Notifications"
48
+ }
49
+ monitoring_alerts.create(**monitoring_alert_config)
50
+ end
51
+
52
+ puts "\n\nCreated -- "
53
+ puts "Autoscaling Group: #{scaler_name}"
54
+ puts "Launch Config: #{config_name}"
55
+ puts 'Instance Count: 0'
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,7 @@
1
+ module Tapjoy
2
+ module AutoscalingBootstrap
3
+ # Module containing all references to objects in AWS SDK
4
+ module AWS
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,29 @@
1
+ module Tapjoy
2
+ module AutoscalingBootstrap
3
+ # This module configures cloudwatch alarms
4
+ module Cloudwatch
5
+ class << self
6
+ # Create autoscaling alarms
7
+ def create_alarm(scale_alert)
8
+ puts "Creating: #{scale_alert[:alarm]}"
9
+ Tapjoy::AutoscalingBootstrap::AWS::Cloudwatch.put_metric_alarm(
10
+ **scale_alert)
11
+ end
12
+
13
+ # Delete autoscaling alarms
14
+ def delete_alarm(alarm)
15
+ if self.alarm_exists(alarm)
16
+ puts "Deleting alarm: #{alarm}"
17
+ Tapjoy::AutoscalingBootstrap::AWS::Cloudwatch.delete_alarm(alarm)
18
+ else
19
+ STDERR.puts "'#{alarm}' doesn't exist. Skipping..."
20
+ end
21
+ end
22
+
23
+ def alarm_exists(alarm)
24
+ Tapjoy::AutoscalingBootstrap::AWS::Cloudwatch.describe_alarm(alarm).length > 0
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,40 @@
1
+ module Tapjoy
2
+ module AutoscalingBootstrap
3
+ # This class configures autoscaling groups
4
+ class ConfigureAutoscalers
5
+ # required arguments first, then optional
6
+ def initialize(misc_config:, aws_env:, user_data:, **unused_values)
7
+
8
+ if misc_config[:create_as_group]
9
+ sec_group_exists(aws_env[:security_groups]) unless misc_config[:vpc_subnets]
10
+ create_autoscaling_group(misc_config, aws_env, user_data)
11
+ else
12
+ puts 'Skipping creating autoscale group and launch config'
13
+ puts "\n"
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ # Check if security group exists and create it if it does not
20
+ def sec_group_exists(groups)
21
+ groups.each do |group|
22
+ begin
23
+ puts "Verifying #{group} exists..."
24
+ group = Tapjoy::AutoscalingBootstrap::AWS::EC2.describe_security_groups(group)
25
+ rescue Aws::EC2::Errors::InvalidGroupNotFound => err
26
+ STDERR.puts "Warning: #{err}"
27
+ puts "Creating #{group} for #{Tapjoy::AutoscalingBootstrap.scaler_name}"
28
+ Tapjoy::AutoscalingBootstrap::AWS::EC2.create_security_group(group)
29
+ end
30
+ end
31
+ end
32
+
33
+ # Create ASG logic
34
+ def create_autoscaling_group(misc_config, aws_env, user_data)
35
+ Tapjoy::AutoscalingBootstrap.group.create(config: misc_config,
36
+ aws_env: aws_env, user_data: user_data)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,56 @@
1
+ module Tapjoy
2
+ module AutoscalingBootstrap
3
+ # This class configures elastic load balancers
4
+ class ELB
5
+ # Initialize the class
6
+ def initialize
7
+ end
8
+
9
+ # Create load balancer
10
+ def create(config, aws_env)
11
+
12
+ check_valid_config(config)
13
+ delete if exists
14
+ Tapjoy::AutoscalingBootstrap::AWS::ELB.create(**config, **aws_env)
15
+ health_check(config)
16
+ end
17
+
18
+ # Configure health check
19
+ def health_check(config)
20
+ abort('Target must be specified') if config[:elb_health_target].nil?
21
+
22
+ begin
23
+ Tapjoy::AutoscalingBootstrap::AWS::ELB.health_check(**config)
24
+ rescue Aws::ElasticLoadBalancing::Errors::ValidationError => err
25
+ abort("Fatal! Invalid ELB Configuration: #{err}")
26
+ end
27
+ end
28
+
29
+ # Check if ELB exists
30
+ def exists
31
+ begin
32
+ Tapjoy::AutoscalingBootstrap::AWS::ELB.describe
33
+ return true
34
+ rescue Aws::ElasticLoadBalancing::Errors::LoadBalancerNotFound => err
35
+ STDERR.puts "Warning: #{err}"
36
+ return false
37
+ end
38
+ end
39
+
40
+ # Delete ELB
41
+ def delete
42
+ puts 'Removing existing ELB'
43
+ Tapjoy::AutoscalingBootstrap::AWS::ELB.delete
44
+ end
45
+
46
+ private
47
+ # Check configuration
48
+ def check_valid_config(config)
49
+ fail Tapjoy::AutoscalingBootstrap::Errors::ELB::NameTooLong if Tapjoy::AutoscalingBootstrap.elb_name.length > 32
50
+ fail Tapjoy::AutoscalingBootstrap::Errors::ELB::NotAnELB if Tapjoy::AutoscalingBootstrap.elb_name.eql?'NaE'
51
+ fail Tapjoy::AutoscalingBootstrap::Errors::ELB::MissingPort if config[:elb_port].nil?
52
+ fail Tapjoy::AutoscalingBootstrap::Errors::ELB::MissingInstanceProtocol if config[:instance_protocol].nil?
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,48 @@
1
+ module Tapjoy
2
+ module AutoscalingBootstrap
3
+ module Errors
4
+ module ELB
5
+ # Raise if we try to overwrite an unclobbered ELB
6
+ class ClobberRequired < ArgumentError
7
+ def initialize
8
+ elb_name = Tapjoy::AutoscalingBootstrap.elb_name
9
+ error = 'CLOBBER_ELB env var was not true, CREATE_ELB setting was ' \
10
+ "true and ELB '#{elb_name}' exists so we are aborting."
11
+ abort(error)
12
+ end
13
+ end
14
+
15
+ # Raise if ELB Name is too long
16
+ class NameTooLong < NameError
17
+ def initialize
18
+ elb_name = Tapjoy::AutoscalingBootstrap.elb_name
19
+ error = "ELB Name too long: #{elb_name.length} characters. " \
20
+ 'Must be less than 32'
21
+ abort(error)
22
+ end
23
+ end
24
+
25
+ # Raise if NaE
26
+ class NotAnELB < ArgumentError
27
+ def initialize
28
+ abort('CREATE_ELB specified without a name')
29
+ end
30
+ end
31
+
32
+ # Raise if ELB port is missing
33
+ class MissingPort < ArgumentError
34
+ def initialize
35
+ abort('ELB port must be specified')
36
+ end
37
+ end
38
+
39
+ # Raise if ELB instance protocol is missing
40
+ class MissingInstanceProtocol < ArgumentError
41
+ def initialize
42
+ abort('Instance protocol must be specified')
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,30 @@
1
+ module Tapjoy
2
+ module AutoscalingBootstrap
3
+ module Errors
4
+ # Raise if we try to overwrite an unclobbered ASG
5
+ class ClobberRequired < ArgumentError
6
+ def initialize
7
+ scaler_name = Tapjoy::AutoscalingBootstrap.scaler_name
8
+ error = 'CLOBBER env var was not true, CREATE_AS_GROUP setting ' \
9
+ "true and autoscale group '#{scaler_name}' exists so we are aborting."
10
+ abort(error)
11
+ end
12
+ end
13
+
14
+ # Raise if an invalid environment is specified
15
+ class InvalidEnvironment < ArgumentError
16
+ def initialize
17
+ abort('Invalid environment specified')
18
+ end
19
+ end
20
+
21
+ # Raise if an invalid launch configuration or autoscaling group
22
+ # is specified
23
+ class InvalidAutoscalingGroup < NoMethodError
24
+ def initialize
25
+ abort("ERROR: Specified autoscaling group doesn't exist")
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,42 @@
1
+ module Tapjoy
2
+ module AutoscalingBootstrap
3
+ # This class is the central launching point for autoscaling group update
4
+ class LaunchConfiguration
5
+ # Initialize the class
6
+ def initialize(new_config, aws_env, user_data)
7
+ Tapjoy::AutoscalingBootstrap.scaler_name = "#{new_config[:name]}-group"
8
+ Tapjoy::AutoscalingBootstrap.config_name = "#{new_config[:name]}-config"
9
+
10
+ updated_config = current.to_hash.merge!(new_config)
11
+
12
+ lc_name = "#{updated_config[:launch_configuration_name].split('-config')[0]}-config_#{date_stamp}"
13
+ update(config_name: lc_name, user_data: user_data,
14
+ updated_config: updated_config, aws_env: aws_env)
15
+ end
16
+
17
+ def current
18
+ begin
19
+ current_config_name = Tapjoy::AutoscalingBootstrap::AWS::Autoscaling::Group.describe[:launch_configuration_name]
20
+ rescue NoMethodError
21
+ raise Tapjoy::AutoscalingBootstrap::Errors::InvalidAutoscalingGroup
22
+ end
23
+ puts "Current launch config is: #{current_config_name}\n\n"
24
+ Tapjoy::AutoscalingBootstrap::AWS::Autoscaling::LaunchConfig.describe(current_config_name)
25
+ end
26
+
27
+ def update(config_name:, scaler_name: 'NaS', user_data: user_data,
28
+ updated_config:, aws_env:)
29
+
30
+ Tapjoy::AutoscalingBootstrap.config_name = config_name
31
+ Tapjoy::AutoscalingBootstrap.scaler_name = scaler_name
32
+
33
+ Tapjoy::AutoscalingBootstrap.config.create(updated_config, aws_env,
34
+ user_data)
35
+ end
36
+
37
+ def date_stamp
38
+ Time.now.strftime('%Y%m%d-%H%M%S')
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,11 @@
1
+ module Tapjoy
2
+ module AutoscalingBootstrap
3
+ module Version
4
+ MAJOR = 0
5
+ MINOR = 1
6
+ PATCH = 0
7
+ end
8
+
9
+ VERSION = [Version::MAJOR, Version::MINOR, Version::PATCH].join('.')
10
+ end
11
+ end
@@ -0,0 +1,165 @@
1
+ require 'aws-sdk-core'
2
+ require 'highline/import'
3
+ require 'base64'
4
+ require 'yaml'
5
+ require 'trollop'
6
+ require 'erb'
7
+ require 'hashdiff'
8
+
9
+ # relative requires
10
+ require_relative 'autoscaling_bootstrap/elb'
11
+ require_relative 'autoscaling_bootstrap/autoscaling'
12
+ require_relative 'autoscaling_bootstrap/autoscaling/config'
13
+ require_relative 'autoscaling_bootstrap/autoscaling/policy'
14
+ require_relative 'autoscaling_bootstrap/autoscaling/group'
15
+ require_relative 'autoscaling_bootstrap/cloudwatch'
16
+ require_relative 'autoscaling_bootstrap/configure_autoscaler'
17
+ require_relative 'autoscaling_bootstrap/errors'
18
+ require_relative 'autoscaling_bootstrap/errors/elb'
19
+ require_relative 'autoscaling_bootstrap/alerts'
20
+ require_relative 'autoscaling_bootstrap/alerts/scaling'
21
+ require_relative 'autoscaling_bootstrap/alerts/monitoring'
22
+ require_relative 'autoscaling_bootstrap/aws'
23
+ require_relative 'autoscaling_bootstrap/AWS/elb'
24
+ require_relative 'autoscaling_bootstrap/AWS/ec2'
25
+ require_relative 'autoscaling_bootstrap/AWS/cloudwatch'
26
+ require_relative 'autoscaling_bootstrap/AWS/autoscaling'
27
+ require_relative 'autoscaling_bootstrap/AWS/Autoscaling/group'
28
+ require_relative 'autoscaling_bootstrap/AWS/Autoscaling/launch_config'
29
+ require_relative 'autoscaling_bootstrap/autoscaling_group'
30
+ require_relative 'autoscaling_bootstrap/launch_configuration'
31
+ require_relative 'autoscaling_bootstrap/version'
32
+ require_relative 'autoscaling_bootstrap/audit'
33
+
34
+ module Tapjoy
35
+ # Module for Autoscaling Bootstrap
36
+ module AutoscalingBootstrap
37
+ # This class is meant for class and instances variables used throughout
38
+ # the application.
39
+ class << self
40
+ attr_accessor :scaler_name, :config_name, :create_elb
41
+ attr_reader :elb_name
42
+
43
+ def elb_name=(str)
44
+ @elb_name = str
45
+ end
46
+
47
+ def policy
48
+ @policy = Tapjoy::AutoscalingBootstrap::Autoscaling::Policy.new
49
+ end
50
+
51
+ def group
52
+ @group = Tapjoy::AutoscalingBootstrap::Autoscaling::Group.new
53
+ end
54
+
55
+ def config
56
+ @config = Tapjoy::AutoscalingBootstrap::Autoscaling::Config.new
57
+ end
58
+
59
+ def cloudwatch
60
+ @cloudwatch = Tapjoy::AutoscalingBootstrap::CloudWatch.new
61
+ end
62
+
63
+ def config_dir
64
+ @config_dir ||= ENV['TASS_CONFIG_DIR'] || "#{ENV['HOME']}/.tass"
65
+ end
66
+ end
67
+
68
+ # Base class for generic methods used throughout the gem
69
+ class Base
70
+ # Confirm that yaml is readable and then convert to hash
71
+ def load_yaml(filename)
72
+ abort("ERROR: '#{filename}' is not readable") unless File.readable?(filename)
73
+ Hash[YAML.load_file(filename)]
74
+ end
75
+
76
+ # Using variables passed in, generate user data file
77
+ def generate_user_data(config)
78
+
79
+ ERB.new(
80
+ File.new("#{config[:config_dir]}/userdata/#{config[:bootstrap_script]}").read,nil,'-'
81
+ ).result(binding)
82
+ end
83
+
84
+ # Check if we allow clobbering and need to clobber
85
+ def check_clobber(opts, config)
86
+ fail Tapjoy::AutoscalingBootstrap::Errors::ClobberRequired if check_as_clobber(**opts, **config)
87
+ fail Tapjoy::AutoscalingBootstrap::Errors::ELB::ClobberRequired if check_elb_clobber(**opts, **config)
88
+ puts "We don't need to clobber"
89
+ end
90
+
91
+ # Check autoscaling clobber
92
+ def check_as_clobber(create_as_group:, clobber_as:, **unused_values)
93
+ create_as_group && Tapjoy::AutoscalingBootstrap.group.exists && !clobber_as
94
+ end
95
+
96
+ # Check ELB clobber
97
+ def check_elb_clobber(create_elb:, clobber_elb:, **unused_values)
98
+ elb = Tapjoy::AutoscalingBootstrap::ELB.new
99
+ create_elb && elb.exists && !clobber_elb
100
+ end
101
+
102
+ # Get AWS Environment
103
+ def get_security_groups(config_dir, env, group)
104
+
105
+ # Check environment file
106
+ unless File.readable?("#{config_dir}/config/common/#{env}.yaml")
107
+ fail Tapjoy::AutoscalingBootstrap::Errors::InvalidEnvironment
108
+ end
109
+
110
+ security_groups = {security_groups: group.split(',')}
111
+ end
112
+
113
+ # Confirm config settings before running autoscaling code
114
+ def confirm_config(keypair:, zones:, security_groups:, instance_type:,
115
+ image_id:, iam_instance_profile:, prompt:, use_vpc: use_vpc,
116
+ vpc_subnets: nil, **unused_values)
117
+
118
+ elb_name = Tapjoy::AutoscalingBootstrap.elb_name
119
+
120
+ puts ' Preparing to configure the following autoscaling group:'
121
+ puts " Launch Config: #{Tapjoy::AutoscalingBootstrap.config_name}"
122
+ puts " Auto Scaler: #{Tapjoy::AutoscalingBootstrap.scaler_name}"
123
+ puts " ELB: #{elb_name}" unless elb_name.eql? 'NaE'
124
+ puts " Key Pair: #{keypair}"
125
+ puts " Zones: #{zones.join(',')}"
126
+ puts " Groups: #{security_groups.sort.join(',')}"
127
+ puts " Instance Type: #{instance_type}"
128
+ puts " Image ID: #{image_id}"
129
+ puts " IAM Role: #{iam_instance_profile}"
130
+ puts " VPC Subnets: #{vpc_subnets}" if use_vpc
131
+
132
+ puts "\n\nNOTE! Continuing may have adverse effects if you end up " \
133
+ "deleting an IN-USE PRODUCTION scaling group. Don't be dumb."
134
+ return true unless prompt
135
+ agree('Is this information correct? [y/n]')
136
+ end
137
+
138
+ # configure environment
139
+ def configure_environment(filename, env, config_dir)
140
+ defaults_hash = self.load_yaml("#{config_dir}/config/common/defaults.yaml")
141
+ facet_hash = self.load_yaml("#{config_dir}/config/clusters/#{filename}")
142
+ env_hash = self.load_yaml("#{config_dir}/config/common/#{env}.yaml")
143
+
144
+ new_config = defaults_hash.merge!(env_hash).merge(facet_hash)
145
+ new_config[:config_dir] = config_dir
146
+ aws_env = self.get_security_groups(config_dir, env, new_config[:group])
147
+
148
+ Tapjoy::AutoscalingBootstrap.scaler_name = "#{new_config[:name]}-group"
149
+ Tapjoy::AutoscalingBootstrap.config_name = "#{new_config[:name]}-config"
150
+ # If there's no ELB, then Not a ELB
151
+ puts new_config[:elb_name]
152
+ Tapjoy::AutoscalingBootstrap.elb_name = new_config[:elb_name] || 'NaE'
153
+ Tapjoy::AutoscalingBootstrap.create_elb = new_config[:create_elb]
154
+ user_data = self.generate_user_data(new_config)
155
+ return new_config, aws_env, user_data
156
+ end
157
+
158
+ # Exponential backup
159
+ def aws_wait(tries)
160
+ puts "Sleeping for #{2 ** tries}..."
161
+ sleep 2 ** tries
162
+ end
163
+ end
164
+ end
165
+ end