aerosol 0.5.1

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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.cane +3 -0
  3. data/.gitignore +15 -0
  4. data/.rspec +3 -0
  5. data/.travis.yml +6 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.md +399 -0
  9. data/Rakefile +18 -0
  10. data/aerosol.gemspec +32 -0
  11. data/bin/aerosol +8 -0
  12. data/img/aerosol.pdf +3898 -11
  13. data/img/aerosol.png +0 -0
  14. data/lib/aerosol/auto_scaling.rb +240 -0
  15. data/lib/aerosol/aws.rb +62 -0
  16. data/lib/aerosol/aws_model.rb +93 -0
  17. data/lib/aerosol/cli.rb +41 -0
  18. data/lib/aerosol/connection.rb +39 -0
  19. data/lib/aerosol/deploy.rb +105 -0
  20. data/lib/aerosol/env.rb +6 -0
  21. data/lib/aerosol/instance.rb +55 -0
  22. data/lib/aerosol/launch_configuration.rb +106 -0
  23. data/lib/aerosol/rake_task.rb +141 -0
  24. data/lib/aerosol/runner.rb +329 -0
  25. data/lib/aerosol/util.rb +41 -0
  26. data/lib/aerosol/version.rb +5 -0
  27. data/lib/aerosol.rb +83 -0
  28. data/spec/aerosol/auto_scaling_spec.rb +420 -0
  29. data/spec/aerosol/aws_spec.rb +24 -0
  30. data/spec/aerosol/cli_spec.rb +10 -0
  31. data/spec/aerosol/connection_spec.rb +94 -0
  32. data/spec/aerosol/deploy_spec.rb +192 -0
  33. data/spec/aerosol/env_spec.rb +16 -0
  34. data/spec/aerosol/instance_spec.rb +57 -0
  35. data/spec/aerosol/launch_configuration_spec.rb +328 -0
  36. data/spec/aerosol/rake_task_spec.rb +19 -0
  37. data/spec/aerosol/runner_spec.rb +482 -0
  38. data/spec/aerosol_spec.rb +41 -0
  39. data/spec/fixtures/Procfile +1 -0
  40. data/spec/fixtures/Rakefile +17 -0
  41. data/spec/fixtures/not_a_tar-2.txt +1 -0
  42. data/spec/fixtures/not_a_tar.txt +1 -0
  43. data/spec/fixtures/tar-2.tar +0 -0
  44. data/spec/fixtures/test-1.tar +0 -0
  45. data/spec/fixtures/test-2.tar.gz +0 -0
  46. data/spec/spec_helper.rb +22 -0
  47. data/spec/support/vcr.rb +11 -0
  48. data/spec/vcr/Deployz_Docker/_fetch_import/when_both_import_and_name_are_present_present/and_it_points_to_a_non-S3_url/pulls_the_file.yml +214 -0
  49. metadata +312 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e6cf29a31c88ffb04c424c3bcbbcb0645d74e071
