capistrano-autoscale-hannah 1.1.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 +7 -0
- data/.gitignore +23 -0
- data/.rspec +1 -0
- data/.rubocop.yml +39 -0
- data/.travis.yml +13 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +208 -0
- data/LICENSE.txt +22 -0
- data/README.md +84 -0
- data/Rakefile +10 -0
- data/capistrano-autoscale.gemspec +33 -0
- data/lib/capistrano/autoscale/aws/ami.rb +70 -0
- data/lib/capistrano/autoscale/aws/autoscale_group.rb +96 -0
- data/lib/capistrano/autoscale/aws/base.rb +50 -0
- data/lib/capistrano/autoscale/aws/instance.rb +24 -0
- data/lib/capistrano/autoscale/aws/instance_collection.rb +35 -0
- data/lib/capistrano/autoscale/aws/launch_template.rb +57 -0
- data/lib/capistrano/autoscale/aws/snapshot.rb +26 -0
- data/lib/capistrano/autoscale/aws/taggable.rb +19 -0
- data/lib/capistrano/autoscale/dsl.rb +50 -0
- data/lib/capistrano/autoscale/errors/create_image_failed.rb +16 -0
- data/lib/capistrano/autoscale/errors/no_auto_scaling_group.rb +10 -0
- data/lib/capistrano/autoscale/errors/no_launch_template.rb +10 -0
- data/lib/capistrano/autoscale/logger.rb +43 -0
- data/lib/capistrano/autoscale/plugin.rb +20 -0
- data/lib/capistrano/autoscale/version.rb +7 -0
- data/lib/capistrano/autoscale.rb +24 -0
- data/lib/capistrano/tasks/autoscale.rake +129 -0
- data/spec/capistrano/autoscale/aws/ami_spec.rb +119 -0
- data/spec/capistrano/autoscale/aws/autoscale_group_spec.rb +70 -0
- data/spec/capistrano/autoscale/aws/instance_collection_spec.rb +55 -0
- data/spec/capistrano/autoscale/aws/instance_spec.rb +32 -0
- data/spec/capistrano/autoscale/aws/launch_template_spec.rb +90 -0
- data/spec/capistrano/autoscale/aws/taggable_spec.rb +34 -0
- data/spec/capistrano/autoscale_spec.rb +89 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/stubs/CreateImage.200.xml +4 -0
- data/spec/support/stubs/CreateLaunchTemplateVersion.200.xml +16 -0
- data/spec/support/stubs/CreateTags.200.xml +5 -0
- data/spec/support/stubs/DeleteSnapshot.200.xml +4 -0
- data/spec/support/stubs/DeregisterImage.200.xml +4 -0
- data/spec/support/stubs/DescribeAutoScalingGroups.200.xml +60 -0
- data/spec/support/stubs/DescribeImages.200.xml +70 -0
- data/spec/support/stubs/DescribeInstances.200.xml +231 -0
- data/spec/support/stubs/DescribeInstances_Empty.200.xml +17 -0
- data/spec/support/stubs/DescribeInstances_MultipleReservations.200.xml +243 -0
- data/spec/support/stubs/DescribeInstances_MultipleRunning.200.xml +338 -0
- data/spec/support/stubs/DescribeLaunchTemplateVersions.200.xml +106 -0
- data/spec/support/stubs/DescribeSnapshots.200.xml +18 -0
- data/spec/support/stubs/DescribeTags.200.xml +17 -0
- data/spec/support/stubs/UpdateAutoScalingGroup.200.xml +5 -0
- data/spec/support/stubs/security-credentials.200.json +9 -0
- metadata +244 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 37a7f2e1a67b257817b60b0d96b555d4e675b4a7f571e9e40784884b5c755935
|
|
4
|
+
data.tar.gz: 43a96392b008a1f4964dbf4a0f20101d6e889b1e7307750fb1548cc5845f81b5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: b63ac6c1b20a777a589ad981bca9089899117adc0c979ed6a3cff8e84dba2aa0d6382bc00c168e50980da9adfa609bef0780b52ac286619fd373be70c93e782f
|
|
7
|
+
data.tar.gz: 9ae10046c10028cb55916e97bef4d94f876c294c74b8571c680e5949bfcd126cfb603f863476b43fd2822499b1f78ad97c533aa52ec31d901ebea3870e6eee05
|
data/.gitignore
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
bin/
|
|
2
|
+
*.gem
|
|
3
|
+
*.rbc
|
|
4
|
+
.bundle
|
|
5
|
+
.config
|
|
6
|
+
.yardoc
|
|
7
|
+
InstalledFiles
|
|
8
|
+
_yardoc
|
|
9
|
+
coverage
|
|
10
|
+
doc/
|
|
11
|
+
lib/bundler/man
|
|
12
|
+
pkg
|
|
13
|
+
rdoc
|
|
14
|
+
.ruby-version
|
|
15
|
+
.ruby-gemset
|
|
16
|
+
test/tmp
|
|
17
|
+
test/version_tmp
|
|
18
|
+
tmp
|
|
19
|
+
*.bundle
|
|
20
|
+
*.so
|
|
21
|
+
*.o
|
|
22
|
+
*.a
|
|
23
|
+
mkmf.log
|
data/.rspec
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--require spec_helper
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 2.3
|
|
3
|
+
|
|
4
|
+
Layout/HashAlignment:
|
|
5
|
+
Enabled: false
|
|
6
|
+
|
|
7
|
+
Layout/LineLength:
|
|
8
|
+
Enabled: false
|
|
9
|
+
|
|
10
|
+
Metrics/AbcSize:
|
|
11
|
+
Max: 27
|
|
12
|
+
|
|
13
|
+
Metrics/BlockLength:
|
|
14
|
+
Enabled: false
|
|
15
|
+
|
|
16
|
+
Metrics/MethodLength:
|
|
17
|
+
Max: 28
|
|
18
|
+
|
|
19
|
+
Style/BlockDelimiters:
|
|
20
|
+
Exclude:
|
|
21
|
+
- 'spec/**/*.rb'
|
|
22
|
+
|
|
23
|
+
Style/Documentation:
|
|
24
|
+
Enabled: false
|
|
25
|
+
|
|
26
|
+
Style/HashEachMethods:
|
|
27
|
+
Enabled: true
|
|
28
|
+
|
|
29
|
+
Style/HashTransformKeys:
|
|
30
|
+
Enabled: true
|
|
31
|
+
|
|
32
|
+
Style/HashTransformValues:
|
|
33
|
+
Enabled: true
|
|
34
|
+
|
|
35
|
+
Style/StderrPuts:
|
|
36
|
+
Enabled: false
|
|
37
|
+
|
|
38
|
+
Style/SymbolArray:
|
|
39
|
+
EnforcedStyle: brackets
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
capistrano-autoscale (1.0.0)
|
|
5
|
+
aws-sdk-autoscaling (~> 1)
|
|
6
|
+
aws-sdk-ec2 (~> 1)
|
|
7
|
+
capistrano (~> 3.9, > 3.9)
|
|
8
|
+
|
|
9
|
+
GEM
|
|
10
|
+
remote: https://rubygems.org/
|
|
11
|
+
specs:
|
|
12
|
+
actioncable (5.2.4.3)
|
|
13
|
+
actionpack (= 5.2.4.3)
|
|
14
|
+
nio4r (~> 2.0)
|
|
15
|
+
websocket-driver (>= 0.6.1)
|
|
16
|
+
actionmailer (5.2.4.3)
|
|
17
|
+
actionpack (= 5.2.4.3)
|
|
18
|
+
actionview (= 5.2.4.3)
|
|
19
|
+
activejob (= 5.2.4.3)
|
|
20
|
+
mail (~> 2.5, >= 2.5.4)
|
|
21
|
+
rails-dom-testing (~> 2.0)
|
|
22
|
+
actionpack (5.2.4.3)
|
|
23
|
+
actionview (= 5.2.4.3)
|
|
24
|
+
activesupport (= 5.2.4.3)
|
|
25
|
+
rack (~> 2.0, >= 2.0.8)
|
|
26
|
+
rack-test (>= 0.6.3)
|
|
27
|
+
rails-dom-testing (~> 2.0)
|
|
28
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
|
29
|
+
actionview (5.2.4.3)
|
|
30
|
+
activesupport (= 5.2.4.3)
|
|
31
|
+
builder (~> 3.1)
|
|
32
|
+
erubi (~> 1.4)
|
|
33
|
+
rails-dom-testing (~> 2.0)
|
|
34
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
|
35
|
+
activejob (5.2.4.3)
|
|
36
|
+
activesupport (= 5.2.4.3)
|
|
37
|
+
globalid (>= 0.3.6)
|
|
38
|
+
activemodel (5.2.4.3)
|
|
39
|
+
activesupport (= 5.2.4.3)
|
|
40
|
+
activerecord (5.2.4.3)
|
|
41
|
+
activemodel (= 5.2.4.3)
|
|
42
|
+
activesupport (= 5.2.4.3)
|
|
43
|
+
arel (>= 9.0)
|
|
44
|
+
activestorage (5.2.4.3)
|
|
45
|
+
actionpack (= 5.2.4.3)
|
|
46
|
+
activerecord (= 5.2.4.3)
|
|
47
|
+
marcel (~> 0.3.1)
|
|
48
|
+
activesupport (5.2.4.3)
|
|
49
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
50
|
+
i18n (>= 0.7, < 2)
|
|
51
|
+
minitest (~> 5.1)
|
|
52
|
+
tzinfo (~> 1.1)
|
|
53
|
+
addressable (2.7.0)
|
|
54
|
+
public_suffix (>= 2.0.2, < 5.0)
|
|
55
|
+
airbrussh (1.4.0)
|
|
56
|
+
sshkit (>= 1.6.1, != 1.7.0)
|
|
57
|
+
arel (9.0.0)
|
|
58
|
+
ast (2.4.1)
|
|
59
|
+
aws-eventstream (1.1.0)
|
|
60
|
+
aws-partitions (1.338.0)
|
|
61
|
+
aws-sdk-autoscaling (1.43.0)
|
|
62
|
+
aws-sdk-core (~> 3, >= 3.99.0)
|
|
63
|
+
aws-sigv4 (~> 1.1)
|
|
64
|
+
aws-sdk-core (3.103.0)
|
|
65
|
+
aws-eventstream (~> 1, >= 1.0.2)
|
|
66
|
+
aws-partitions (~> 1, >= 1.239.0)
|
|
67
|
+
aws-sigv4 (~> 1.1)
|
|
68
|
+
jmespath (~> 1.0)
|
|
69
|
+
aws-sdk-ec2 (1.174.0)
|
|
70
|
+
aws-sdk-core (~> 3, >= 3.99.0)
|
|
71
|
+
aws-sigv4 (~> 1.1)
|
|
72
|
+
aws-sigv4 (1.2.1)
|
|
73
|
+
aws-eventstream (~> 1, >= 1.0.2)
|
|
74
|
+
builder (3.2.4)
|
|
75
|
+
capistrano (3.14.1)
|
|
76
|
+
airbrussh (>= 1.0.0)
|
|
77
|
+
i18n
|
|
78
|
+
rake (>= 10.0.0)
|
|
79
|
+
sshkit (>= 1.9.0)
|
|
80
|
+
concurrent-ruby (1.1.6)
|
|
81
|
+
crack (0.4.3)
|
|
82
|
+
safe_yaml (~> 1.0.0)
|
|
83
|
+
crass (1.0.6)
|
|
84
|
+
diff-lcs (1.4.4)
|
|
85
|
+
erubi (1.9.0)
|
|
86
|
+
globalid (0.4.2)
|
|
87
|
+
activesupport (>= 4.2.0)
|
|
88
|
+
hashdiff (1.0.1)
|
|
89
|
+
i18n (1.8.3)
|
|
90
|
+
concurrent-ruby (~> 1.0)
|
|
91
|
+
jaro_winkler (1.5.4)
|
|
92
|
+
jmespath (1.4.0)
|
|
93
|
+
loofah (2.6.0)
|
|
94
|
+
crass (~> 1.0.2)
|
|
95
|
+
nokogiri (>= 1.5.9)
|
|
96
|
+
mail (2.7.1)
|
|
97
|
+
mini_mime (>= 0.1.1)
|
|
98
|
+
marcel (0.3.3)
|
|
99
|
+
mimemagic (~> 0.3.2)
|
|
100
|
+
method_source (1.0.0)
|
|
101
|
+
mimemagic (0.3.5)
|
|
102
|
+
mini_mime (1.0.2)
|
|
103
|
+
mini_portile2 (2.4.0)
|
|
104
|
+
minitest (5.14.1)
|
|
105
|
+
net-scp (3.0.0)
|
|
106
|
+
net-ssh (>= 2.6.5, < 7.0.0)
|
|
107
|
+
net-ssh (6.1.0)
|
|
108
|
+
nio4r (2.5.2)
|
|
109
|
+
nokogiri (1.10.9)
|
|
110
|
+
mini_portile2 (~> 2.4.0)
|
|
111
|
+
parallel (1.19.2)
|
|
112
|
+
parser (2.7.1.4)
|
|
113
|
+
ast (~> 2.4.1)
|
|
114
|
+
public_suffix (4.0.5)
|
|
115
|
+
rack (2.2.3)
|
|
116
|
+
rack-test (1.1.0)
|
|
117
|
+
rack (>= 1.0, < 3)
|
|
118
|
+
rails (5.2.4.3)
|
|
119
|
+
actioncable (= 5.2.4.3)
|
|
120
|
+
actionmailer (= 5.2.4.3)
|
|
121
|
+
actionpack (= 5.2.4.3)
|
|
122
|
+
actionview (= 5.2.4.3)
|
|
123
|
+
activejob (= 5.2.4.3)
|
|
124
|
+
activemodel (= 5.2.4.3)
|
|
125
|
+
activerecord (= 5.2.4.3)
|
|
126
|
+
activestorage (= 5.2.4.3)
|
|
127
|
+
activesupport (= 5.2.4.3)
|
|
128
|
+
bundler (>= 1.3.0)
|
|
129
|
+
railties (= 5.2.4.3)
|
|
130
|
+
sprockets-rails (>= 2.0.0)
|
|
131
|
+
rails-dom-testing (2.0.3)
|
|
132
|
+
activesupport (>= 4.2.0)
|
|
133
|
+
nokogiri (>= 1.6)
|
|
134
|
+
rails-html-sanitizer (1.3.0)
|
|
135
|
+
loofah (~> 2.3)
|
|
136
|
+
railties (5.2.4.3)
|
|
137
|
+
actionpack (= 5.2.4.3)
|
|
138
|
+
activesupport (= 5.2.4.3)
|
|
139
|
+
method_source
|
|
140
|
+
rake (>= 0.8.7)
|
|
141
|
+
thor (>= 0.19.0, < 2.0)
|
|
142
|
+
rainbow (3.0.0)
|
|
143
|
+
rake (13.0.1)
|
|
144
|
+
rexml (3.2.4)
|
|
145
|
+
rspec (3.9.0)
|
|
146
|
+
rspec-core (~> 3.9.0)
|
|
147
|
+
rspec-expectations (~> 3.9.0)
|
|
148
|
+
rspec-mocks (~> 3.9.0)
|
|
149
|
+
rspec-core (3.9.2)
|
|
150
|
+
rspec-support (~> 3.9.3)
|
|
151
|
+
rspec-expectations (3.9.2)
|
|
152
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
153
|
+
rspec-support (~> 3.9.0)
|
|
154
|
+
rspec-mocks (3.9.1)
|
|
155
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
156
|
+
rspec-support (~> 3.9.0)
|
|
157
|
+
rspec-support (3.9.3)
|
|
158
|
+
rubocop (0.80.1)
|
|
159
|
+
jaro_winkler (~> 1.5.1)
|
|
160
|
+
parallel (~> 1.10)
|
|
161
|
+
parser (>= 2.7.0.1)
|
|
162
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
163
|
+
rexml
|
|
164
|
+
ruby-progressbar (~> 1.7)
|
|
165
|
+
unicode-display_width (>= 1.4.0, < 1.7)
|
|
166
|
+
ruby-progressbar (1.10.1)
|
|
167
|
+
safe_yaml (1.0.5)
|
|
168
|
+
sprockets (3.7.2)
|
|
169
|
+
concurrent-ruby (~> 1.0)
|
|
170
|
+
rack (> 1, < 3)
|
|
171
|
+
sprockets-rails (3.2.1)
|
|
172
|
+
actionpack (>= 4.0)
|
|
173
|
+
activesupport (>= 4.0)
|
|
174
|
+
sprockets (>= 3.0.0)
|
|
175
|
+
sshkit (1.21.0)
|
|
176
|
+
net-scp (>= 1.1.2)
|
|
177
|
+
net-ssh (>= 2.8.0)
|
|
178
|
+
thor (1.0.1)
|
|
179
|
+
thread_safe (0.3.6)
|
|
180
|
+
tzinfo (1.2.7)
|
|
181
|
+
thread_safe (~> 0.1)
|
|
182
|
+
unicode-display_width (1.6.1)
|
|
183
|
+
webmock (3.8.3)
|
|
184
|
+
addressable (>= 2.3.6)
|
|
185
|
+
crack (>= 0.3.2)
|
|
186
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
|
187
|
+
webmock-rspec-helper (0.0.5)
|
|
188
|
+
rails (>= 3.0.0)
|
|
189
|
+
rspec
|
|
190
|
+
webmock
|
|
191
|
+
websocket-driver (0.7.2)
|
|
192
|
+
websocket-extensions (>= 0.1.0)
|
|
193
|
+
websocket-extensions (0.1.5)
|
|
194
|
+
|
|
195
|
+
PLATFORMS
|
|
196
|
+
ruby
|
|
197
|
+
|
|
198
|
+
DEPENDENCIES
|
|
199
|
+
bundler (~> 1.14)
|
|
200
|
+
capistrano-autoscale!
|
|
201
|
+
rake (~> 13.0)
|
|
202
|
+
rspec (~> 3.0, > 3.0)
|
|
203
|
+
rubocop (~> 0.80.1)
|
|
204
|
+
webmock (~> 3.8)
|
|
205
|
+
webmock-rspec-helper (~> 0.0.5)
|
|
206
|
+
|
|
207
|
+
BUNDLED WITH
|
|
208
|
+
1.17.3
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2014 Logan Serman
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Capistrano Autoscale
|
|
2
|
+
|
|
3
|
+
[](https://travis-ci.org/KentaaNL/capistrano-autoscale)
|
|
4
|
+
|
|
5
|
+
This is a fork of [lserman/capistrano-elbas](https://github.com/lserman/capistrano-elbas), with several improvements.
|
|
6
|
+
|
|
7
|
+
Capistrano-autoscale was written to ease the deployment of Rails applications to AWS Auto Scaling
|
|
8
|
+
Groups. During your Capistrano deployment, capistrano-autoscale will:
|
|
9
|
+
|
|
10
|
+
- Suspend Launch & Terminate processes on the Auto Scaling Group.
|
|
11
|
+
- Deploy your code to each running instance connected to a given Auto Scaling Group.
|
|
12
|
+
- After deployment, create an AMI from one of the running instances.
|
|
13
|
+
- Create a new Launch Template version with the AMI ID based on the current Auto Scaling Group's Launch Template.
|
|
14
|
+
- Delete any outdated Launch Template versions, AMIs and snapshots created by previous deployments.
|
|
15
|
+
- Resume Launch & Terminate processes on the Auto Scaling Group.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
Add to Gemfile, then run `bundle`:
|
|
20
|
+
|
|
21
|
+
`gem 'capistrano-autoscale', require: false, git: 'https://github.com/KentaaNL/capistrano-autoscale.git'`
|
|
22
|
+
|
|
23
|
+
Add to Capfile:
|
|
24
|
+
|
|
25
|
+
`require 'capistrano/autoscale'`
|
|
26
|
+
|
|
27
|
+
## Configuration
|
|
28
|
+
|
|
29
|
+
Setup AWS credentials:
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
set :aws_access_key_id, ENV['AWS_ACCESS_KEY_ID']
|
|
33
|
+
set :aws_secret_access_key, ENV['AWS_SECRET_ACCESS_KEY']
|
|
34
|
+
set :aws_region, ENV['AWS_REGION']
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
To configure the prefix that AMIs will get (defaults to stage name):
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
set :aws_autoscale_ami_prefix, "my-ami"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
To add custom tags to AMIs and snapshots you can specify a hash:
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
set :aws_autoscale_ami_tags, { "Environment" => "Sandbox" }
|
|
47
|
+
set :aws_autoscale_snapshot_tags, { "Environment" => "Sandbox" }
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
By default, the Launch & Terminate processes will be suspended during deployment. To disable this:
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
set :aws_autoscale_suspend_processes, false
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
After deployment, any outdated Launch Template versions, AMIs and snapshots will be deleted. By default, the number of `keep_releases` will be kept. To change this, set:
|
|
57
|
+
|
|
58
|
+
```ruby
|
|
59
|
+
set :aws_autoscale_cleanup_old_versions, true
|
|
60
|
+
set :aws_autoscale_keep_versions, 8
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
Instead of using Capistrano's `server` method, use `autoscale` instead in
|
|
66
|
+
`deploy/<environment>.rb` (replace <environment> with your environment). Provide
|
|
67
|
+
the name of your Auto Scaling group instead of a hostname:
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
autoscale 'my-autoscale-group', user: 'apps', roles: [:app, :web, :db]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
If you have multiple autoscaling groups to deploy to, specify each of them:
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
autoscale 'app-autoscale-group', user: 'apps', roles: [:app, :web]
|
|
77
|
+
autoscale 'worker-autoscale-group', user: 'apps', roles: [:worker]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Run `cap production deploy`.
|
|
81
|
+
|
|
82
|
+
Note: Your Auto Scaling Group must use Launch Templates as opposed to Launch Configurations.
|
|
83
|
+
This allows capistrano-autoscale to simply create a new Launch Template version with the new AMI ID after a deployment.
|
|
84
|
+
Failure to use a Launch Template will result in a `Capistrano::Autoscale::Errors::NoLaunchTemplate` error.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
|
+
require 'capistrano/autoscale/version'
|
|
6
|
+
|
|
7
|
+
Gem::Specification.new do |spec|
|
|
8
|
+
spec.name = 'capistrano-autoscale-hannah'
|
|
9
|
+
spec.version = Capistrano::Autoscale::VERSION
|
|
10
|
+
spec.authors = ['François Fitzpatrick']
|
|
11
|
+
spec.email = ['francois.fitzpatrick@gmail.com']
|
|
12
|
+
spec.summary = 'Capistrano plugin for deploying to AWS Auto Scaling Groups with enhanced features.'
|
|
13
|
+
spec.description = spec.summary
|
|
14
|
+
spec.homepage = 'https://github.com/ID-Soft/capistrano-autoscale'
|
|
15
|
+
spec.license = 'MIT'
|
|
16
|
+
|
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
20
|
+
spec.require_paths = ['lib']
|
|
21
|
+
|
|
22
|
+
spec.required_ruby_version = '>= 2.3.0'
|
|
23
|
+
|
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.14'
|
|
25
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
26
|
+
spec.add_development_dependency 'rspec', '~> 3.0', '> 3.0'
|
|
27
|
+
spec.add_development_dependency 'webmock', '~> 3.8'
|
|
28
|
+
spec.add_development_dependency 'webmock-rspec-helper', '~> 0.0.5'
|
|
29
|
+
|
|
30
|
+
spec.add_dependency 'aws-sdk-autoscaling', '~> 1'
|
|
31
|
+
spec.add_dependency 'aws-sdk-ec2', '~> 1'
|
|
32
|
+
spec.add_dependency 'capistrano', '~> 3.9', '> 3.9'
|
|
33
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Capistrano
|
|
4
|
+
module Autoscale
|
|
5
|
+
module AWS
|
|
6
|
+
class AMI < Base
|
|
7
|
+
include Taggable
|
|
8
|
+
|
|
9
|
+
DEPLOY_GROUP_TAG = 'Autoscale-Deploy-group'
|
|
10
|
+
|
|
11
|
+
attr_reader :aws_counterpart, :id, :snapshots
|
|
12
|
+
|
|
13
|
+
def initialize(id, block_device_mappings = [])
|
|
14
|
+
@id = id
|
|
15
|
+
@aws_counterpart = ::Aws::EC2::Image.new id, client: ec2_client
|
|
16
|
+
|
|
17
|
+
@snapshots = block_device_mappings.map do |mapping|
|
|
18
|
+
Capistrano::Autoscale::AWS::Snapshot.new mapping&.ebs&.snapshot_id
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def deploy_group
|
|
23
|
+
tags[DEPLOY_GROUP_TAG]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def delete
|
|
27
|
+
ec2_client.deregister_image image_id: id
|
|
28
|
+
snapshots.each(&:delete)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.create(instance, prefix: 'autoscale', no_reboot: false)
|
|
32
|
+
name = "#{prefix}-#{Time.now.to_i}"
|
|
33
|
+
|
|
34
|
+
image = instance.aws_counterpart.create_image(
|
|
35
|
+
name: name,
|
|
36
|
+
instance_id: instance.id,
|
|
37
|
+
no_reboot: no_reboot
|
|
38
|
+
)
|
|
39
|
+
image = image.wait_until_exists
|
|
40
|
+
|
|
41
|
+
block_device_mappings = nil
|
|
42
|
+
# Wait until block_device_mappings/snapshots are available.
|
|
43
|
+
loop do
|
|
44
|
+
block_device_mappings = image.block_device_mappings
|
|
45
|
+
snapshot_ids = block_device_mappings.map { |mapping| mapping.ebs&.snapshot_id }.compact
|
|
46
|
+
break if !snapshot_ids.empty? || image.state == 'failed'
|
|
47
|
+
|
|
48
|
+
sleep 1
|
|
49
|
+
image.load
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
raise Capistrano::Autoscale::Errors::CreateImageFailed, image if image.state == 'failed'
|
|
53
|
+
|
|
54
|
+
ami = new image.id, block_device_mappings
|
|
55
|
+
ami.tag 'Name', name
|
|
56
|
+
ami.snapshots.each { |snapshot| snapshot.tag 'Name', name }
|
|
57
|
+
ami
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def create_tags(deploy_group)
|
|
61
|
+
tag(DEPLOY_GROUP_TAG, deploy_group)
|
|
62
|
+
|
|
63
|
+
aws_autoscale_ami_tags.each { |key, value| tag(key, value) }
|
|
64
|
+
|
|
65
|
+
snapshots.each(&:create_tags)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Capistrano
|
|
4
|
+
module Autoscale
|
|
5
|
+
module AWS
|
|
6
|
+
class AutoscaleGroup < Base
|
|
7
|
+
SUSPEND_PROCESSES = %w[Launch Terminate].freeze
|
|
8
|
+
|
|
9
|
+
LIFECYCLE_STATE_IN_SERVICE = 'InService'
|
|
10
|
+
LIFECYCLE_STATE_STANDBY = 'Standby'
|
|
11
|
+
|
|
12
|
+
AMI_PREFIX_TAG = 'Autoscale-Ami-Prefix'
|
|
13
|
+
|
|
14
|
+
attr_reader :name, :aws_counterpart
|
|
15
|
+
|
|
16
|
+
def initialize(name)
|
|
17
|
+
@name = name
|
|
18
|
+
@aws_counterpart = Aws::AutoScaling::AutoScalingGroup.new name: name, client: autoscaling_client
|
|
19
|
+
|
|
20
|
+
raise Capistrano::Autoscale::Errors::NoAutoScalingGroup, name unless @aws_counterpart.exists?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def instances
|
|
24
|
+
instance_ids = aws_counterpart.instances.map(&:instance_id)
|
|
25
|
+
InstanceCollection.new(instance_ids)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def instances_in_service
|
|
29
|
+
instance_ids = aws_counterpart.instances.select { |i| i.lifecycle_state == LIFECYCLE_STATE_IN_SERVICE }.map(&:instance_id)
|
|
30
|
+
InstanceCollection.new(instance_ids)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def launch_template
|
|
34
|
+
lts = aws_launch_template || aws_launch_template_specification
|
|
35
|
+
raise Capistrano::Autoscale::Errors::NoLaunchTemplate unless lts
|
|
36
|
+
|
|
37
|
+
LaunchTemplate.new(
|
|
38
|
+
lts.launch_template_id,
|
|
39
|
+
lts.launch_template_name,
|
|
40
|
+
lts.version,
|
|
41
|
+
false,
|
|
42
|
+
nil
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def suspend
|
|
47
|
+
aws_counterpart.suspend_processes(scaling_processes: SUSPEND_PROCESSES)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def resume
|
|
51
|
+
aws_counterpart.resume_processes(scaling_processes: SUSPEND_PROCESSES)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def suspended?
|
|
55
|
+
aws_counterpart.suspended_processes.map(&:process_name).any? { |name| SUSPEND_PROCESSES.include?(name) }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def tags
|
|
59
|
+
aws_counterpart.tags.map { |tag| [tag.key, tag.value] }.to_h
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def ami_prefix
|
|
63
|
+
tags[AMI_PREFIX_TAG]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def enter_standby(instance)
|
|
67
|
+
instance = aws_counterpart.instances.select { |i| i.id == instance.id }.first
|
|
68
|
+
instance.enter_standby(should_decrement_desired_capacity: true)
|
|
69
|
+
|
|
70
|
+
loop do
|
|
71
|
+
break if instance.lifecycle_state == LIFECYCLE_STATE_STANDBY
|
|
72
|
+
|
|
73
|
+
sleep 1
|
|
74
|
+
instance.load
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def exit_standby(instance)
|
|
79
|
+
instance = aws_counterpart.instances.select { |i| i.id == instance.id }.first
|
|
80
|
+
instance.exit_standby
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def aws_launch_template
|
|
86
|
+
aws_counterpart.launch_template
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def aws_launch_template_specification
|
|
90
|
+
aws_counterpart.mixed_instances_policy&.launch_template
|
|
91
|
+
&.launch_template_specification
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Capistrano
|
|
4
|
+
module Autoscale
|
|
5
|
+
module AWS
|
|
6
|
+
class Base
|
|
7
|
+
include Capistrano::DSL
|
|
8
|
+
|
|
9
|
+
def ec2_client
|
|
10
|
+
@ec2_client ||= ::Aws::EC2::Client.new(aws_options)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def autoscaling_client
|
|
14
|
+
@autoscaling_client ||= ::Aws::AutoScaling::Client.new(aws_options)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def aws_options
|
|
18
|
+
options = {}
|
|
19
|
+
options[:region] = aws_region if aws_region
|
|
20
|
+
options[:credentials] = aws_credentials if aws_credentials.set?
|
|
21
|
+
options
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def aws_credentials
|
|
25
|
+
fetch :aws_credentials, ::Aws::Credentials.new(aws_access_key_id, aws_secret_access_key)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def aws_access_key_id
|
|
29
|
+
fetch :aws_access_key_id
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def aws_secret_access_key
|
|
33
|
+
fetch :aws_secret_access_key
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def aws_region
|
|
37
|
+
fetch :aws_region
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def aws_autoscale_ami_tags
|
|
41
|
+
fetch :aws_autoscale_ami_tags
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def aws_autoscale_snapshot_tags
|
|
45
|
+
fetch :aws_autoscale_snapshot_tags
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|