aerosol 1.8.0 → 1.9.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
  SHA256:
3
- metadata.gz: 8800e253ba3945d047a0186145a0aa58bc2d1ea2374ca6cc3e8f9e102a8ad510
4
- data.tar.gz: 9748857dd6d759985cf7e1071364474dbb013b2eff7eae3c86616e0eebcc1879
3
+ metadata.gz: 5c51be45f1098f15a79cbab049755110bf351bed1661bb5b28504ab34c613f01
4
+ data.tar.gz: 235972faf898d0cc796cdf0b7de74f05a6c3aa396dc13b9f0f8909fb1229cecb
5
5
  SHA512:
6
- metadata.gz: 143084a0ffcd6ed83e36bea8a106e88776cc146adacc7d55b3976f52fd0ce80d6e0c7543311c5d82110900ce927cca5ca29bb4a06903131497d88ae7ed02a7f6
7
- data.tar.gz: 4ea6f13e4f3464f04ab05bd33d504f586c5206cbf13bfbdeed63411ad2a2170b812631d8185c18981a8c46dfc55d5f18d189a59826b04129aca4c14d034148a3
6
+ metadata.gz: 5aa215e96061f829d5042d72c56495f0059cb716b12b89386ca84e7b5568b6993d39a18d07e216c90de2af96ba742d5ea588c733e0303d275ffdb16bfb7f8965
7
+ data.tar.gz: 890ced1dce45bcf8ab1de6d60834f78bd881490efd9d7473ada54ac92359a691c53f031959c9cb7e08fb1745c7d9ada0abb84b00913d83e5166cb661c252fdbd
data/lib/aerosol.rb CHANGED
@@ -13,6 +13,7 @@ module Aerosol
13
13
  require 'aerosol/util'
14
14
  require 'aerosol/aws_model'
15
15
  require 'aerosol/launch_configuration'
16
+ require 'aerosol/launch_template'
16
17
  require 'aerosol/auto_scaling'
17
18
  require 'aerosol/instance'
18
19
  require 'aerosol/connection'
@@ -61,6 +62,7 @@ module Aerosol
61
62
  :auto_scalings => Aerosol::AutoScaling.instances,
62
63
  :deploys => Aerosol::Deploy.instances,
63
64
  :launch_configurations => Aerosol::LaunchConfiguration.instances,
65
+ :launch_templates => Aerosol::LaunchTemplate.instances,
64
66
  :sshs => Aerosol::Connection.instances,
65
67
  :envs => Aerosol::Env.instances
66
68
  }
@@ -70,6 +72,7 @@ module Aerosol
70
72
  :auto_scaling => Aerosol::AutoScaling,
71
73
  :deploy => Aerosol::Deploy,
72
74
  :launch_configuration => Aerosol::LaunchConfiguration,
75
+ :launch_template => Aerosol::LaunchTemplate,
73
76
  :ssh => Aerosol::Connection,
74
77
  :env => Aerosol::Env
75
78
  }.each do |method, klass|
@@ -82,15 +85,15 @@ module Aerosol
82
85
  end
83
86
  end
84
87
 
85
- [:auto_scalings, :deploys, :launch_configurations, :sshs, :envs].each do |method|
88
+ [:auto_scalings, :deploys, :launch_configurations, :launch_templates, :sshs, :envs].each do |method|
86
89
  define_method(method) do
87
90
  inst[method]
88
91
  end
89
92
  end
90
93
 
91
94
  module_function :inst, :load_inst, :setup, :load_file, :load_file=,
92
- :auto_scaling, :launch_configuration, :deploy, :ssh, :git_sha,
93
- :auto_scalings, :launch_configurations, :deploys, :sshs,
95
+ :auto_scaling, :launch_configuration, :launch_template, :deploy, :ssh, :git_sha,
96
+ :auto_scalings, :launch_configurations, :launch_templates, :deploys, :sshs,
94
97
  :namespace, :env, :envs, :region
95
98
  end
96
99
 
@@ -7,6 +7,7 @@ class Aerosol::AutoScaling
7
7
  :desired_capacity, :health_check_grace_period, :health_check_type, :load_balancer_names,
8
8
  :placement_group, :tags, :created_time, :vpc_zone_identifier, :target_group_arns
9
9
  aws_class_attribute :launch_configuration, Aerosol::LaunchConfiguration
10
+ aws_class_attribute :launch_template, Aerosol::LaunchTemplate
10
11
  primary_key :auto_scaling_group_name
11
12
 