4
+ data.tar.gz: 4e9f58b45fd64a4875e09ec9c3ce0645f82d6ecf
5
+ SHA512:
6
+ metadata.gz: 25cb41164e46803c1abe915dd809c12fdf050b3427d6ded99353b1e7ca3a434eb3a74d60f24f1ef66896b3510ea1905483f66bb8c279d59bfce7588026ecc234
7
+ data.tar.gz: 525852da882273707a57af5161075dd36a9c1f1ad3abaa032ba8dcc80ed4697c20c7e67a9c4e713f497461e187e876cd481d1ff669e0be043d4fe0465eede0bf
data/.cane ADDED
@@ -0,0 +1,3 @@
1
+ --no-doc
2
+ --abc-max 30
3
+ --style-measure 120
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ # bundler
2
+ .bundle
3
+
4
+ # OSX
5
+ .DS_Store
6
+
7
+ # Vim
8
+ *.swp
9
+
10
+ Gemfile.lock
11
+ *.gem
12
+ build/
13
+ dist/
14
+
15
+ docker-export-ubuntu-latest.tar.gz
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --profile
3
+ --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ script: CI=true bundle exec rake
6
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Swipely, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,399 @@
1
+ [![Gem Version](https://badge.fury.io/rb/aerosol.png)](http://badge.fury.io/rb/aerosol)
2
+ [![Build Status](https://travis-ci.org/swipely/aerosol.png)](https://travis-ci.org/swipely/aerosol)
3
+
4
+ ![Aerosol](https://raw.github.com/swipely/aerosol/master/img/aerosol.png)
5
+ =========================================================================
6
+
7
+ 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.
8
+
9
+ Getting Started
10
+ ---------------
11
+
12
+ Add it to your Gemfile:
13
+
14
+ ```ruby
15
+ gem 'aerosol'
16
+ ```
17
+
18
+ And build an aerosol.rb
19
+
20
+ If you're not using Rails, add it to your Rakefile:
21
+
22
+ ```ruby
23
+ require 'aerosol'
24
+ ```
25
+
26
+ Usage
27
+ -----
28
+
29
+ ### Rake Tasks
30
+
31
+ The deploy tasks are within the `aerosol:deploy_name` namespace where deploy_name is based upon the deploy section detailed below.
32
+
33
+ #### Full deploy tasks
34
+
35
+ `all` - Full serial deployment: Run migration, create auto scaling group, wait for instances, stop old application, destroy old auto scaling groups and run the post deploy command
36
+
37
+ `all_asynch` - Same as `all` but runs the migration and creates auto scaling groups in parallel
38
+
39
+ #### The separate deploy rake tasks
40
+
41
+ `run_migration` - Runs the ActiveRecord migration through the SSH connection given
42
+
43
+ `create_auto_scaling_group` - Creates a new auto scaling group for the current git hash
44
+
45
+ `wait_for_new_instances` - Waits for instances of the new autoscaling groups to start up
46
+
47
+ `stop_old_app` - Runs command to shut down the application on the old instances instead of just terminating
48
+
49
+ `destroy_old_auto_scaling_groups` - Terminates instances with the current tag and different git hash
50
+
51
+ `destroy_new_auto_scaling_groups` - Terminates instances with the current tag and same git hash
52
+
53
+ `run_post_deploy` - Runs a post deploy command
54
+
55
+ #### Non-deploy rake tasks
56
+
57
+ `aerosol:ssh:deploy_name` - Prints out ssh command to all instances of the latest deploy
58
+
59
+ ### CLI
60
+
61
+ `aerosol ssh deploy_name` - Same as aerosol:ssh:deploy_name
62
+
63
+ `aerosol ssh -r deploy_name` - Runs the ssh command to the first instance available (still prints out the others)
64
+
65
+ Demo
66
+ ----
67
+
68
+ ```ruby
69
+ namespace :test
70
+
71
+ launch_configuration :launch_config do
72
+ ami 'ami-1715317e' # Ubuntu 13.04 US-East-1 ebs amd64
73
+ instance_type 'm1.small'
74
+ iam_role 'role-app'
75
+ key_name 'app'
76
+
77
+ user_data ERB.new(File.read('startup.sh.erb')).result(binding)
78
+ end
79
+
80
+ auto_scaling :auto_scaling_group do
81
+ availability_zones ['us-east-1a']
82
+ max_size 1
83
+ min_size 1
84
+ launch_configuration :launch_config
85
+ end
86
+
87
+ ssh :ssh do
88
+ user 'ubuntu'
89
+ end
90
+
91
+ ssh :migration do
92
+ user 'ubuntu'
93
+ host 'dbserver.example.com'
94
+ end
95
+
96
+ ssh :local do
97
+ jump :user => 'ubuntu', :host => 'jump.example.com'
98
+ end
99
+
100
+ deploy :deploy do
101
+ ssh :ssh
102
+ migration_ssh :migration
103
+ local_ssh :local
104
+ auto_scaling :auto_scaling_group
105
+ stop_command 'sudo stop app'
106
+ live_check '/version'
107
+ app_port 443
108
+ post_deploy_command 'bundle exec rake postdeploycommand'
109
+ end
110
+ ```
111
+
112
+ The DSL
113
+ -------
114
+
115
+ The DSL is broken down into multiple objects, all of which conform to a specific format. Each object starts with the name of the section,
116
+ followed by a name for the object you're creating, and a block for configuration.
117
+
118
+ ```ruby
119
+ auto_scaling :test_auto_scaling do
120
+ # code here
121
+ end
122
+ ```
123
+
124
+ Each object has an enumeration of valid attributes. The following code sets the `max_size` attribute in a `auto_scaling` group called `test_auto_scaling`:
125
+
126
+ ```ruby
127
+ auto_scaling :test_auto_scaling do
128
+ max_size 1
129
+ end
130
+ ```
131
+
132
+ Finally, each object has zero or more valid references to other DSL objects. The following code sets `auto_scaling` that references a `launch_configuration`:
133
+
134
+ ```ruby
135
+ launch_configuration :my_launch_config do
136
+ max_size 1
137
+ end
138
+
139
+ auto_scaling :my_auto_scaling do
140
+ launch_configuration :my_launch_config
141
+ end
142
+ ```
143
+
144
+ Below is an alternative syntax that accomplishes the same thing:
145
+
146
+ ```ruby
147
+ auto_scaling :my_auto_scaling do
148
+ launch_configuration do
149
+ max_size 1
150
+ end
151
+ end
152
+ ```
153
+
154
+ Network Design
155
+ --------------
156
+
157
+ A simplified version of the AWS network design that Aerosol manages is: auto scaling groups control running instances, and determine how those instances start up.
158
+
159
+ Aerosol defines a way to deploy to an auto scaling group, with the correct launch configuration and properly brings up the instances.
160
+
161
+ Controlling SSH connections
162
+ ---------------------------
163
+
164
+ SSH connections are used when connecting for migrations, checking if the instances are live and running local connections.
165
+
166
+ Options:
167
+
168
+ - user - The user to connect with
169
+ - host - Where to connect to (will be filled in for instance and local connections)
170
+ - jump - A hash of a user and host to connect through. For secure/VPN connections.
171
+
172
+ ### Examples
173
+
174
+ Minimal SSH connection for local connections:
175
+
176
+ ```ruby
177
+ ssh :local_ssh do
178
+ end
179
+ ```
180
+
181
+ Since a machine could start up with your user and not need a jump server, this could be all you need.
182
+
183
+ SSH connection with a jump server:
184
+
185
+ ```ruby
186
+ ssh :jump_ssh do
187
+ jump :user => 'ec2_user', :host => 'jump.example.com'
188
+ end
189
+ ```
190
+
191
+ A lot of network structures use a middle jump server before connecting to the internal network. Supplying either a user, host or both, you can establish a jump server to connect through.
192
+
193
+ SSH connection with a user and host:
194
+
195
+ ```ruby
196
+ ssh :migration_ssh do
197
+ user 'db_user'
198
+ host 'dbserver.example.com'
199
+ end
200
+ ```
201
+
202
+ When using ActiveRecord, you'll need to supply a connection to pass through. Supply your database server credentials like this (you can also use a jump server here).
203
+
204
+ Controlling instance definition
205
+ -------------------------------
206
+
207
+ Launch configurations define the EC2 instance startup. All the features entered via the EC2 wizard are available.
208
+
209
+ Options:
210
+
211
+ - ami - The Amazon Machine Image that designates what operating system and possible tiers to run on.
212
+ - instance_type - The tier to run the instance on (m1.large, etc.)
213
+ - security_groups - A list of security groups the instances are paired with.
214
+ - user_data - The bash script that is run as the instance comes live
215
+ - iam_role - the Identity and Access Management role the instances should startup with
216
+ - kernel_id - The kernel ID configurable for the EC2 instance (best found through the EC2 wizard)
217
+ - key_name - The name of the EC2 key pair for initial connections to the instance
218
+ - spot_price - The max hourly price to be paid for any spot prices
219
+
220
+ ### Examples
221
+
222
+ Launch configurations must specify an AMI and instance type. Everything else can be ignored and the instance will start up:
223
+
224
+ ```ruby
225
+ launch_configuration :minimal_lc do
226
+ ami 'ami-1715317e' # Ubuntu 13.04 US-East-1 ebs amd64
227
+ instance_type 'm1.small'
228
+ end
229
+ ```
230
+
231
+ This instance will startup and do nothing, with almost no way to connect to it though.
232
+
233
+ Adding a script into the user_data section sets how the instance will start up. Either use plain text, read from a file, or use ERB:
234
+
235
+ Text:
236
+
237
+ ```ruby
238
+ launch_configuration :startup_lc do
239
+ ami 'ami-1715317e' # Ubuntu 13.04 US-East-1 ebs amd64
240
+ instance_type 'm1.small'
241
+ user_data "#!/bin/bash\n# Get file here"
242
+ end
243
+ ```
244
+
245
+ File:
246
+
247
+ ```ruby
248
+ launch_configuration :startup_lc do
249
+ ami 'ami-1715317e' # Ubuntu 13.04 US-East-1 ebs amd64
250
+ instance_type 'm1.small'
251
+ user_data File.read('startup.sh')
252
+ end
253
+ ```
254
+
255
+ ERB:
256
+
257
+ ```ruby
258
+ launch_configuration :startup_lc do
259
+ ami 'ami-1715317e' # Ubuntu 13.04 US-East-1 ebs amd64
260
+ instance_type 'm1.small'
261
+
262
+ thing = "google.com" # This is accessible within the ERB file!
263
+
264
+ user_data ERB.new(File.read('startup.sh.erb')).result(binding)
265
+ end
266
+ ```
267
+
268
+ Using an ERB file is likely the most powerful especially since anything defined within the launch configurations context is available, as well as any other gems required before this.
269
+
270
+ Controlling auto scaling groups
271
+ -------------------------------
272
+
273
+ Auto scaling groups define how your network expands as needed and spans multiple availability zones.
274
+
275
+ Options:
276
+
277
+ - availability_zones - A list of availability zones
278
+ - min_size/max_size - The min and max number of instances for the auto scaling group
279
+ - default_cooldown - The number of seconds after a scaling activity completes before any further trigger-related scaling activities can start
280
+ - desired_capacity - The number of instances that should be running in the group
281
+ - health_check_grace_period - The number of seconds AWS waits before it befores a health check
282
+ - health_check_type - The type of health check to perform, `'ELB'` and `'EC2'` are valid options
283
+ - load_balancer_names - A list of the names of desired load balancers
284
+ - placement_group - Physical location of your cluster placement group created in EC2
285
+ - tag - A hash of tags for the instances in the group
286
+ - launch_configuration - A reference to the launch configuration used by this auto scaling group
287
+ - vpc_zone_identifier - A comma-separated list of subnet identifiers of Amazon Virtual Private Clouds
288
+
289
+ Auto scaling groups only require an availability zone, a min and max size, and a launch configuration.
290
+
291
+ ```ruby
292
+ auto_scaling :minimal_asg do
293
+ launch_configuration :minimal_lc
294
+ availability_zones ['us-east-1a']
295
+ min_size 1
296
+ max_size 1
297
+ end
298
+ ```
299
+
300
+ This will start up a single instance using our most basic launch configuration in US East 1A
301
+
302
+ Adding tags can help identify the instances (two are already made for you: Deploy and GitSha)
303
+
304
+ ```ruby
305
+ auto_scaling :tagged_asg do
306
+ launch_configuration :minimal_lc
307
+ availability_zones ['us-east-1a']
308
+ min_size 1
309
+ max_size 1
310
+
311
+ tag 'Name' => 'tagged_asg'
312
+ tag 'NextTag' => 'NewValue'
313
+ # or
314
+ tag 'Name' => 'tagged_asg', 'NextTag' => 'NewValue'
315
+ end
316
+ ```
317
+
318
+ Configuring your deploy
319
+ -----------------------
320
+
321
+ A deploy ties the auto scaling groups and possible SSH connections together for application logic
322
+
323
+ Options:
324
+
325
+ - auto_scaling - Auto scaling group for this deployment
326
+ - ssh - SSH connection from deployment computer to new instance
327
+ - migration_ssh - SSH connection from deployment computer to database connection instance (optional: only needed if deployment computer cannot connect to database directly)
328
+ - do_not_migrate! - Do not try and do a migration (for non-ActiveRecord deploys)
329
+ - local_ssh - SSH connection from local computer to running instances
330
+ - stop_command - This command is run before an auto scaling group is run to stop your application gracefully
331
+ - live_check - 'Local path to query on the instance to verify the application is running'
332
+ - instance_live_grace_period - The number of seconds to wait for an instance to be live (default: 30 minutes - 1800 seconds)
333
+ - db_config_path - relative path of your database config file (default: 'config/database.yml')
334
+ - app_port - which port the application is running on
335
+ - stop_app_retries - The number of times to retry stopping the application (default: 2)
336
+ - continue_if_stop_app_fails - When true, will ignore a failure when stopping the application (default: 'false')
337
+ - post_deploy_command - Command run after the deploy has finished
338
+ - sleep_before_termination - Time to wait after the new instance spawns and before terminating the old instance (allow time for external load balancers to start working)
339
+ - ssl - Boolean that enables/disables ssl when doing the live check (default: 'false').
340
+ - log_files - Paths to files on each instance to tail during deploy (default: '/var/log/syslog')
341
+ - tail_logs - Boolean that will enable/disable tailing log files (default: 'false')
342
+
343
+ A lot of the options for deployment are required, but we've defined some sane defaults.
344
+
345
+ A basic deployment could look like:
346
+
347
+ ```ruby
348
+ deploy :quick_app do
349
+ ssh :jump_ssh
350
+ do_not_migrate!
351
+ auto_scaling :minimal_asg
352
+ stop_command 'sudo stop app'
353
+ live_check '/version'
354
+ app_port 80
355
+ end
356
+ ```
357
+
358
+ This won't perform a migration, will stop the application with 'sudo stop app' after checking the instance is live at 'localhost:80/version' after SSHing to the instance through jump_ssh.
359
+ It will use the default of waiting 30 minutes for a deploy before failing, and fail if the previous application does not stop correctly.
360
+
361
+ If the server you're deploying from is not behind the same restrictions a development machine is, add a local SSH connection. The local connection will be used when generating commands for connecting to the instances.
362
+
363
+ Environments
364
+ ------------
365
+
366
+ An environment is a set of deploys that may be run in parallel.
367
+ This can be useful if you, for example, want to deploy a load balancer at the same time you deploy your backend application.
368
+
369
+ Options:
370
+
371
+ - deploy - Add a deploy to this environment.
372
+
373
+ A basic environment (assuming there is already a deploy named `:quick_app` and another named `:quick_app_worker`):
374
+
375
+ ```ruby
376
+ env :staging do
377
+ deploy :quick_app
378
+ deploy :quick_app_worker
379
+ end
380
+ ```
381
+
382
+ To run these deploys, the following task can be run:
383
+
384
+ ```shell
385
+ $ bundle exec rake aerosol:env:staging
386
+ ```
387
+
388
+ Namespace
389
+ ---------
390
+
391
+ A namespace will enable branches of a main project to be deployed separately without interfering with auto scaling groups, launch configurations or elastic IPs
392
+
393
+ ```ruby
394
+ namespace :test
395
+ ```
396
+
397
+ This will prefix all auto scaling groups and launch configurations with `test-` and also the `Deploy` tag that is on each auto scaling group by default.
398
+
399
+ Copyright (c) 2013 Swipely, Inc. See LICENSE.txt for further details.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ # Copyright Swipely, Inc. All rights reserved.
2
+
3
+ $LOAD_PATH.unshift( File.join( File.dirname(__FILE__), 'lib' ) )
4
+
5
+ require 'rake'
6
+ require 'aerosol'
7
+ require 'rspec/core/rake_task'
8
+ require 'cane/rake_task'
9
+
10
+ task :default => [:spec, :quality]
11
+
12
+ RSpec::Core::RakeTask.new do |t|
13
+ t.pattern = 'spec/**/*_spec.rb'
14
+ end
15
+
16
+ Cane::RakeTask.new(:quality) do |cane|
17
+ cane.canefile = '.cane'
18
+ end
data/aerosol.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/aerosol/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Swipely, Inc."]
6
+ gem.email = %w{tomhulihan@swipely.com bright@swipely.com toddlunter@swipely.com}
7
+ gem.description = %q{Instance-based deploys made easy}
8
+ gem.summary = %q{Instance-based deploys made easy}
9
+ gem.homepage = "https://github.com/swipely/aerosol"
10
+ gem.license = 'MIT'
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.name = "aerosol"
16
+ gem.require_paths = %w{lib}
17
+ gem.version = Aerosol::VERSION
18
+ gem.add_dependency 'activerecord', '>= 3.2.0'
19
+ gem.add_dependency 'clamp', '~> 0.6'
20
+ gem.add_dependency 'excon'
21
+ gem.add_dependency 'fog', '~> 1.21'
22
+ gem.add_dependency 'grit'
23
+ gem.add_dependency 'net-ssh'
24
+ gem.add_dependency 'net-ssh-gateway'
25
+ gem.add_dependency 'dockly-util', '~> 0.0.5'
26
+ gem.add_development_dependency 'cane'
27
+ gem.add_development_dependency 'pry'
28
+ gem.add_development_dependency 'rake'
29
+ gem.add_development_dependency 'rspec', '< 3.0'
30
+ gem.add_development_dependency 'webmock'
31
+ gem.add_development_dependency 'vcr'
32
+ end
data/bin/aerosol ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ $: << File.join(File.dirname(__FILE__), "..", "lib")
5
+ require 'aerosol'
6
+ require 'aerosol/cli'
7
+
8
+ Aerosol::Cli.run