tass 0.2.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f3f94224d11a7c396b61b38b44d026139f06b038
4
- data.tar.gz: 70597218851be9ffe6d8cd1eccef2db50d144a22
3
+ metadata.gz: d63df49ef7d75eeec0d74aef90721a098a829efa
4
+ data.tar.gz: 23bf79d63f1bb9157c51896c85e05ed28ed20f47
5
5
  SHA512:
6
- metadata.gz: 34905de3f29c57247d272728b3ca0a510703a8129a8148f23d843ce57b6a445fb4dcc37c97026c7631ecaf2f8c067645be3ffa4ec8be2dd6616abc557e35f411
7
- data.tar.gz: 8750964d46b84e5e55b32ae5cc3909b8d0af0e402db82b14d4dda9f410234820183cda03f0754138c392a9f6ef2813ac4e396bf1de75f2602c048c52d976fc0e
6
+ metadata.gz: 921b36ca3ccf7eab2817009c1493357b87f11377b13b92099f7a5af0439c9d29e3aa4fe55f5f189928edee0fcd46eff8253b947af901e4b2bb58a28b5908a96b
7
+ data.tar.gz: 6a1edbb35badfd93bb59c988982581b9bd0cb9be651ebabef6dda8fcb88620b7a14b341e3d66758c240777f0328e5185f6988334c70b6ff9758035e7be14b4ff
data/bin/tass CHANGED
@@ -2,20 +2,31 @@
2
2
 
3
3
  require 'tapjoy/autoscaling_bootstrap'
4
4
 
5
+ def common_args
6
+ opt :filename, 'Specify config file to load', type: :string, required: true
7
+ opt :prompt, 'Enable/disable prompts', default: true
8
+ opt :env, 'Specify which environment config to load', type: :string
9
+ end
10
+
5
11
  def confirm_config(aws_env, misc_config, opts)
6
12
  use_vpc = true if misc_config[:vpc_subnets]
7
- unless Tapjoy::AutoscalingBootstrap::Base.new.confirm_config(**aws_env,
8
- **misc_config, **opts, use_vpc: use_vpc)
13
+ has_elb = true if misc_config.key?(:elb)
14
+ Tapjoy::AutoscalingBootstrap::Base.new.confirm_config(**aws_env,
15
+ **misc_config, **opts, use_vpc: use_vpc, has_elb: has_elb,
16
+ config: misc_config)
17
+ end
9
18
 
10
- abort('Cannot continue if configuration is not correct. Please fix.')
11
- end
19
+ def configure_environment(opts)
20
+ config, aws_env, user_data = Tapjoy::AutoscalingBootstrap::Base.new.configure_environment(opts)
21
+ Aws.config[:region] = config[:aws_region]
22
+ [config, aws_env, user_data]
12
23
  end
13
24
 
14
- SUB_COMMANDS = %w(create update audit)
25
+ SUB_COMMANDS = %w(create update audit scale)
15
26
  Trollop::options do
16
27
  usage '[SUB_COMMAND] [options]'
17
28
  synopsis "\nConfigures autoscaling groups.\nAvailable subcommands are: #{SUB_COMMANDS}"
18
- version "#{File.basename($0)} #{Tapjoy::AutoscalingBootstrap::VERSION} \u00A9 2015 Tapjoy, Inc."
29
+ version "#{File.basename($PROGRAM_NAME)} #{Tapjoy::AutoscalingBootstrap::VERSION} \u00A9 2015 Tapjoy, Inc."
19
30
  stop_on SUB_COMMANDS
20
31
  end
21
32
 
@@ -27,33 +38,43 @@ when 'create'
27
38
  usage 'create [options]'
28
39
  synopsis 'This command creates new autoscaling groups, and overwrites existing ones.'
29
40
 
30
- opt :filename, 'Specify config file to load', type: :string, required: true
31
- opt :config_dir, 'Specify the directory for configuration files', type: :string, short: :none, default: Tapjoy::AutoscalingBootstrap.config_dir
32
- opt :env, 'Specify which environment config to load', type: :string
33
41
  opt :clobber_elb, 'Force ELB creation', default: false, short: :none