12
13
  def initialize(options={}, &block)
@@ -38,21 +39,30 @@ class Aerosol::AutoScaling
38
39
  end
39
40
 
40
41
  def create!
41
- ensure_present! :launch_configuration, :max_size, :min_size
42
+ ensure_present! :max_size, :min_size
42
43
  raise 'availability_zones or vpc_zone_identifier must be set' if [availability_zones, vpc_zone_identifier].none?
44
+ raise 'launch_configuration or launch_template must be set' if [launch_configuration, launch_template].none?
43
45
 
44
46
  info "creating auto scaling group"
45
- launch_configuration.create
47
+ launch_details = create_launch_details
48
+
46
49
  info self.inspect
47
50
 
48
51
  conn.create_auto_scaling_group({
49
52
  auto_scaling_group_name: auto_scaling_group_name,
50
53
  availability_zones: [*availability_zones],
51
- launch_configuration_name: launch_configuration.launch_configuration_name,
52
54
  max_size: max_size,
53
55
  min_size: min_size
54
- }.merge(create_options))
55
- sleep 10
56
+ }
57
+ .merge(create_options)
58
+ .merge(launch_details)
59
+ )
60
+
61
+ conn.wait_until(:group_in_service, auto_scaling_group_names: [auto_scaling_group_name]) do |waiter|
62
+ waiter.before_wait do |attempt_count, _response|
63
+ info "Wait count #{attempt_count} of #{waiter.max_attempts} for #{auto_scaling_group_name} to be in service"
64
+ end
65
+ end
56
66
  end
57
67
 
58
68
  def destroy!
@@ -147,6 +157,22 @@ private
147
157
  Aerosol::AWS.auto_scaling
148
158
  end
149
159
 
160
+ def create_launch_details
161
+ if launch_configuration
162
+ launch_configuration.create
163
+ { launch_configuration_name: launch_configuration.launch_configuration_name }
164
+ elsif launch_template
165
+ launch_template.create
166
+ {
167
+ launch_template:
168
+ {
169
+ launch_template_name: launch_template.launch_template_name,
170
+ version: '$Latest'
171
+ }
172
+ }
173
+ end
174
+ end
175
+
150
176
  def create_options
