aerosol 1.8.0 → 1.10.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/.github/workflows/unit_test.yml +31 -0
- data/.gitignore +2 -0
- data/README.md +1 -2
- data/aerosol.gemspec +3 -3
- data/lib/aerosol/auto_scaling.rb +43 -8
- data/lib/aerosol/aws_model.rb +6 -4
- data/lib/aerosol/instance.rb +5 -0
- data/lib/aerosol/launch_template.rb +127 -0
- data/lib/aerosol/runner.rb +7 -4
- data/lib/aerosol/version.rb +1 -1
- data/lib/aerosol.rb +6 -3
- data/spec/aerosol/auto_scaling_spec.rb +5 -3
- data/spec/aerosol/cli_spec.rb +1 -1
- data/spec/aerosol/deploy_spec.rb +13 -6
- data/spec/aerosol/launch_configuration_spec.rb +5 -3
- data/spec/aerosol/launch_template_spec.rb +404 -0
- data/spec/aerosol/runner_spec.rb +52 -1
- metadata +19 -14
- data/.travis.yml +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8743c2772be4ced4908e79d58b495dc040f9a00a
|
4
|
+
data.tar.gz: 381431aa30ee0f28ed00baf8bcc17da47de3f824
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb227893206994a0a1df737c0c08a9f77353df2773c2a7e2b18e3eb04175ea95e32d567729a2d02fecf60b78eb07652d3faff6528a378f22801db3d796a8a800
|
7
|
+
data.tar.gz: 444a844c3f2038b8fe2ad382b88c227802937c02bf92f53dcaa72b01023d9b5ff67aa6a177510dca94613b99a33c654d9dbe403c69683c79f97daa4f468b51c7
|
@@ -0,0 +1,31 @@
|
|
1
|
+
name: Unit Tests
|
2
|
+
on: [push, pull_request]
|
3
|
+
jobs:
|
4
|
+
docker-rspec:
|
5
|
+
runs-on:
|
6
|
+
- ubuntu-18.04
|
7
|
+
strategy:
|
8
|
+
matrix:
|
9
|
+
ruby:
|
10
|
+
- 2.7
|
11
|
+
- 2.2
|
12
|
+
- 2.1
|
13
|
+
fail-fast: true
|
14
|
+
steps:
|
15
|
+
- uses: actions/checkout@v2
|
16
|
+
with:
|
17
|
+
fetch-depth: 0
|
18
|
+
- uses: ruby/setup-ruby@v1
|
19
|
+
with:
|
20
|
+
ruby-version: ${{ matrix.ruby }}
|
21
|
+
- name: install bundler
|
22
|
+
run: |
|
23
|
+
gem install bundler -v '~> 1.17.3'
|
24
|
+
bundle update
|
25
|
+
- name: install rpm
|
26
|
+
run: |
|
27
|
+
set -x
|
28
|
+
sudo apt-get update -y
|
29
|
+
sudo apt-get install -y rpm
|
30
|
+
- name: spec tests
|
31
|
+
run: CI=true bundle exec rake
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
[](http://badge.fury.io/rb/aerosol)
|
2
|
-
[](https://travis-ci.org/swipely/aerosol)
|
3
2
|
|
4
|
-

|
5
4
|
=========================================================================
|
6
5
|
|
7
6
|
Aerosol orchestrates instance-based-deploys. Start new EC2 instances running your app every release, using auto scaling groups to orchestrate the startup of the new version and the graceful shutdown of the old version.
|
data/aerosol.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
|
|
6
6
|
gem.email = %w{tomhulihan@swipely.com bright@swipely.com toddlunter@swipely.com}
|
7
7
|
gem.description = %q{Instance-based deploys made easy}
|
8
8
|
gem.summary = %q{Instance-based deploys made easy}
|
9
|
-
gem.homepage = "https://github.com/
|
9
|
+
gem.homepage = "https://github.com/upserve/aerosol"
|
10
10
|
gem.license = 'MIT'
|
11
11
|
|
12
12
|
gem.files = `git ls-files`.split($\)
|
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.require_paths = %w{lib}
|
17
17
|
gem.version = Aerosol::VERSION
|
18
18
|
gem.add_dependency 'activerecord', '>= 3.2.0'
|
19
|
-
gem.add_dependency 'clamp', '~>
|
19
|
+
gem.add_dependency 'clamp', '~> 1'
|
20
20
|
gem.add_dependency 'excon'
|
21
21
|
gem.add_dependency 'aws-sdk-core', '~> 3'
|
22
22
|
gem.add_dependency 'aws-sdk-s3', '~> 1'
|
@@ -29,7 +29,7 @@ Gem::Specification.new do |gem|
|
|
29
29
|
gem.add_development_dependency 'cane'
|
30
30
|
gem.add_development_dependency 'pry'
|
31
31
|
gem.add_development_dependency 'rake', '~> 10.0'
|
32
|
-
gem.add_development_dependency 'rspec', '
|
32
|
+
gem.add_development_dependency 'rspec', '~> 3'
|
33
33
|
gem.add_development_dependency 'webmock'
|
34
34
|
gem.add_development_dependency 'vcr'
|
35
35
|
end
|
data/lib/aerosol/auto_scaling.rb
CHANGED
@@ -7,6 +7,12 @@ 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(
|
11
|
+
:launch_template,
|
12
|
+
Aerosol::LaunchTemplate,
|
13
|
+
proc { |argument| argument.fetch(:launch_template, {})[:launch_template_name] }
|
14
|
+
)
|
15
|
+
|
10
16
|
primary_key :auto_scaling_group_name
|
11
17
|
|
12
18
|
def initialize(options={}, &block)
|
@@ -38,21 +44,30 @@ class Aerosol::AutoScaling
|
|
38
44
|
end
|
39
45
|
|
40
46
|
def create!
|
41
|
-
ensure_present! :
|
47
|
+
ensure_present! :max_size, :min_size
|
42
48
|
raise 'availability_zones or vpc_zone_identifier must be set' if [availability_zones, vpc_zone_identifier].none?
|
49
|
+
raise 'launch_configuration or launch_template must be set' unless launch_details
|
43
50
|
|
44
51
|
info "creating auto scaling group"
|
45
|
-
|
52
|
+
launch_details = create_launch_details
|
53
|
+
|
46
54
|
info self.inspect
|
47
55
|
|
48
56
|
conn.create_auto_scaling_group({
|
49
57
|
auto_scaling_group_name: auto_scaling_group_name,
|
50
58
|
availability_zones: [*availability_zones],
|
51
|
-
launch_configuration_name: launch_configuration.launch_configuration_name,
|
52
59
|
max_size: max_size,
|
53
60
|
min_size: min_size
|
54
|
-
}
|
55
|
-
|
61
|
+
}
|
62
|
+
.merge(create_options)
|
63
|
+
.merge(launch_details)
|
64
|
+
)
|
65
|
+
|
66
|
+
conn.wait_until(:group_in_service, auto_scaling_group_names: [auto_scaling_group_name]) do |waiter|
|
67
|
+
waiter.before_wait do |attempt_count, _response|
|
68
|
+
info "Wait count #{attempt_count} of #{waiter.max_attempts} for #{auto_scaling_group_name} to be in service"
|
69
|
+
end
|
70
|
+
end
|
56
71
|
end
|
57
72
|
|
58
73
|
def destroy!
|
@@ -60,9 +75,9 @@ class Aerosol::AutoScaling
|
|
60
75
|
conn.delete_auto_scaling_group(auto_scaling_group_name: auto_scaling_group_name, force_delete: true)
|
61
76
|
begin
|
62
77
|
(0..2).each { break if deleting?; sleep 1 }
|
63
|
-
|
78
|
+
launch_details.destroy
|
64
79
|
rescue => ex
|
65
|
-
info "Launch
|
80
|
+
info "Launch Details: #{launch_details} for #{auto_scaling_group_name} were not deleted."
|
66
81
|
info ex.message
|
67
82
|
end
|
68
83
|
end
|
@@ -78,7 +93,11 @@ class Aerosol::AutoScaling
|
|
78
93
|
def all_instances
|
79
94
|
conn.describe_auto_scaling_groups(auto_scaling_group_names: [*auto_scaling_group_name])
|
80
95
|
.auto_scaling_groups.first
|
81
|
-
.instances.map { |instance| Aerosol::Instance.from_hash(instance) }
|
96
|
+
.instances.map { |instance| Aerosol::Instance.from_hash(instance.to_hash) }
|
97
|
+
end
|
98
|
+
|
99
|
+
def launch_details
|
100
|
+
launch_configuration || launch_template
|
82
101
|
end
|
83
102
|
|
84
103
|
def tag(val)
|
@@ -147,6 +166,22 @@ private
|
|
147
166
|
Aerosol::AWS.auto_scaling
|
148
167
|
end
|
149
168
|
|
169
|
+
def create_launch_details
|
170
|
+
if launch_configuration
|
171
|
+
launch_configuration.create
|
172
|
+
{ launch_configuration_name: launch_configuration.launch_configuration_name }
|
173
|
+
elsif launch_template
|
174
|
+
launch_template.create
|
175
|
+
{
|
176
|
+
launch_template:
|
177
|
+
{
|
178
|
+
launch_template_name: launch_template.launch_template_name,
|
179
|
+
version: '$Latest'
|
180
|
+
}
|
181
|
+
}
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
150
185
|
def create_options
|
151
186
|
{
|
152
187
|
default_cooldown: default_cooldown,
|
data/lib/aerosol/aws_model.rb
CHANGED
@@ -47,13 +47,15 @@ module Aerosol::AWSModel
|
|
47
47
|
aws_attributes.merge(attrs)
|
48
48
|
end
|
49
49
|
|
50
|
-
def aws_class_attribute(name, klass)
|
50
|
+
def aws_class_attribute(name, klass, primary_key_proc = nil)
|
51
51
|
unless klass.ancestors.include?(Aerosol::AWSModel) || (klass == self)
|
52
52
|
raise '.aws_class_attribute requires a Aerosol::AWSModel that is not the current class.'
|
53
53
|
end
|
54
54
|
|
55
|
+
primary_key_proc ||= proc { |hash| hash[klass.primary_key] }
|
56
|
+
|
55
57
|
dsl_class_attribute(name, klass)
|
56
|
-
aws_class_attributes.merge!({ name => klass })
|
58
|
+
aws_class_attributes.merge!({ name => [klass, primary_key_proc] })
|
57
59
|
end
|
58
60
|
|
59
61
|
def exists?(key)
|
@@ -67,9 +69,9 @@ module Aerosol::AWSModel
|
|
67
69
|
|
68
70
|
def from_hash(hash)
|
69
71
|
raise 'To use .from_hash, you must specify a primary_key' if primary_key.nil?
|
70
|
-
refs = Hash[aws_class_attributes.map do |name, klass|
|
72
|
+
refs = Hash[aws_class_attributes.map do |name, (klass, primary_key_proc)|
|
71
73
|
value = klass.instances.values.find do |inst|
|
72
|
-
inst.send(klass.primary_key).to_s == hash
|
74
|
+
inst.send(klass.primary_key).to_s == primary_key_proc.call(hash).to_s unless inst.send(klass.primary_key).nil?
|
73
75
|
end
|
74
76
|
[name, value]
|
75
77
|
end].reject { |k, v| v.nil? }
|
data/lib/aerosol/instance.rb
CHANGED
@@ -5,6 +5,11 @@ class Aerosol::Instance
|
|
5
5
|
|
6
6
|
aws_attribute :availability_zone, :health_status, :instance_id, :lifecycle_state
|
7
7
|
aws_class_attribute :launch_configuration, Aerosol::LaunchConfiguration
|
8
|
+
aws_class_attribute(
|
9
|
+
:launch_template,
|
10
|
+
Aerosol::LaunchTemplate,
|
11
|
+
proc { |argument| argument.fetch(:launch_template, {})[:launch_template_name] }
|
12
|
+
)
|
8
13
|
primary_key :instance_id
|
9
14
|
|
10
15
|
def live?
|
@@ -0,0 +1,127 @@
|
|
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, :launch_template_id, :latest_version_number,
|
7
|
+
:image_id, :instance_type, :security_groups, :user_data,
|
8
|
+
:iam_instance_profile, :kernel_id, :key_name, :spot_price, :created_time,
|
9
|
+
:network_interfaces, :block_device_mappings, :ebs_optimized
|
10
|
+
dsl_attribute :meta_data
|
11
|
+
|
12
|
+
primary_key :launch_template_name
|
13
|
+
default_value(:security_groups) { [] }
|
14
|
+
default_value(:meta_data) { {} }
|
15
|
+
|
16
|
+
def launch_template_name(arg = nil)
|
17
|
+
if arg
|
18
|
+
raise "You cannot set the launch_template_name directly" unless from_aws
|
19
|
+
@launch_template_name = arg
|
20
|
+
else
|
21
|
+
@launch_template_name || default_identifier
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def security_group(group)
|
26
|
+
security_groups << group
|
27
|
+
end
|
28
|
+
|
29
|
+
def create!
|
30
|
+
ensure_present! :image_id, :instance_type
|
31
|
+
|
32
|
+
info "creating launch template"
|
33
|
+
conn.create_launch_template(
|
34
|
+
launch_template_name: launch_template_name,
|
35
|
+
launch_template_data: {
|
36
|
+
image_id: image_id,
|
37
|
+
instance_type: instance_type,
|
38
|
+
monitoring: {
|
39
|
+
enabled: true
|
40
|
+
},
|
41
|
+
}.merge(create_options)
|
42
|
+
)
|
43
|
+
|
44
|
+
debug self.inspect
|
45
|
+
end
|
46
|
+
|
47
|
+
def destroy!
|
48
|
+
info self.to_s
|
49
|
+
raise StandardError.new('No launch_template_name found') unless launch_template_name
|
50
|
+
conn.delete_launch_template(launch_template_name: launch_template_name)
|
51
|
+
end
|
52
|
+
|
53
|
+
def all_instances
|
54
|
+
Aerosol::Instance.all.select { |instance|
|
55
|
+
!instance.launch_template.nil? &&
|
56
|
+
(instance.launch_template.launch_template_name == launch_template_name)
|
57
|
+
}.each(&:description)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.request_all_for_token(next_token)
|
61
|
+
options = next_token.nil? ? {} : { next_token: next_token }
|
62
|
+
Aerosol::AWS.compute.describe_launch_templates(options)
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.request_all
|
66
|
+
next_token = nil
|
67
|
+
lts = []
|
68
|
+
|
69
|
+
begin
|
70
|
+
new_lts = request_all_for_token(next_token)
|
71
|
+
lts.concat(new_lts.launch_templates)
|
72
|
+
next_token = new_lts.next_token
|
73
|
+
end until next_token.nil?
|
74
|
+
lts
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_s
|
78
|
+
%{Aerosol::LaunchTemplate { \
|
79
|
+
"launch_template_name" => "#{launch_template_name}", \
|
80
|
+
"launch_template_id" => "#{launch_template_id}", \
|
81
|
+
"latest_version_number" => "#{latest_version_number}", \
|
82
|
+
"image_id" => "#{image_id}", \
|
83
|
+
"instance_type" => "#{instance_type}", \
|
84
|
+
"security_group_ids" => #{security_groups.to_s}, \
|
85
|
+
"user_data" => "#{user_data}", \
|
86
|
+
"iam_instance_profile" => "#{iam_instance_profile}", \
|
87
|
+
"kernel_id" => "#{kernel_id}", \
|
88
|
+
"key_name" => "#{key_name}", \
|
89
|
+
"spot_price" => "#{spot_price}", \
|
90
|
+
"created_time" => "#{created_time}", \
|
91
|
+
"block_device_mappings" => #{block_device_mappings}", \
|
92
|
+
"ebs_optimized" => #{ebs_optimized} \
|
93
|
+
}}
|
94
|
+
end
|
95
|
+
|
96
|
+
def corrected_user_data
|
97
|
+
realized_user_data = user_data.is_a?(Proc) ? user_data.call : user_data
|
98
|
+
|
99
|
+
Base64.encode64(Aerosol::Util.strip_heredoc(realized_user_data || ''))
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
def create_options
|
104
|
+
instance_market_options = {
|
105
|
+
market_type: 'spot',
|
106
|
+
spot_options: {
|
107
|
+
max_price: spot_price
|
108
|
+
}
|
109
|
+
} if spot_price
|
110
|
+
|
111
|
+
{
|
112
|
+
iam_instance_profile: { name: iam_instance_profile },
|
113
|
+
kernel_id: kernel_id,
|
114
|
+
key_name: key_name,
|
115
|
+
security_group_ids: security_groups,
|
116
|
+
instance_market_options: instance_market_options,
|
117
|
+
user_data: corrected_user_data,
|
118
|
+
network_interfaces: network_interfaces,
|
119
|
+
block_device_mappings: block_device_mappings,
|
120
|
+
ebs_optimized: ebs_optimized,
|
121
|
+
}.reject { |k, v| v.nil? }
|
122
|
+
end
|
123
|
+
|
124
|
+
def conn
|
125
|
+
Aerosol::AWS.compute
|
126
|
+
end
|
127
|
+
end
|
data/lib/aerosol/runner.rb
CHANGED
@@ -229,7 +229,7 @@ class Aerosol::Runner
|
|
229
229
|
|
230
230
|
def old_instances
|
231
231
|
require_deploy!
|
232
|
-
old_auto_scaling_groups.map(&:
|
232
|
+
old_auto_scaling_groups.map(&:launch_details).compact.map(&:all_instances).flatten.compact
|
233
233
|
end
|
234
234
|
|
235
235
|
def old_auto_scaling_groups
|
@@ -243,6 +243,7 @@ class Aerosol::Runner
|
|
243
243
|
def select_auto_scaling_groups(&block)
|
244
244
|
require_deploy!
|
245
245
|
Aerosol::LaunchConfiguration.all # load all of the launch configurations first
|
246
|
+
Aerosol::LaunchTemplate.all
|
246
247
|
Aerosol::AutoScaling.all.select { |asg|
|
247
248
|
(asg.tags['Deploy'].to_s == auto_scaling.tags['Deploy']) &&
|
248
249
|
(block.nil? ? true : block.call(asg))
|
@@ -251,11 +252,13 @@ class Aerosol::Runner
|
|
251
252
|
|
252
253
|
def new_instances
|
253
254
|
require_deploy!
|
254
|
-
|
255
|
+
|
256
|
+
while launch_details.all_instances.length < auto_scaling.min_size
|
255
257
|
info "Waiting for instances to come up"
|
256
258
|
sleep 10
|
257
259
|
end
|
258
|
-
|
260
|
+
|
261
|
+
launch_details.all_instances
|
259
262
|
end
|
260
263
|
|
261
264
|
def with_deploy(name)
|
@@ -280,7 +283,7 @@ class Aerosol::Runner
|
|
280
283
|
:live_check, :db_config_path, :instance_live_grace_period,
|
281
284
|
:app_port, :continue_if_stop_app_fails, :stop_app_retries,
|
282
285
|
:is_alive?, :log_files, :tail_logs, :to => :deploy
|
283
|
-
delegate :
|
286
|
+
delegate :launch_details, :to => :auto_scaling
|
284
287
|
|
285
288
|
private
|
286
289
|
|
data/lib/aerosol/version.rb
CHANGED
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
|
|
@@ -212,7 +212,7 @@ describe Aerosol::AutoScaling do
|
|
212
212
|
}],
|
213
213
|
next_token: nil
|
214
214
|
})
|
215
|
-
subject.exists?('test').should
|
215
|
+
subject.exists?('test').should be true
|
216
216
|
end
|
217
217
|
end
|
218
218
|
|
@@ -226,7 +226,7 @@ describe Aerosol::AutoScaling do
|
|
226
226
|
end
|
227
227
|
|
228
228
|
it 'returns false' do
|
229
|
-
subject.exists?('does-not-exist').should
|
229
|
+
subject.exists?('does-not-exist').should be false
|
230
230
|
end
|
231
231
|
end
|
232
232
|
end
|
@@ -303,7 +303,9 @@ describe Aerosol::AutoScaling do
|
|
303
303
|
{ auto_scaling_groups: [], next_token: nil }
|
304
304
|
])
|
305
305
|
end
|
306
|
-
|
306
|
+
it 'is empty' do
|
307
|
+
expect(subject.all).to be_empty
|
308
|
+
end
|
307
309
|
end
|
308
310
|
|
309
311
|
context 'when there are auto scaling groups' do
|
data/spec/aerosol/cli_spec.rb
CHANGED
data/spec/aerosol/deploy_spec.rb
CHANGED
@@ -10,13 +10,16 @@ describe Aerosol::Deploy do
|
|
10
10
|
|
11
11
|
describe '#migration' do
|
12
12
|
context 'by default' do
|
13
|
-
|
13
|
+
it 'is true' do
|
14
|
+
expect(subject.migrate?).to be true
|
15
|
+
end
|
14
16
|
end
|
15
17
|
|
16
18
|
context 'when do_not_migrate! has been called' do
|
17
19
|
before { subject.do_not_migrate! }
|
18
|
-
|
19
|
-
|
20
|
+
it 'is false' do
|
21
|
+
expect(subject.migrate?).to be false
|
22
|
+
end
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
@@ -80,7 +83,7 @@ describe Aerosol::Deploy do
|
|
80
83
|
end
|
81
84
|
|
82
85
|
it "returns true" do
|
83
|
-
expect(subject.run_post_deploy).to
|
86
|
+
expect(subject.run_post_deploy).to be true
|
84
87
|
end
|
85
88
|
end
|
86
89
|
|
@@ -98,7 +101,9 @@ describe Aerosol::Deploy do
|
|
98
101
|
|
99
102
|
describe '#local_ssh_ref' do
|
100
103
|
context 'when there is no local_ssh' do
|
101
|
-
|
104
|
+
it 'is ssh' do
|
105
|
+
expect(subject.local_ssh_ref).to eq(ssh)
|
106
|
+
end
|
102
107
|
end
|
103
108
|
|
104
109
|
context 'when there is a local_ssh' do
|
@@ -107,7 +112,9 @@ describe Aerosol::Deploy do
|
|
107
112
|
subject.stub(:local_ssh).and_return(local_ssh)
|
108
113
|
end
|
109
114
|
|
110
|
-
|
115
|
+
it 'is ssh' do
|
116
|
+
expect(subject.local_ssh_ref).to eq(local_ssh)
|
117
|
+
end
|
111
118
|
end
|
112
119
|
end
|
113
120
|
|
@@ -242,7 +242,7 @@ describe Aerosol::LaunchConfiguration do
|
|
242
242
|
}],
|
243
243
|
next_token: nil
|
244
244
|
})
|
245
|
-
subject.exists?(instance.launch_configuration_name).should
|
245
|
+
subject.exists?(instance.launch_configuration_name).should be true
|
246
246
|
end
|
247
247
|
end
|
248
248
|
|
@@ -254,7 +254,7 @@ describe Aerosol::LaunchConfiguration do
|
|
254
254
|
launch_configurations: [],
|
255
255
|
next_token: nil
|
256
256
|
})
|
257
|
-
subject.exists?(instance.launch_configuration_name).should
|
257
|
+
subject.exists?(instance.launch_configuration_name).should be false
|
258
258
|
end
|
259
259
|
end
|
260
260
|
end
|
@@ -310,7 +310,9 @@ describe Aerosol::LaunchConfiguration do
|
|
310
310
|
{ launch_configurations: [], next_token: nil }
|
311
311
|
])
|
312
312
|
end
|
313
|
-
|
313
|
+
it "is empty" do
|
314
|
+
expect(subject.all).to be_empty
|
315
|
+
end
|
314
316
|
end
|
315
317
|
|
316
318
|
context 'when there are launch configurations' do
|
@@ -0,0 +1,404 @@
|
|
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
|
+
it 'is empty' do
|
287
|
+
expect(subject.all).to be_empty
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
context 'when there are launch templates' do
|
292
|
+
let(:insts) {
|
293
|
+
[
|
294
|
+
{ launch_template_name: 'test' },
|
295
|
+
{ launch_template_name: 'test2' }
|
296
|
+
]
|
297
|
+
}
|
298
|
+
|
299
|
+
it 'returns each of them' do
|
300
|
+
Aerosol::AWS.compute.stub_responses(:describe_launch_templates, {
|
301
|
+
launch_templates: insts,
|
302
|
+
next_token: nil
|
303
|
+
})
|
304
|
+
subject.all.map(&:launch_template_name).should == %w[test test2]
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
describe '.from_hash' do
|
310
|
+
context 'when the launch template has not been initialized' do
|
311
|
+
subject { described_class.from_hash(hash) }
|
312
|
+
let(:hash) do
|
313
|
+
{
|
314
|
+
launch_template_name: '~test-launch-config~',
|
315
|
+
image_id: 'ami-123',
|
316
|
+
instance_type: 'm1.large',
|
317
|
+
security_groups: [],
|
318
|
+
user_data: 'echo hi',
|
319
|
+
iam_instance_profile: nil,
|
320
|
+
kernel_id: 'kernel-id',
|
321
|
+
key_name: 'key-name',
|
322
|
+
spot_price: '0.04',
|
323
|
+
}
|
324
|
+
end
|
325
|
+
|
326
|
+
it 'creates a new launch template with the specified values' do
|
327
|
+
subject.launch_template_name.should == '~test-launch-config~'
|
328
|
+
subject.image_id.should == 'ami-123'
|
329
|
+
subject.instance_type.should == 'm1.large'
|
330
|
+
subject.security_groups.should be_empty
|
331
|
+
subject.user_data.should == 'echo hi'
|
332
|
+
subject.iam_instance_profile.should be_nil
|
333
|
+
subject.kernel_id.should == 'kernel-id'
|
334
|
+
subject.spot_price.should == '0.04'
|
335
|
+
subject.from_aws = true
|
336
|
+
end
|
337
|
+
|
338
|
+
it 'generates a name' do
|
339
|
+
subject.name.to_s.should start_with 'LaunchTemplate_'
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
context 'when the launch template has already been initialized' do
|
344
|
+
let(:old_hash) do
|
345
|
+
{
|
346
|
+
launch_template_name: 'this-aws-id-abc-123',
|
347
|
+
image_id: 'ami-456',
|
348
|
+
}
|
349
|
+
end
|
350
|
+
let(:new_hash) { old_hash.merge(instance_type: 'm1.large') }
|
351
|
+
let!(:existing) { described_class.from_hash(old_hash) }
|
352
|
+
let(:new) { described_class.from_hash(new_hash) }
|
353
|
+
|
354
|
+
it 'makes a new instance' do
|
355
|
+
expect { new }.to change { described_class.instances.length }.by(1)
|
356
|
+
new.launch_template_name.should == 'this-aws-id-abc-123'
|
357
|
+
new.image_id.should == 'ami-456'
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
describe '#corrected_user_data' do
|
363
|
+
let(:encoded_user_data_string) { Base64.encode64('test') }
|
364
|
+
|
365
|
+
context 'when the user_data is a String' do
|
366
|
+
subject do
|
367
|
+
described_class.new do
|
368
|
+
name :corrected_user_data
|
369
|
+
user_data 'test'
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
it 'correctly encodes to base64' do
|
374
|
+
expect(subject.corrected_user_data).to eq(encoded_user_data_string)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
context 'when the user_data is a Proc' do
|
379
|
+
subject do
|
380
|
+
described_class.new do
|
381
|
+
name :corrected_user_data_2
|
382
|
+
user_data { 'test' }
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
it 'correctly encodes to base64' do
|
387
|
+
expect(subject.corrected_user_data).to eq(encoded_user_data_string)
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
describe '#meta_data' do
|
393
|
+
subject do
|
394
|
+
described_class.new do
|
395
|
+
name :my_launch_template
|
396
|
+
meta_data('Test' => '1')
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
it 'returns the hash' do
|
401
|
+
expect(subject.meta_data['Test']).to eq('1')
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
data/spec/aerosol/runner_spec.rb
CHANGED
@@ -90,7 +90,7 @@ describe Aerosol::Runner do
|
|
90
90
|
ERB.stub_chain(:new, :result)
|
91
91
|
YAML.stub(:load).and_return(conf)
|
92
92
|
deploy.stub_chain(:migration_ssh, :with_connection).and_yield(session)
|
93
|
-
Process.stub(:waitpid).and_return
|
93
|
+
Process.stub(:waitpid).and_return(1)
|
94
94
|
Process::Status.any_instance.stub(:exitstatus) { 0 }
|
95
95
|
session.stub(:loop).and_yield
|
96
96
|
end
|
@@ -253,6 +253,57 @@ describe Aerosol::Runner do
|
|
253
253
|
end
|
254
254
|
|
255
255
|
describe '#new_instances' do
|
256
|
+
context 'With a launch template' do
|
257
|
+
let!(:lt) do
|
258
|
+
Aerosol::LaunchTemplate.new! do
|
259
|
+
name :lt
|
260
|
+
image_id 'fake-ami-how-scandalous'
|
261
|
+
instance_type 'm1.large'
|
262
|
+
end
|
263
|
+
end
|
264
|
+
let!(:asg_lt) do
|
265
|
+
Aerosol::AutoScaling.new! do
|
266
|
+
name :asg_lt
|
267
|
+
availability_zones 'us-east-1'
|
268
|
+
min_size 0
|
269
|
+
max_size 3
|
270
|
+
launch_template :lt
|
271
|
+
stub(:sleep)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
let!(:instance1) do
|
275
|
+
Aerosol::Instance.from_hash(
|
276
|
+
{
|
277
|
+
instance_id: 'z0',
|
278
|
+
launch_template: { launch_template_name: lt.launch_template_name }
|
279
|
+
}
|
280
|
+
)
|
281
|
+
end
|
282
|
+
let!(:instance2) do
|
283
|
+
double(
|
284
|
+
:launch_template => double(:launch_template_name => 'lc7-8891022'),
|
285
|
+
:launch_configuration => nil
|
286
|
+
)
|
287
|
+
end
|
288
|
+
let!(:instance3) do
|
289
|
+
double(
|
290
|
+
:launch_template => nil,
|
291
|
+
:launch_configuration => double(:launch_configuration_name => 'lc0-8891022')
|
292
|
+
)
|
293
|
+
end
|
294
|
+
|
295
|
+
before do
|
296
|
+
Aerosol::Instance.stub(:all).and_return([instance1, instance2, instance3])
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'returns each instance that is a member of the current launch template' do
|
300
|
+
deploy = Aerosol::Deploy.new!(name: :lt_deploy, auto_scaling: :asg_lt)
|
301
|
+
subject.with_deploy(:lt_deploy) do
|
302
|
+
subject.new_instances.should == [instance1]
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
256
307
|
let!(:lc7) do
|
257
308
|
Aerosol::LaunchConfiguration.new! do
|
258
309
|
name :lc7
|
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.10.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: 2022-01-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '1'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '1'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: excon
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -210,16 +210,16 @@ dependencies:
|
|
210
210
|
name: rspec
|
211
211
|
requirement: !ruby/object:Gem::Requirement
|
212
212
|
requirements:
|
213
|
-
- - "
|
213
|
+
- - "~>"
|
214
214
|
- !ruby/object:Gem::Version
|
215
|
-
version: '3
|
215
|
+
version: '3'
|
216
216
|
type: :development
|
217
217
|
prerelease: false
|
218
218
|
version_requirements: !ruby/object:Gem::Requirement
|
219
219
|
requirements:
|
220
|
-
- - "
|
220
|
+
- - "~>"
|
221
221
|
- !ruby/object:Gem::Version
|
222
|
-
version: '3
|
222
|
+
version: '3'
|
223
223
|
- !ruby/object:Gem::Dependency
|
224
224
|
name: webmock
|
225
225
|
requirement: !ruby/object:Gem::Requirement
|
@@ -259,9 +259,9 @@ extensions: []
|
|
259
259
|
extra_rdoc_files: []
|
260
260
|
files:
|
261
261
|
- ".cane"
|
262
|
+
- ".github/workflows/unit_test.yml"
|
262
263
|
- ".gitignore"
|
263
264
|
- ".rspec"
|
264
|
-
- ".travis.yml"
|
265
265
|
- Gemfile
|
266
266
|
- LICENSE.txt
|
267
267
|
- README.md
|
@@ -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,16 +293,17 @@ 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
|
298
300
|
- spec/spec_helper.rb
|
299
301
|
- spec/support/vcr.rb
|
300
|
-
homepage: https://github.com/
|
302
|
+
homepage: https://github.com/upserve/aerosol
|
301
303
|
licenses:
|
302
304
|
- MIT
|
303
305
|
metadata: {}
|
304
|
-
post_install_message:
|
306
|
+
post_install_message:
|
305
307
|
rdoc_options: []
|
306
308
|
require_paths:
|
307
309
|
- lib
|
@@ -316,8 +318,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
316
318
|
- !ruby/object:Gem::Version
|
317
319
|
version: '0'
|
318
320
|
requirements: []
|
319
|
-
|
320
|
-
|
321
|
+
rubyforge_project:
|
322
|
+
rubygems_version: 2.6.11
|
323
|
+
signing_key:
|
321
324
|
specification_version: 4
|
322
325
|
summary: Instance-based deploys made easy
|
323
326
|
test_files:
|
@@ -329,8 +332,10 @@ test_files:
|
|
329
332
|
- spec/aerosol/env_spec.rb
|
330
333
|
- spec/aerosol/instance_spec.rb
|
331
334
|
- spec/aerosol/launch_configuration_spec.rb
|
335
|
+
- spec/aerosol/launch_template_spec.rb
|
332
336
|
- spec/aerosol/rake_task_spec.rb
|
333
337
|
- spec/aerosol/runner_spec.rb
|
334
338
|
- spec/aerosol_spec.rb
|
335
339
|
- spec/spec_helper.rb
|
336
340
|
- spec/support/vcr.rb
|
341
|
+
has_rdoc:
|