aerosol 1.6.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.travis.yml +1 -2
- data/aerosol.gemspec +5 -2
- data/lib/aerosol.rb +10 -4
- data/lib/aerosol/auto_scaling.rb +35 -7
- data/lib/aerosol/cli.rb +15 -0
- data/lib/aerosol/launch_configuration.rb +5 -3
- data/lib/aerosol/launch_template.rb +133 -0
- data/lib/aerosol/rake_task.rb +0 -2
- data/lib/aerosol/version.rb +1 -1
- data/spec/aerosol/launch_template_spec.rb +402 -0
- metadata +58 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 5c51be45f1098f15a79cbab049755110bf351bed1661bb5b28504ab34c613f01
|
4
|
+
data.tar.gz: 235972faf898d0cc796cdf0b7de74f05a6c3aa396dc13b9f0f8909fb1229cecb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5aa215e96061f829d5042d72c56495f0059cb716b12b89386ca84e7b5568b6993d39a18d07e216c90de2af96ba742d5ea588c733e0303d275ffdb16bfb7f8965
|
7
|
+
data.tar.gz: 890ced1dce45bcf8ab1de6d60834f78bd881490efd9d7473ada54ac92359a691c53f031959c9cb7e08fb1745c7d9ada0abb84b00913d83e5166cb661c252fdbd
|
data/.travis.yml
CHANGED
data/aerosol.gemspec
CHANGED
@@ -18,14 +18,17 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.add_dependency 'activerecord', '>= 3.2.0'
|
19
19
|
gem.add_dependency 'clamp', '~> 0.6'
|
20
20
|
gem.add_dependency 'excon'
|
21
|
-
gem.add_dependency 'aws-sdk', '~>
|
21
|
+
gem.add_dependency 'aws-sdk-core', '~> 3'
|
22
|
+
gem.add_dependency 'aws-sdk-s3', '~> 1'
|
23
|
+
gem.add_dependency 'aws-sdk-ec2', '~> 1'
|
24
|
+
gem.add_dependency 'aws-sdk-autoscaling', '~> 1'
|
22
25
|
gem.add_dependency 'minigit', '~> 0.0.4'
|
23
26
|
gem.add_dependency 'net-ssh'
|
24
27
|
gem.add_dependency 'net-ssh-gateway'
|
25
28
|
gem.add_dependency 'dockly-util', '~> 0.1.0'
|
26
29
|
gem.add_development_dependency 'cane'
|
27
30
|
gem.add_development_dependency 'pry'
|
28
|
-
gem.add_development_dependency 'rake'
|
31
|
+
gem.add_development_dependency 'rake', '~> 10.0'
|
29
32
|
gem.add_development_dependency 'rspec', '< 3.0'
|
30
33
|
gem.add_development_dependency 'webmock'
|
31
34
|
gem.add_development_dependency 'vcr'
|
data/lib/aerosol.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'yaml'
|
2
|
-
require 'aws-sdk'
|
2
|
+
require 'aws-sdk-autoscaling'
|
3
|
+
require 'aws-sdk-core'
|
4
|
+
require 'aws-sdk-s3'
|
5
|
+
require 'aws-sdk-ec2'
|
3
6
|
require 'dockly/util'
|
4
7
|
require 'base64'
|
5
8
|
|
@@ -10,6 +13,7 @@ module Aerosol
|
|
10
13
|
require 'aerosol/util'
|
11
14
|
require 'aerosol/aws_model'
|
12
15
|
require 'aerosol/launch_configuration'
|
16
|
+
require 'aerosol/launch_template'
|
13
17
|
require 'aerosol/auto_scaling'
|
14
18
|
require 'aerosol/instance'
|
15
19
|
require 'aerosol/connection'
|
@@ -58,6 +62,7 @@ module Aerosol
|
|
58
62
|
:auto_scalings => Aerosol::AutoScaling.instances,
|
59
63
|
:deploys => Aerosol::Deploy.instances,
|
60
64
|
:launch_configurations => Aerosol::LaunchConfiguration.instances,
|
65
|
+
:launch_templates => Aerosol::LaunchTemplate.instances,
|
61
66
|
:sshs => Aerosol::Connection.instances,
|
62
67
|
:envs => Aerosol::Env.instances
|
63
68
|
}
|
@@ -67,6 +72,7 @@ module Aerosol
|
|
67
72
|
:auto_scaling => Aerosol::AutoScaling,
|
68
73
|
:deploy => Aerosol::Deploy,
|
69
74
|
:launch_configuration => Aerosol::LaunchConfiguration,
|
75
|
+
:launch_template => Aerosol::LaunchTemplate,
|
70
76
|
:ssh => Aerosol::Connection,
|
71
77
|
:env => Aerosol::Env
|
72
78
|
}.each do |method, klass|
|
@@ -79,15 +85,15 @@ module Aerosol
|
|
79
85
|
end
|
80
86
|
end
|
81
87
|
|
82
|
-
[:auto_scalings, :deploys, :launch_configurations, :sshs, :envs].each do |method|
|
88
|
+
[:auto_scalings, :deploys, :launch_configurations, :launch_templates, :sshs, :envs].each do |method|
|
83
89
|
define_method(method) do
|
84
90
|
inst[method]
|
85
91
|
end
|
86
92
|
end
|
87
93
|
|
88
94
|
module_function :inst, :load_inst, :setup, :load_file, :load_file=,
|
89
|
-
:auto_scaling, :launch_configuration, :deploy, :ssh, :git_sha,
|
90
|
-
: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,
|
91
97
|
:namespace, :env, :envs, :region
|
92
98
|
end
|
93
99
|
|
data/lib/aerosol/auto_scaling.rb
CHANGED
@@ -5,8 +5,9 @@ class Aerosol::AutoScaling
|
|
5
5
|
logger_prefix '[aerosol auto_scaling]'
|
6
6
|
aws_attribute :auto_scaling_group_name, :availability_zones, :min_size, :max_size, :default_cooldown,
|
7
7
|
:desired_capacity, :health_check_grace_period, :health_check_type, :load_balancer_names,
|
8
|
-
:placement_group, :tags, :created_time, :vpc_zone_identifier
|
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! :
|
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
|
-
|
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
|
-
}
|
55
|
-
|
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!
|
@@ -138,6 +148,7 @@ class Aerosol::AutoScaling
|
|
138
148
|
"placement_group" => "#{placement_group}", \
|
139
149
|
"tags" => #{tags.to_s}, \
|
140
150
|
"created_time" => "#{created_time}" \
|
151
|
+
"target_group_arns" => "#{target_group_arns}" \
|
141
152
|
}}
|
142
153
|
end
|
143
154
|
|
@@ -146,6 +157,22 @@ private
|
|
146
157
|
Aerosol::AWS.auto_scaling
|
147
158
|
end
|
148
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
|
+
|
149
176
|
def create_options
|
150
177
|
{
|
151
178
|
default_cooldown: default_cooldown,
|
@@ -155,7 +182,8 @@ private
|
|
155
182
|
load_balancer_names: load_balancer_names,
|
156
183
|
placement_group: placement_group,
|
157
184
|
tags: tags_to_array,
|
158
|
-
vpc_zone_identifier: vpc_zone_identifier
|
185
|
+
vpc_zone_identifier: vpc_zone_identifier,
|
186
|
+
target_group_arns: target_group_arns
|
159
187
|
}.reject { |k, v| v.nil? }
|
160
188
|
end
|
161
189
|
|
data/lib/aerosol/cli.rb
CHANGED
@@ -14,6 +14,20 @@ class Aerosol::AbstractCommand < Clamp::Command
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
class Aerosol::DeployCommand < Aerosol::AbstractCommand
|
18
|
+
parameter 'DEPLOY', 'the deploy to run (can also be an environment name) for', :attribute_name => :deploy_name
|
19
|
+
|
20
|
+
def execute
|
21
|
+
super
|
22
|
+
|
23
|
+
if Aerosol.deploy(deploy_name.to_sym)
|
24
|
+
Rake::Task["aerosol:#{deploy_name}:all"].invoke
|
25
|
+
elsif Aerosol.env(deploy_name.to_sym)
|
26
|
+
Rake::Task["aerosol:env:#{deploy_name}"].invoke
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
17
31
|
class Aerosol::SshCommand < Aerosol::AbstractCommand
|
18
32
|
option ['-r', '--run'], :flag, 'run first ssh command', :attribute_name => :run_first
|
19
33
|
parameter 'DEPLOY', 'the deploy to list commands for', :attribute_name => :deploy_name
|
@@ -37,5 +51,6 @@ end
|
|
37
51
|
|
38
52
|
class Aerosol::Cli < Aerosol::AbstractCommand
|
39
53
|
subcommand ['ssh', 's'], 'Print ssh commands for latest running instances', Aerosol::SshCommand
|
54
|
+
subcommand ['deploy', 'd'], 'Run a deploy', Aerosol::DeployCommand
|
40
55
|
end
|
41
56
|
|
@@ -5,7 +5,7 @@ class Aerosol::LaunchConfiguration
|
|
5
5
|
logger_prefix '[aerosol launch_configuration]'
|
6
6
|
aws_attribute :launch_configuration_name, :image_id, :instance_type, :security_groups, :user_data,
|
7
7
|
:iam_instance_profile, :kernel_id, :key_name, :spot_price, :created_time,
|
8
|
-
:associate_public_ip_address, :block_device_mappings
|
8
|
+
:associate_public_ip_address, :block_device_mappings, :ebs_optimized
|
9
9
|
dsl_attribute :meta_data
|
10
10
|
|
11
11
|
primary_key :launch_configuration_name
|
@@ -89,7 +89,8 @@ class Aerosol::LaunchConfiguration
|
|
89
89
|
"key_name" => "#{key_name}", \
|
90
90
|
"spot_price" => "#{spot_price}", \
|
91
91
|
"created_time" => "#{created_time}", \
|
92
|
-
"block_device_mappings" => #{block_device_mappings}" \
|
92
|
+
"block_device_mappings" => #{block_device_mappings}", \
|
93
|
+
"ebs_optimized" => #{ebs_optimized} \
|
93
94
|
}}
|
94
95
|
end
|
95
96
|
|
@@ -109,7 +110,8 @@ private
|
|
109
110
|
spot_price: spot_price,
|
110
111
|
user_data: corrected_user_data,
|
111
112
|
associate_public_ip_address: associate_public_ip_address,
|
112
|
-
block_device_mappings: block_device_mappings
|
113
|
+
block_device_mappings: block_device_mappings,
|
114
|
+
ebs_optimized: ebs_optimized
|
113
115
|
}.reject { |k, v| v.nil? }
|
114
116
|
end
|
115
117
|
|
@@ -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
|
data/lib/aerosol/rake_task.rb
CHANGED
data/lib/aerosol/version.rb
CHANGED
@@ -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.
|
4
|
+
version: 1.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Swipely, Inc.
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -53,19 +53,61 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name: aws-sdk
|
56
|
+
name: aws-sdk-core
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '3'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '3'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: aws-sdk-s3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: aws-sdk-ec2
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: aws-sdk-autoscaling
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1'
|
69
111
|
- !ruby/object:Gem::Dependency
|
70
112
|
name: minigit
|
71
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -154,16 +196,16 @@ dependencies:
|
|
154
196
|
name: rake
|
155
197
|
requirement: !ruby/object:Gem::Requirement
|
156
198
|
requirements:
|
157
|
-
- - "
|
199
|
+
- - "~>"
|
158
200
|
- !ruby/object:Gem::Version
|
159
|
-
version: '0'
|
201
|
+
version: '10.0'
|
160
202
|
type: :development
|
161
203
|
prerelease: false
|
162
204
|
version_requirements: !ruby/object:Gem::Requirement
|
163
205
|
requirements:
|
164
|
-
- - "
|
206
|
+
- - "~>"
|
165
207
|
- !ruby/object:Gem::Version
|
166
|
-
version: '0'
|
208
|
+
version: '10.0'
|
167
209
|
- !ruby/object:Gem::Dependency
|
168
210
|
name: rspec
|
169
211
|
requirement: !ruby/object:Gem::Requirement
|
@@ -238,6 +280,7 @@ files:
|
|
238
280
|
- lib/aerosol/env.rb
|
239
281
|
- lib/aerosol/instance.rb
|
240
282
|
- lib/aerosol/launch_configuration.rb
|
283
|
+
- lib/aerosol/launch_template.rb
|
241
284
|
- lib/aerosol/rake_task.rb
|
242
285
|
- lib/aerosol/runner.rb
|
243
286
|
- lib/aerosol/util.rb
|
@@ -250,6 +293,7 @@ files:
|
|
250
293
|
- spec/aerosol/env_spec.rb
|
251
294
|
- spec/aerosol/instance_spec.rb
|
252
295
|
- spec/aerosol/launch_configuration_spec.rb
|
296
|
+
- spec/aerosol/launch_template_spec.rb
|
253
297
|
- spec/aerosol/rake_task_spec.rb
|
254
298
|
- spec/aerosol/runner_spec.rb
|
255
299
|
- spec/aerosol_spec.rb
|
@@ -259,7 +303,7 @@ homepage: https://github.com/swipely/aerosol
|
|
259
303
|
licenses:
|
260
304
|
- MIT
|
261
305
|
metadata: {}
|
262
|
-
post_install_message:
|
306
|
+
post_install_message:
|
263
307
|
rdoc_options: []
|
264
308
|
require_paths:
|
265
309
|
- lib
|
@@ -274,9 +318,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
274
318
|
- !ruby/object:Gem::Version
|
275
319
|
version: '0'
|
276
320
|
requirements: []
|
277
|
-
|
278
|
-
|
279
|
-
signing_key:
|
321
|
+
rubygems_version: 3.0.3
|
322
|
+
signing_key:
|
280
323
|
specification_version: 4
|
281
324
|
summary: Instance-based deploys made easy
|
282
325
|
test_files:
|
@@ -288,9 +331,9 @@ test_files:
|
|
288
331
|
- spec/aerosol/env_spec.rb
|
289
332
|
- spec/aerosol/instance_spec.rb
|
290
333
|
- spec/aerosol/launch_configuration_spec.rb
|
334
|
+
- spec/aerosol/launch_template_spec.rb
|
291
335
|
- spec/aerosol/rake_task_spec.rb
|
292
336
|
- spec/aerosol/runner_spec.rb
|
293
337
|
- spec/aerosol_spec.rb
|
294
338
|
- spec/spec_helper.rb
|
295
339
|
- spec/support/vcr.rb
|
296
|
-
has_rdoc:
|