151
177
  {
152
178
  default_cooldown: default_cooldown,
@@ -0,0 +1,133 @@
1
+ class Aerosol::LaunchTemplate
2
+ include Aerosol::AWSModel
3
+ include Dockly::Util::Logger::Mixin
4
+
5
+ logger_prefix '[aerosol launch_template]'
6
+ aws_attribute :launch_template_name, :image_id, :instance_type, :security_groups, :user_data,
7
+ :iam_instance_profile, :kernel_id, :key_name, :spot_price, :created_time,
8
+ :network_interfaces, :block_device_mappings, :ebs_optimized
9
+ dsl_attribute :meta_data
10
+
11
+ primary_key :launch_template_name
12
+ default_value(:security_groups) { [] }
13
+ default_value(:meta_data) { {} }
14
+
15
+ def launch_template_name(arg = nil)
16
+ if arg
17
+ raise "You cannot set the launch_template_name directly" unless from_aws
18
+ @launch_template_name = arg
19
+ else
20
+ @launch_template_name || default_identifier
21
+ end
22
+ end
23
+
24
+ def exists?
25
+ info "launch_template: needed?: #{launch_template_name}: " +
26
+ "checking for launch template: #{launch_template_name}"
27
+ exists = super
28
+ info "launch template: needed?: #{launch_template_name}: " +
29
+ "#{exists ? 'found' : 'did not find'} launch template: #{launch_template_name}"
30
+ exists
31
+ end
32
+
33
+ def security_group(group)
34
+ security_groups << group
35
+ end
36
+
37
+ def create!
38
+ ensure_present! :image_id, :instance_type
39
+
40
+ info "creating launch template"
41
+ conn.create_launch_template(
42
+ launch_template_name: launch_template_name,
43
+ launch_template_data: {
44
+ image_id: image_id,
45
+ instance_type: instance_type,
46
+ monitoring: {
47
+ enabled: true
48
+ },
49
+ }.merge(create_options)
50
+ )
51
+ info self.inspect
52
+ end
53
+
54
+ def destroy!
55
+ info self.to_s
56
+ raise StandardError.new('No launch_template_name found') unless launch_template_name
57
+ conn.delete_launch_template(launch_template_name: launch_template_name)
58
+ end
59
+
60
+ def all_instances
61
+ Aerosol::Instance.all.select { |instance|
62
+ !instance.launch_template.nil? &&
63
+ (instance.launch_template.launch_template == launch_template_name)
64
+ }.each(&:description)
65
+ end
66
+
67
+ def self.request_all_for_token(next_token)
68
+ options = next_token.nil? ? {} : { next_token: next_token }
69
+ Aerosol::AWS.compute.describe_launch_templates(options)
70
+ end
71
+
72
+ def self.request_all
73
+ next_token = nil
74
+ lts = []
75
+
76
+ begin
77
+ new_lts = request_all_for_token(next_token)
78
+ lts.concat(new_lts.launch_templates)
79
+ next_token = new_lts.next_token
80
+ end until next_token.nil?
81
+
82
+ lts
83
+ end
84
+
85
+ def to_s
86
+ %{Aerosol::LaunchTemplate { \
87
+ "launch_template_name" => "#{launch_template_name}", \
88
+ "image_id" => "#{image_id}", \
89
+ "instance_type" => "#{instance_type}", \
90
+ "security_group_ids" => #{security_groups.to_s}, \
91
+ "user_data" => "#{user_data}", \
92
+ "iam_instance_profile" => "#{iam_instance_profile}", \
93
+ "kernel_id" => "#{kernel_id}", \
94
+ "key_name" => "#{key_name}", \
95
+ "spot_price" => "#{spot_price}", \
96
+ "created_time" => "#{created_time}", \
97
+ "block_device_mappings" => #{block_device_mappings}", \
98
+ "ebs_optimized" => #{ebs_optimized} \
99
+ }}
100
+ end
101
+
102
+ def corrected_user_data
103
+ realized_user_data = user_data.is_a?(Proc) ? user_data.call : user_data
104
+
105
+ Base64.encode64(Aerosol::Util.strip_heredoc(realized_user_data || ''))
106
+ end
107
+
108
+ private
109
+ def create_options
110
+ instance_market_options = {
111
+ market_type: 'spot',
112
+ spot_options: {
113
+ max_price: spot_price
114
+ }
115
+ } if spot_price
116
+
117
+ {
118
+ iam_instance_profile: { name: iam_instance_profile },
119
+ kernel_id: kernel_id,
120
+ key_name: key_name,
121
+ security_group_ids: security_groups,
122
+ instance_market_options: instance_market_options,
123
+ user_data: corrected_user_data,
124
+ network_interfaces: network_interfaces,
125
+ block_device_mappings: block_device_mappings,
126
+ ebs_optimized: ebs_optimized,
127
+ }.reject { |k, v| v.nil? }
128
+ end
129
+
130
+ def conn
131
+ Aerosol::AWS.compute
132
+ end
133
+ end
@@ -1,5 +1,5 @@
1
1
  # Copyright Swipely, Inc. All rights reserved.
2
2
 
3
3
  module Aerosol
4
- VERSION = '1.8.0'
4
+ VERSION = '1.9.0'
5
5
  end
@@ -0,0 +1,402 @@
1
+ require 'spec_helper'
2
+
3
+ describe Aerosol::LaunchTemplate do
4
+ subject do
5
+ described_class.new do
6
+ name :my_launch_template
7
+ image_id 'ami-123'
8
+ instance_type 'super-cool-instance-type'
9
+ user_data <<-END_OF_STRING
10
+ #!/bin/bash
11
+ rm -rf /
12
+ END_OF_STRING
13
+ end
14
+ end
15
+ before { subject.stub(:sleep) }
16
+
17
+ describe "#launch_template_name" do
18
+ context "with no namespace set" do
19
+ let(:identifier) { "my_launch_template-#{Aerosol::Util.git_sha}" }
20
+ it "returns a normal identifier" do
21
+ expect(subject.launch_template_name).to eq(identifier)
22
+ end
23
+ end
24
+
25
+ context "with a namespace set" do
26
+ let(:namespace) { "test" }
27
+ let(:identifier) { "#{namespace}-my_launch_template-#{Aerosol::Util.git_sha}" }
28
+
29
+ before { Aerosol.namespace namespace }
30
+ after { Aerosol.instance_variable_set(:"@namespace", nil) }
31
+
32
+ it "returns a namespaced identifier" do
33
+ expect(subject.launch_template_name).to eq(identifier)
34
+ end
35
+ end
36
+ end
37
+
38
+ describe '#security_group' do
39
+ subject { described_class.new!(:name => 'conf-conf-conf') }
40
+
41
+ it 'adds the argument to the list of security groups' do
42
+ expect { subject.security_group 'my group' }
43
+ .to change { subject.security_groups.length }
44
+ .by 1
45
+ end
46
+
47
+ it 'does not the default security group' do
48
+ expect { subject.security_group 'other test' }
49
+ .to_not change { described_class.default_values[:security_groups] }
50
+ end
51
+ end
52
+
53
+ describe '#create!' do
54
+ context 'when some required fields are nil' do
55
+ before { subject.instance_variable_set(:@image_id, nil) }
56
+
57
+ it 'raises an error' do
58
+ expect { subject.create! }.to raise_error
59
+ end
60
+ end
61
+
62
+ context 'when everything is present' do
63
+ context 'and the launch template already exists' do
64
+ it 'raises an error' do
65
+ Aerosol::AWS.compute.stub_responses(
66
+ :create_launch_template,
67
+ Aws::EC2::Errors::AlreadyExists
68
+ )
69
+ expect { subject.create! }.to raise_error
70
+ end
71
+ end
72
+
73
+ context 'and the launch template does not exist yet' do
74
+ after { subject.destroy! rescue nil }
75
+
76
+ it 'creates the launch template group' do
77
+ Aerosol::AWS.compute.stub_responses(:create_launch_template, [])
78
+ expect { subject.create! }.to_not raise_error
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ describe '#destroy!' do
85
+ context 'when the launch_template_name is nil' do
86
+
87
+ it 'raises an error' do
88
+ allow(subject).to receive(:launch_template_name).and_return(nil)
89
+ Aerosol::AWS.compute.stub_responses(:delete_launch_template, [])
90
+ expect { subject.destroy! }.to raise_error
91
+ end
92
+ end
93
+
94
+ context 'when the launch_template_name is present' do
95
+ context 'but the launch template does not exist' do
96
+ it 'raises an error' do
97
+ Aerosol::AWS.compute.stub_responses(
98
+ :delete_launch_template,
99
+ Aws::EC2::Errors::ValidationError
100
+ )
101
+ expect { subject.destroy! }.to raise_error
102
+ end
103
+ end
104
+
105
+ context 'and the launch template exists' do
106
+ it 'deletes the launch template' do
107
+ Aerosol::AWS.compute.stub_responses(:delete_launch_template, [])
108
+ expect { subject.destroy! }.to_not raise_error
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ describe '#create' do
115
+ context 'when the launch_template_name is nil' do
116
+ subject do
117
+ described_class.new! do
118
+ name :random_test_name
119
+ image_id 'test-ami-who-even-cares-really'
120
+ instance_type 'm1.large'
121
+ end
122
+ end
123
+
124
+ it 'raises an error' do
125
+ allow(subject).to receive(:launch_template_name).and_return(nil)
126
+ Aerosol::AWS.compute.stub_responses(:create_launch_template, [])
127
+ Aerosol::AWS.compute.stub_responses(:describe_launch_templates, {
128
+ launch_templates: [], next_token: nil
129
+ })
130
+ expect { subject.create }.to raise_error
131
+ end
132
+ end
133
+
134
+ context 'when the launch_template_name is present' do
135
+ subject do
136
+ described_class.new! do
137
+ name :random_test_name_2
138
+ image_id 'test-ami-who-even-cares-really'
139
+ instance_type 'm1.large'
140
+ end
141
+ end
142
+
143
+ context 'but the launch template already exists' do
144
+ it 'does not call #create!' do
145
+ Aerosol::AWS.compute.stub_responses(:describe_launch_templates, {
146
+ launch_templates: [{
147
+ launch_template_name: subject.launch_template_name,
148
+ }],
149
+ next_token: nil
150
+ })
151
+ expect(subject).to_not receive(:create!)
152
+ subject.create
153
+ end
154
+ end
155
+
156
+ context 'and the launch template does not yet exist' do
157
+ it 'creates it' do
158
+ Aerosol::AWS.compute.stub_responses(:describe_launch_templates, {
159
+ launch_templates: [],
160
+ next_token: nil
161
+ })
162
+ subject.should_receive(:create!)
163
+ subject.create
164
+ end
165
+ end
166
+ end
167
+ end
168
+
169
+ describe '#destroy' do
170
+ subject do
171
+ described_class.new! do
172
+ name :random_test_name_3
173
+ image_id 'awesome-ami'
174
+ instance_type 'm1.large'
175
+ end
176
+ end
177
+
178
+ context 'when the launch_template_name is nil' do
179
+ it 'raises an error' do
180
+ allow(subject).to receive(:launch_template_name).and_return(nil)
181
+ Aerosol::AWS.compute.stub_responses(:describe_launch_templates, {
182
+ launch_templates: [],
183
+ next_token: nil
184
+ })
185
+ expect { subject.create }.to raise_error(ArgumentError)
186
+ end
187
+ end
188
+
189
+ context 'when the launch_template_name is present' do
190
+ context 'and the launch template already exists' do
191
+
192
+ it 'calls #destroy!' do
193
+ Aerosol::AWS.compute.stub_responses(:describe_launch_templates, {
194
+ launch_templates: [{
195
+ launch_template_name: subject.launch_template_name
196
+ }],
197
+ next_token: nil
198
+ })
199
+ subject.should_receive(:destroy!)
200
+ subject.destroy
201
+ end
202
+ end
203
+
204
+ context 'but the launch template does not yet exist' do
205
+ it 'does not call #destroy!' do
206
+ Aerosol::AWS.compute.stub_responses(:describe_launch_templates, {
207
+ launch_templates: [],
208
+ next_token: nil
209
+ })
210
+ subject.should_not_receive(:destroy!)
211
+ subject.destroy
212
+ end
213
+ end
214
+ end
215
+ end
216
+
217
+ describe '.exists?' do
218
+ subject { described_class }
219
+ let(:instance) do
220
+ subject.new! do
221
+ name :exists_test_name
222
+ image_id 'ami123'
223
+ instance_type 'm1.large'
224
+ stub(:sleep)
225
+ end
226
+ end
227
+
228
+ context 'when the argument exists' do
229
+ it 'returns true' do
230
+ Aerosol::AWS.compute.stub_responses(:describe_launch_templates, {
231
+ launch_templates: [{
232
+ launch_template_name: instance.launch_template_name,
233
+ }],
234
+ next_token: nil
235
+ })
236
+ subject.exists?(instance.launch_template_name).should be_true
237
+ end
238
+ end
239
+
240
+ context 'when the argument does not exist' do
241
+ let(:instance) { described_class.new! }
242
+
243
+ it 'returns false' do
244
+ Aerosol::AWS.compute.stub_responses(:describe_launch_templates, {
245
+ launch_templates: [],
246
+ next_token: nil
247
+ })
248
+ subject.exists?(instance.launch_template_name).should be_false
249
+ end
250
+ end
251
+ end
252
+
253
+ describe '.request_all' do
254
+ describe 'repeats until no NextToken' do
255
+ it 'should include both autoscaling groups lists' do
256
+ Aerosol::AWS.compute.stub_responses(:describe_launch_templates, [
257
+ {
258
+ launch_templates: [
259
+ { launch_template_name: '1' },
260
+ { launch_template_name: '4' }
261
+ ],
262
+ next_token: 'yes'
263
+ },
264
+ {
265
+ launch_templates: [
266
+ { launch_template_name: '2' },
267
+ { launch_template_name: '3' }
268
+ ],
269
+ next_token: nil
270
+ }
271
+ ])
272
+ expect(Aerosol::LaunchTemplate.request_all.map(&:launch_template_name)).to eq(['1','4','2','3'])
273
+ end
274
+ end
275
+ end
276
+
277
+ describe '.all' do
278
+ subject { described_class }
279
+
280
+ context 'when there are no launch templates' do
281
+ before do
282
+ Aerosol::AWS.compute.stub_responses(:describe_launch_templates, [
283
+ { launch_templates: [], next_token: nil }
284
+ ])
285
+ end
286
+ its(:all) { should be_empty }
287
+ end
288
+
289
+ context 'when there are launch templates' do
290
+ let(:insts) {
291
+ [
292
+ { launch_template_name: 'test' },
293
+ { launch_template_name: 'test2' }
294
+ ]
295
+ }
296
+
297
+ it 'returns each of them' do
298
+ Aerosol::AWS.compute.stub_responses(:describe_launch_templates, {
299
+ launch_templates: insts,
300
+ next_token: nil
301
+ })
302
+ subject.all.map(&:launch_template_name).should == %w[test test2]
303
+ end
304
+ end
305
+ end
306
+
307
+ describe '.from_hash' do
308
+ context 'when the launch template has not been initialized' do
309
+ subject { described_class.from_hash(hash) }
310
+ let(:hash) do
311
+ {
312
+ launch_template_name: '~test-launch-config~',
313
+ image_id: 'ami-123',
314
+ instance_type: 'm1.large',
315
+ security_groups: [],
316
+ user_data: 'echo hi',
317
+ iam_instance_profile: nil,
318
+ kernel_id: 'kernel-id',
319
+ key_name: 'key-name',
320
+ spot_price: '0.04',
321
+ }
322
+ end
323
+
324
+ it 'creates a new launch template with the specified values' do
325
+ subject.launch_template_name.should == '~test-launch-config~'
326
+ subject.image_id.should == 'ami-123'
327
+ subject.instance_type.should == 'm1.large'
328
+ subject.security_groups.should be_empty
329
+ subject.user_data.should == 'echo hi'
330
+ subject.iam_instance_profile.should be_nil
331
+ subject.kernel_id.should == 'kernel-id'
332
+ subject.spot_price.should == '0.04'
333
+ subject.from_aws = true
334
+ end
335
+
336
+ it 'generates a name' do
337
+ subject.name.to_s.should start_with 'LaunchTemplate_'
338
+ end
339
+ end
340
+
341
+ context 'when the launch template has already been initialized' do
342
+ let(:old_hash) do
343
+ {
344
+ launch_template_name: 'this-aws-id-abc-123',
345
+ image_id: 'ami-456',
346
+ }
347
+ end
348
+ let(:new_hash) { old_hash.merge(instance_type: 'm1.large') }
349
+ let!(:existing) { described_class.from_hash(old_hash) }
350
+ let(:new) { described_class.from_hash(new_hash) }
351
+
352
+ it 'makes a new instance' do
353
+ expect { new }.to change { described_class.instances.length }.by(1)
354
+ new.launch_template_name.should == 'this-aws-id-abc-123'
355
+ new.image_id.should == 'ami-456'
356
+ end
357
+ end
358
+ end
359
+
360
+ describe '#corrected_user_data' do
361
+ let(:encoded_user_data_string) { Base64.encode64('test') }
362
+
363
+ context 'when the user_data is a String' do
364
+ subject do
365
+ described_class.new do
366
+ name :corrected_user_data
367
+ user_data 'test'
368
+ end
369
+ end
370
+
371
+ it 'correctly encodes to base64' do
372
+ expect(subject.corrected_user_data).to eq(encoded_user_data_string)
373
+ end
374
+ end
375
+
376
+ context 'when the user_data is a Proc' do
377
+ subject do
378
+ described_class.new do
379
+ name :corrected_user_data_2
380
+ user_data { 'test' }
381
+ end
382
+ end
383
+
384
+ it 'correctly encodes to base64' do
385
+ expect(subject.corrected_user_data).to eq(encoded_user_data_string)
386
+ end
387
+ end
388
+ end
389
+
390
+ describe '#meta_data' do
391
+ subject do
392
+ described_class.new do
393
+ name :my_launch_template
394
+ meta_data('Test' => '1')
395
+ end
396
+ end
397
+
398
+ it 'returns the hash' do
399
+ expect(subject.meta_data['Test']).to eq('1')
400
+ end
401
+ end
402
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aerosol
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Swipely, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-29 00:00:00.000000000 Z
11
+ date: 2021-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -280,6 +280,7 @@ files:
280
280
  - lib/aerosol/env.rb
281
281
  - lib/aerosol/instance.rb
282
282
  - lib/aerosol/launch_configuration.rb
283
+ - lib/aerosol/launch_template.rb
283
284
  - lib/aerosol/rake_task.rb
284
285
  - lib/aerosol/runner.rb
285
286
  - lib/aerosol/util.rb
@@ -292,6 +293,7 @@ files:
292
293
  - spec/aerosol/env_spec.rb
293
294
  - spec/aerosol/instance_spec.rb
294
295
  - spec/aerosol/launch_configuration_spec.rb
296
+ - spec/aerosol/launch_template_spec.rb
295
297
  - spec/aerosol/rake_task_spec.rb
296
298
  - spec/aerosol/runner_spec.rb
297
299
  - spec/aerosol_spec.rb
@@ -329,6 +331,7 @@ test_files:
329
331
  - spec/aerosol/env_spec.rb
330
332
  - spec/aerosol/instance_spec.rb
331
333
  - spec/aerosol/launch_configuration_spec.rb
334
+ - spec/aerosol/launch_template_spec.rb
332
335
  - spec/aerosol/rake_task_spec.rb
333
336
  - spec/aerosol/runner_spec.rb
334
337
  - spec/aerosol_spec.rb