34
42
  opt :clobber_as, 'Force AS group creation', default: false, short: :none
35
- opt :prompt, 'Enable/disable prompts', default: true
43
+ common_args
36
44
  end
37
45
 
38
- config, aws_env, user_data = Tapjoy::AutoscalingBootstrap::Base.new.configure_environment(opts[:filename], opts[:env], opts[:config_dir])
39
- Aws.config[:region] = config[:aws_region]
40
- confirm_config(aws_env, config, opts)
46
+ config, aws_env, user_data = configure_environment(opts)
41
47
 
42
48
  Tapjoy::AutoscalingBootstrap::Base.new.check_clobber(opts, config)
49
+ unless confirm_config(aws_env, config, opts)
50
+ abort('Cannot continue if configuration is not correct. Please fix.')
51
+ end
43
52
  Tapjoy::AutoscalingBootstrap::AutoscalingGroup.new.create(opts, config, aws_env, user_data)
53
+
54
+ if config.key?(:elb)
55
+ config[:elb].each do |elb|
56
+ elb.each do |elb_name, elb_config|
57
+ Tapjoy::AutoscalingBootstrap.elb_name = elb_name
58
+ elb_hash = {
59
+ elb_name => config[:default_elb_parameters].merge!(elb[elb_name])
60
+ }
61
+
62
+ Tapjoy::AutoscalingBootstrap::ELB.new(
63
+ elb_hash, config[:clobber_elb], config[:zones],
64
+ config[:security_groups])
65
+ end
66
+ end
67
+ end
68
+
44
69
  when 'update'
45
70
  opts = Trollop.options do
46
71
  # Set help message
47
72
  usage 'update [options]'
48
73
  synopsis 'This command creates new launch configurations based on existing autoscaling groups using local instance configuration files as overrides.'
49
- opt :filename, 'Specify config file to load', type: :string, required: true
50
- opt :config_dir, 'Specify the directory for configuration files', type: :string, short: :none, default: Tapjoy::AutoscalingBootstrap.config_dir
51
- opt :env, 'Specify which environment config to load', type: :string
52
- opt :prompt, 'Enable/disable prompts', default: true
74
+ common_args
53
75
  end
54
76
 
55
- config, aws_env, user_data = Tapjoy::AutoscalingBootstrap::Base.new.configure_environment(opts[:filename], opts[:env], opts[:config_dir])
56
- Aws.config[:region] = config[:aws_region]
77
+ config, aws_env, user_data = configure_environment(opts)
57
78
  confirm_config(aws_env, config, opts)
58
79
 
59
80
  Tapjoy::AutoscalingBootstrap::LaunchConfiguration.new(config, aws_env, user_data)
@@ -61,17 +82,23 @@ when 'audit'
61
82
  opts = Trollop.options do
62
83
  usage 'audit'
63
84
  synopsis 'This command compares local configuration files for a given cluster to the existing launch configuration and autoscaling group running in AWS.'
64
- opt :filename, 'Specify config file to load', type: :string, required: true
65
- opt :config_dir, 'Specify the directory for configuration files', type: :string, short: :none, default: Tapjoy::AutoscalingBootstrap.config_dir
66
- opt :env, 'Specify which environment config to load', required: true, type: :string
67
- opt :prompt, 'Enable/disable prompts', default: true
85
+ common_args
68
86
  end
69
87
 
70
- config, aws_env, user_data = Tapjoy::AutoscalingBootstrap::Base.new.configure_environment(opts[:filename], opts[:env], opts[:config_dir])
71
- Aws.config[:region] = config[:aws_region]
88
+ config, aws_env, user_data = configure_environment(opts)
72
89
 
73
- config.merge!(aws_env.merge({user_data: Base64.encode64("#{user_data}")}))
90
+ config.merge!(aws_env.merge(user_data: Base64.encode64("#{user_data}")))
74
91
  Tapjoy::AutoscalingBootstrap::Audit.new(config)
