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 +4 -4
- data/bin/tass +53 -26
- data/lib/tapjoy/autoscaling_bootstrap.rb +45 -65
- data/lib/tapjoy/autoscaling_bootstrap/AWS/Autoscaling/group.rb +19 -15
- data/lib/tapjoy/autoscaling_bootstrap/AWS/ec2.rb +19 -1
- data/lib/tapjoy/autoscaling_bootstrap/audit.rb +1 -1
- data/lib/tapjoy/autoscaling_bootstrap/autoscaling/group.rb +63 -0
- data/lib/tapjoy/autoscaling_bootstrap/autoscaling/policy.rb +1 -1
- data/lib/tapjoy/autoscaling_bootstrap/autoscaling_group.rb +1 -19
- data/lib/tapjoy/autoscaling_bootstrap/ec2.rb +26 -0
- data/lib/tapjoy/autoscaling_bootstrap/elb.rb +23 -7
- data/lib/tapjoy/autoscaling_bootstrap/errors.rb +9 -0
- data/lib/tapjoy/autoscaling_bootstrap/version.rb +3 -3
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d63df49ef7d75eeec0d74aef90721a098a829efa
|
4
|
+
data.tar.gz: 23bf79d63f1bb9157c51896c85e05ed28ed20f47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
8
|
-
|
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
|
-
|
11
|
-
|
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($
|
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
|
-
|
43
|
+
common_args
|
36
44
|
end
|
37
45
|
|
38
|
-
config, aws_env, user_data =
|
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
|
-
|
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 =
|
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
|
-
|
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 =
|
71
|
-
Aws.config[:region] = config[:aws_region]
|
88
|
+
config, aws_env, user_data = configure_environment(opts)
|
72
89
|
|
73
|
-
config.merge!(aws_env.merge(
|
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
|
87
|
-
env_list =
|
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(
|
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(
|
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}
|
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,
|
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:
|
159
|
-
puts " Auto Scaler:
|
160
|
-
puts " ELB:
|
161
|
-
puts " Key Pair:
|
162
|
-
puts " Zones:
|
163
|
-
puts " Groups:
|
164
|
-
puts " Instance Type:
|
165
|
-
puts " Image ID:
|
166
|
-
puts " IAM Role:
|
167
|
-
puts " VPC Subnets:
|
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(
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
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, '
|
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
|
189
|
-
env
|
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
|
-
|
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
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
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
|
-
|
211
|
-
|
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(
|
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:
|
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,
|
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:
|
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
|
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
|
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
|
-
|
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
|
-
|
6
|
-
|
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
|
-
#
|
10
|
-
def
|
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
|
-
|
13
|
-
|
14
|
-
Tapjoy::AutoscalingBootstrap::AWS::ELB.create(**config
|
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
|
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.
|
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-
|
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
|