tass 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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