92
+ when 'scale'
93
+ opts = Trollop.options do
94
+ usage 'scale [options]'
95
+ synopsis 'This command is used to scale up/down auto scaling groups'
96
+ common_args
97
+ opt :instance_ids, 'Instance IDs to scale down', type: :strings
98
+ end
99
+
100
+ config, aws_env, user_data = configure_environment(opts)
101
+ Tapjoy::AutoscalingBootstrap::Autoscaling::Group.new.scale(config)
75
102
  else
76
103
  Trollop.educate
77
104
  end
@@ -30,6 +30,7 @@ require_relative 'autoscaling_bootstrap/autoscaling_group'
30
30
  require_relative 'autoscaling_bootstrap/launch_configuration'
31
31
  require_relative 'autoscaling_bootstrap/version'
32
32
  require_relative 'autoscaling_bootstrap/audit'
33
+ require_relative 'autoscaling_bootstrap/ec2'
33
34
 
34
35
  module Tapjoy
35
36
  # Module for Autoscaling Bootstrap
@@ -45,24 +46,6 @@ module Tapjoy
45
46
  @elb_name = str
46
47
  end
47
48
 
48
- # If you're using AutoscalingBootstrap to join to a list of existing ELBs, that array
49
- # goes here. This list can include or not include the provided elb_name, the
50
- # array + a custom elb_name will be uniq-ed before being passed to Amazon
51
- def elb_list=(list)
52
- @elb_list = list
53
- end
54
-
55
- def elb_list
56
- @elb_list ||= []
57
- end
58
-
59
- # This is the list of elbs passed to the autoscaling configuration. It will include
60
- # the created elb, as well as the specific list of elbs to join. It will call uniq
61
- # on the list in case you accidentally specify the same elb twice
62
- def elbs_to_join
63
- (elb_list + [Tapjoy::AutoscalingBootstrap.elb_name]).uniq
64
- end
65
-
66
49
  def policy
67
50
  @policy = Tapjoy::AutoscalingBootstrap::Autoscaling::Policy.new
68
51
  end
@@ -83,9 +66,8 @@ module Tapjoy
83
66
  @config_dir ||= ENV['TASS_CONFIG_DIR'] || "#{ENV['HOME']}/.tass"
84
67
  end
85
68
 
86
- def is_valid_env?(config_dir, env)
87
- env_list = self.supported_envs(config_dir)
88
- puts config_dir
69
+ def valid_env?(config_dir, env)
70
+ env_list = supported_envs(config_dir)
89
71
  unless env_list.include?(env)
90
72
  Trollop.die :env, "Currently supported enviroments are #{env_list.join(',')}"
91
73
  end
@@ -93,7 +75,7 @@ module Tapjoy
93
75
 
94
76
  def supported_envs(listing)
95
77
  envs = []
96
- Dir.entries("#{listing}/config/common").each do |file|
78
+ Dir.entries(listing).each do |file|
97
79
  next unless file.end_with?('yaml')
98
80
  next if file.start_with?('defaults')
99
81
  envs << file.chomp!('.yaml')
@@ -111,17 +93,16 @@ module Tapjoy
111
93
  end
112
94
 
113
95
  # Using variables passed in, generate user data file
114
- def generate_user_data(config)
96
+ def generate_user_data(userdata_dir, bootstrap_script, config)
115
97
 
116
98
  ERB.new(
117
- File.new("#{config[:config_dir]}/userdata/#{config[:bootstrap_script]}").read,nil,'-'
99
+ File.new(File.join(userdata_dir, bootstrap_script)).read, nil, '-'
118
100
  ).result(binding)
119
101
  end
120
102
 
121
103
  # Check if we allow clobbering and need to clobber
122
104
  def check_clobber(opts, config)
123
105
  fail Tapjoy::AutoscalingBootstrap::Errors::ClobberRequired if check_as_clobber(**opts, **config)
124
- fail Tapjoy::AutoscalingBootstrap::Errors::ELB::ClobberRequired if check_elb_clobber(**opts, **config)
125
106
  puts "We don't need to clobber"
126
107
  end
127
108
 
@@ -130,41 +111,40 @@ module Tapjoy
130
111
  create_as_group && Tapjoy::AutoscalingBootstrap.group.exists && !clobber_as
131
112
  end
132
113
 
133
- # Check ELB clobber
134
- def check_elb_clobber(create_elb:, clobber_elb:, **unused_values)
135
- elb = Tapjoy::AutoscalingBootstrap::ELB.new
136
- create_elb && elb.exists && !clobber_elb
137
- end
138
-
139
114
  # Get AWS Environment
140
115
  def get_security_groups(config_dir, env, group)
141
116
 
142
117
  # Check environment file
143
- unless File.readable?("#{config_dir}/config/common/#{env}.yaml")
118
+ unless File.readable?("#{config_dir}/#{env}.yaml")
144
119
  fail Tapjoy::AutoscalingBootstrap::Errors::InvalidEnvironment
145
120
  end
146
121
 
147
122
  security_groups = {security_groups: group.split(',')}
148
123
  end
149
124
 
125
+ # Clean list of ELBs
126
+ def elb_list(config)
127
+ config[:elb].map(&:keys).flatten.join(',')
128
+ end
129
+
150
130
  # Confirm config settings before running autoscaling code
151
131
  def confirm_config(keypair:, zones:, security_groups:, instance_type:,
152
132
  image_id:, iam_instance_profile:, prompt:, use_vpc: use_vpc,
153
- vpc_subnets: nil, **unused_values)
154
-
155
- elb_name = Tapjoy::AutoscalingBootstrap.elb_name
133
+ vpc_subnets: nil, has_elb: has_elb, config:, termination_policies:,
134
+ **unused_values)
156
135
 
157
136
  puts ' Preparing to configure the following autoscaling group:'
158
- puts " Launch Config: #{Tapjoy::AutoscalingBootstrap.config_name}"
159
- puts " Auto Scaler: #{Tapjoy::AutoscalingBootstrap.scaler_name}"
160
- puts " ELB: #{elb_name}" unless elb_name.eql? 'NaE'
161
- puts " Key Pair: #{keypair}"
162
- puts " Zones: #{zones.join(',')}"
163
- puts " Groups: #{security_groups.sort.join(',')}"
164
- puts " Instance Type: #{instance_type}"
165
- puts " Image ID: #{image_id}"
166
- puts " IAM Role: #{iam_instance_profile}"
167
- puts " VPC Subnets: #{vpc_subnets}" if use_vpc
137
+ puts " Launch Config: #{Tapjoy::AutoscalingBootstrap.config_name}"
138
+ puts " Auto Scaler: #{Tapjoy::AutoscalingBootstrap.scaler_name}"
139
+ puts " ELB: #{elb_list(config)}" if has_elb
140
+ puts " Key Pair: #{keypair}"
141
+ puts " Zones: #{zones.join(',')}"
142
+ puts " Groups: #{security_groups.sort.join(',')}"
143
+ puts " Instance Type: #{instance_type}"
144
+ puts " Image ID: #{image_id}"
145
+ puts " IAM Role: #{iam_instance_profile}"
146
+ puts " VPC Subnets: #{vpc_subnets}" if use_vpc
147
+ puts " Termination Policies: #{termination_policies.sort.join(',')}"
168
148
 
169
149
  puts "\n\nNOTE! Continuing may have adverse effects if you end up " \
170
150
  "deleting an IN-USE PRODUCTION scaling group. Don't be dumb."
@@ -174,41 +154,41 @@ module Tapjoy
174
154
 
175
155
  # configure environment
176
156
 
177
- def configure_environment(filename, env=nil, config_dir)
178
- if filename.include?(File::SEPARATOR)
179
- facet_file = filename
180
- config_dir = File.expand_path('../../..', facet_file)
181
- else
182
- facet_file = File.join(config_dir, 'config', 'clusters', filename)
183
- end
157
+ def configure_environment(opts)
158
+ filename = opts[:filename]
159
+ facet_file = filename
160
+ config_dir = File.expand_path('../..', facet_file)
161
+ userdata_dir = "#{File.expand_path('../../..', facet_file)}/userdata"
184
162
 
185
- common_path = File.join(config_dir, 'config', 'common')
163
+ common_path = File.join(config_dir, 'common')
186
164
  defaults_hash = self.load_yaml(File.join(common_path, 'defaults.yaml'))
187
165
  facet_hash = self.load_yaml(facet_file)
188
- env ||= facet_hash[:environment]
189
- env ||= defaults_hash[:environment]
190
- Tapjoy::AutoscalingBootstrap.is_valid_env?(config_dir, env)
166
+ env = opts[:env] || facet_hash[:environment] || defaults_hash[:environment]
167
+ Tapjoy::AutoscalingBootstrap.valid_env?(common_path, env)
191
168
  env_hash = self.load_yaml(File.join(common_path, "#{env}.yaml"))
192
169
 
193
170
  new_config = defaults_hash.merge!(env_hash).merge(facet_hash)
194
171
  new_config[:config_dir] = config_dir
195
- aws_env = self.get_security_groups(config_dir, env, new_config[:group])
172
+ new_config[:instance_ids] = opts[:instance_ids] if opts.key?(:instance_ids)
173
+ aws_env = self.get_security_groups(common_path, env, new_config[:group])
174
+ new_config.merge!(aws_env)
196
175
 
176
+ new_config[:autoscale] = false unless new_config[:scaling_type].eql?('dynamic')
177
+ new_config[:tags] << {Name: new_config[:name]}
197
178
  Tapjoy::AutoscalingBootstrap.scaler_name = "#{new_config[:name]}-group"
198
179
  Tapjoy::AutoscalingBootstrap.config_name = "#{new_config[:name]}-config"
199
180
  # If there's no ELB, then Not a ELB
200
- puts new_config[:elb_name]
201
- Tapjoy::AutoscalingBootstrap.elb_name = new_config[:elb_name] || 'NaE'
202
- Tapjoy::AutoscalingBootstrap.create_elb = new_config[:create_elb]
203
- Tapjoy::AutoscalingBootstrap.elb_list = new_config[:elb_list] || []
204
- user_data = self.generate_user_data(new_config)
205
- return new_config, aws_env, user_data
181
+ user_data = self.generate_user_data(userdata_dir,
182
+ new_config[:bootstrap_script], new_config)
183
+
184
+ [new_config, aws_env, user_data]
206
185
  end
207
186
 
208
187
  # Exponential backup
209
188
  def aws_wait(tries)
210
- puts "Sleeping for #{2 ** tries}..."
211
- sleep 2 ** tries
189
+ backoff_sleep = 2 ** tries
190
+ puts "Sleeping for #{backoff_sleep}..."
191
+ sleep backoff_sleep
212
192
  end
213
193
 
214
194
  # Check if security group exists and create it if it does not
@@ -9,11 +9,10 @@ module Tapjoy
9
9
  @client ||= Tapjoy::AutoscalingBootstrap::AWS::Autoscaling.client
10
10
  end
11
11
 
12
- def resize(min_size: 0, max_size: 0, desired_capacity:0)
12
+ def resize(min: 0, max: 0, desired:0)
13
13
  self.client.update_auto_scaling_group(
14
14
  auto_scaling_group_name: Tapjoy::AutoscalingBootstrap.scaler_name,
15
- min_size: min_size, max_size: max_size,
16
- desired_capacity: desired_capacity)
15
+ min_size: min, max_size: max, desired_capacity: desired)
17
16
  end
18
17
 
19
18
  def delete(force_delete: true)
@@ -30,31 +29,36 @@ module Tapjoy
30
29
  )[0][0]
31
30
  end
32
31
 
32
+ def detach
33
+ self.client.detach_instances(
34
+ instance_ids: describe.instances.map(&:instance_id),
35
+ auto_scaling_group_name: Tapjoy::AutoscalingBootstrap.scaler_name,
36
+ should_decrement_desired_capacity: true,
37
+ )
38
+ end
39
+
33
40
  def create(zones:, health_check_type: nil, tags:,
34
- vpc_subnets: nil, create_elb:, **unused_values)
41
+ vpc_subnets: nil, termination_policies: , **unused_values)
35
42
 
36
43
  group_hash = {
37
44
  auto_scaling_group_name: Tapjoy::AutoscalingBootstrap.scaler_name,
38
45
  availability_zones: zones,
39
46
  launch_configuration_name: Tapjoy::AutoscalingBootstrap.config_name,
40
47
  min_size: 0, max_size: 0, desired_capacity: 0,
41
- termination_policies: ['OldestInstance'],
48
+ termination_policies: termination_policies,
42
49
  vpc_zone_identifier: vpc_subnets,
43
50
  tags: Tapjoy::AutoscalingBootstrap::Autoscaling::Group.new.generate_tags(tags)
44
51
  }
45
52
 
46
- # If we've chosen to explicitly create an ELB and assign to this ASG
47
- # OR if we've given it a list of ELBs to join (or both)
48
- if create_elb || !Tapjoy::AutoscalingBootstrap.elb_list.empty?
49
- group_hash.merge!({
50
- load_balancer_names: Tapjoy::AutoscalingBootstrap.elbs_to_join,
51
- health_check_type: health_check_type,
52
- health_check_grace_period: 300,
53
- })
54
- end
55
-
56
53
  self.client.create_auto_scaling_group(**group_hash)
57
54
  end
55
+
56
+ def attach_elb(elb_list)
57
+ self.client.attach_load_balancers({
58
+ auto_scaling_group_name: Tapjoy::AutoscalingBootstrap.scaler_name,
59
+ load_balancer_names: elb_list.split(','),
60
+ })
61
+ end
58
62
  end
59
63
  end
60
64
  end
@@ -1,7 +1,7 @@
1
1
  module Tapjoy
2
2
  module AutoscalingBootstrap
3
3
  module AWS
4
- # This class contains AWS methods for ELB
4
+ # This class contains AWS methods for EC2
5
5
  module EC2
6
6
  class << self
7
7
  def client
@@ -16,6 +16,24 @@ module Tapjoy
16
16
  self.client.create_security_group(group_name: group,
17
17
  description: "Security group for #{Tapjoy::AutoscalingBootstrap.scaler_name}")
18
18
  end
19
+
20
+ def describe_instances_by_tag(config)
21
+ self.client.describe_instances(filters: [
22
+ {name: 'tag:Name', values: [config[:name]]},
23
+ {name: 'instance-state-name', values: %w(running)}
24
+ ])
25
+ end
26
+
27
+ def toggle_termination_protection(instance_id, state)
28
+ client.modify_instance_attribute(
29
+ instance_id: instance_id,
30
+ attribute: 'disableApiTermination',
31
+ value: state)
32
+ end
33
+
34
+ def terminate_instances(instance_ids)
35
+ client.terminate_instances(instance_ids: instance_ids)
36
+ end
19
37
  end
20
38
  end
21
39
  end
@@ -22,7 +22,7 @@ module Tapjoy
22
22
  config[:key_name] = config.delete :keypair
23
23
  config[:launch_configuration_name] = Tapjoy::AutoscalingBootstrap.config_name
24
24
  keys = %w(bootstrap_script chef_server_url clobber clobber_elb
25
- create_as_group config_dir)
25
+ create_as_group)
26
26
  delete_keys(config, keys)
27
27
 
28
28
  config
@@ -61,8 +61,60 @@ module Tapjoy
61
61
  tag_array
62
62
  end
63
63
 
64
+ # Scale auto scaling groups
65
+ def scale(config)
66
+ if config[:scaling_type].eql?('dynamic')
67
+ Tapjoy::AutoscalingBootstrap::AWS::Autoscaling::Group.resize(
68
+ **config[:instance_counts])
69
+ elsif config[:scaling_type].eql?('static')
70
+ scale_static(config)
71
+ else
72
+ abort('Unknown scaling type')
73
+ end
74
+ end
75
+
64
76
  private
65
77
 
78
+ # Logic for scaling static clusters
79
+ def scale_static(config)
80
+ current_count = Tapjoy::AutoscalingBootstrap::EC2.count_static_instances(config)
81
+ count_delta = config[:instance_counts][:desired] - current_count
82
+ if count_delta < 0
83
+ count_delta = count_delta.abs
84
+ puts "Scaling #{count_delta} instances down"
85
+ abort('Instances to terminate must be specified') unless config.key?(:instance_ids)
86
+ unless config[:instance_ids].length.eql?(count_delta)
87
+ fail Tapjoy::AutoscalingBootstrap::Errors::IncorrectNumberIds
88
+ end
89
+ disable_termination_protection(config[:instance_ids])
90
+ Tapjoy::AutoscalingBootstrap::AWS::EC2.terminate_instances(config[:instance_ids])
91
+ elsif count_delta > 0
92
+ puts 'Scaling up...'
93
+ puts count_delta
94
+ Tapjoy::AutoscalingBootstrap::AWS::Autoscaling::Group.resize(
95
+ min: 0, max: count_delta, desired: count_delta)
96
+ wait_for_asg_to_populate(config[:instance_counts][:desired], config)
97
+ enable_termination_protection
98
+ Tapjoy::AutoscalingBootstrap::AWS::Autoscaling::Group.detach
99
+ else
100
+ puts 'No action needed'
101
+ end
102
+ end
103
+
104
+ # Helper method to disable termination protection
105
+ def disable_termination_protection(instance_ids)
106
+ instance_ids.each do |instance|
107
+ Tapjoy::AutoscalingBootstrap::EC2.disable_termination_protection(instance)
108
+ end
109
+ end
110
+ # Helper method to enable termination protection
111
+ def enable_termination_protection
112
+ asg = Tapjoy::AutoscalingBootstrap::AWS::Autoscaling::Group.describe
113
+ asg.instances.map(&:instance_id).each do |instance|
114
+ Tapjoy::AutoscalingBootstrap::EC2.enable_termination_protection(instance)
115
+ end
116
+ end
117
+
66
118
  # Clear out existing autoscaling group
67
119
  def zero_autoscale_group
68
120
  Tapjoy::AutoscalingBootstrap::AWS::Autoscaling::Group.resize
@@ -107,6 +159,17 @@ module Tapjoy
107
159
  Tapjoy::AutoscalingBootstrap::Base.new.aws_wait(tries)
108
160
  end
109
161
  end
162
+
163
+ # Wait for ASG to populate
164
+ def wait_for_asg_to_populate(desired, config)
165
+ current_count = Tapjoy::AutoscalingBootstrap::EC2.count_static_instances(config)
166
+ tries = 0
167
+ until current_count.eql?(desired) do
168
+ tries += 1
169
+ Tapjoy::AutoscalingBootstrap::Base.new.aws_wait(tries)
170
+ current_count = Tapjoy::AutoscalingBootstrap::EC2.count_static_instances(config)
171
+ end
172
+ end
110
173
  end
111
174
  end
112
175
  end
@@ -12,7 +12,7 @@ module Tapjoy
12
12
 
13
13
  # Create autoscaling policy
14
14
  def create(policy, scale)
15
- return unless Tapjoy::AutoscalingBootstrap.group.exists
15
+ fail Tapjoy::AutoscalingBootstrap::Errors::InvalidAutoscalingGroup unless Tapjoy::AutoscalingBootstrap.group.exists
16
16
  Tapjoy::AutoscalingBootstrap::AWS::Autoscaling.put_scaling_policy(
17
17
  policy_name: policy, **scale)
18
18
  end
@@ -3,25 +3,7 @@ module Tapjoy
3
3
  # This class is the central launching point for new autoscaling group creation
4
4
  class AutoscalingGroup
5
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
6
+ def create(opts, new_config, aws_env, user_data)
25
7
 
26
8
  Tapjoy::AutoscalingBootstrap::ConfigureAutoscalers.new(**new_config,
27
9
  aws_env: aws_env, user_data: user_data, misc_config: new_config)
@@ -0,0 +1,26 @@
1
+ module Tapjoy
2
+ module AutoscalingBootstrap
3
+ # This class contains tass methods for EC2
4
+ module EC2
5
+ class << self
6
+ def count_static_instances(config)
7
+ find_static_instances(config).length
8
+ end
9
+
10
+ def enable_termination_protection(instance_id)
11
+ Tapjoy::AutoscalingBootstrap::AWS::EC2.toggle_termination_protection(instance_id, 'true')
12
+ end
13
+
14
+ def disable_termination_protection(instance_id)
15
+ Tapjoy::AutoscalingBootstrap::AWS::EC2.toggle_termination_protection(instance_id, 'false')
16
+ end
17
+
18
+ private
19
+ def find_static_instances(config)
20
+ response = Tapjoy::AutoscalingBootstrap::AWS::EC2.describe_instances_by_tag(config)
21
+ response.reservations
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -2,16 +2,32 @@ module Tapjoy
2
2
  module AutoscalingBootstrap
3
3
  # This class configures elastic load balancers
4
4
  class ELB
5
- # Initialize the class
6
- def initialize
5
+ def initialize(elb_hash, clobber_elb, zones, security_groups)
6
+ elb_config = build_config(elb_hash, zones, security_groups)
7
+ check_valid_config(elb_config)
8
+
9
+ if exists && clobber_elb
10
+ delete
11
+ create(elb_config)
12
+ elsif exists
13
+ Tapjoy::AutoscalingBootstrap::AWS::Autoscaling::Group.attach_elb(
14
+ Tapjoy::AutoscalingBootstrap.elb_name)
15
+ else
16
+ create(elb_config)
17
+ end
7
18
  end
8
19
 
9
- # Create load balancer
10
- def create(config, aws_env)
20
+ # Build config hash
21
+ def build_config(elb_hash, zones, security_groups)
22
+ elb_config = elb_hash[Tapjoy::AutoscalingBootstrap.elb_name]
23
+ elb_config[:elb_protocol] ||= elb_config[:instance_protocol]
24
+ elb_config[:elb_health_target] ||= "#{elb_config[:instance_protocol]}:#{elb_config[:instance_port]}/healthz"
25
+ elb_config.merge!({zones: zones, groups: security_groups})
26
+ end
11
27
 
12
- check_valid_config(config)
13
- delete if exists
14
- Tapjoy::AutoscalingBootstrap::AWS::ELB.create(**config, **aws_env)
28
+ # Create load balancer
29
+ def create(config)
30
+ Tapjoy::AutoscalingBootstrap::AWS::ELB.create(**config)
15
31
  health_check(config)
16
32
  end
17
33
 
@@ -25,6 +25,15 @@ module Tapjoy
25
25
  abort("ERROR: Specified autoscaling group doesn't exist")
26
26
  end
27
27
  end
28
+
29
+ # Raise if an incorrect number of instance ids have been specified
30
+ class IncorrectNumberIds < ArgumentError
31
+ def initialize
32
+ error = 'Number of instance IDs specified must match the number '\
33
+ 'of instances scaled down'
34
+ abort(error)
35
+ end
36
+ end
28
37
  end
29
38
  end
30
39
  end
@@ -1,9 +1,9 @@
1
1
  module Tapjoy
2
2
  module AutoscalingBootstrap
3
3
  module Version
4
- MAJOR = 0
5
- MINOR = 2
6
- PATCH = 2
4
+ MAJOR = 1
5
+ MINOR = 0
6
+ PATCH = 0
7
7
  end
8
8
 
9
9
  VERSION = [Version::MAJOR, Version::MINOR, Version::PATCH].join('.')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ali Tayarani
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-22 00:00:00.000000000 Z
11
+ date: 2015-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: trollop
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '2.9'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec_junit_formatter
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '='
130
+ - !ruby/object:Gem::Version
131
+ version: 0.2.2
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '='
137
+ - !ruby/object:Gem::Version
138
+ version: 0.2.2
125
139
  description: TASS is the suite of tools that the Tapjoy Operations team uses to manage
126
140
  autoscaling groups and launch configurations.
127
141
  email: ali.tayarani@tapjoy.com
@@ -150,6 +164,7 @@ files:
150
164
  - lib/tapjoy/autoscaling_bootstrap/aws.rb
151
165
  - lib/tapjoy/autoscaling_bootstrap/cloudwatch.rb
152
166
  - lib/tapjoy/autoscaling_bootstrap/configure_autoscaler.rb
167
+ - lib/tapjoy/autoscaling_bootstrap/ec2.rb
153
168
  - lib/tapjoy/autoscaling_bootstrap/elb.rb
154
169
  - lib/tapjoy/autoscaling_bootstrap/errors.rb
155
170
  - lib/tapjoy/autoscaling_bootstrap/errors/elb.rb