cf_deployer 1.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +29 -0
  3. data/ChangeLog.md +16 -0
  4. data/DETAILS.md +268 -0
  5. data/FAQ.md +61 -0
  6. data/Gemfile +10 -0
  7. data/Gemfile.lock +51 -0
  8. data/LICENSE +22 -0
  9. data/QUICKSTART.md +96 -0
  10. data/README.md +36 -0
  11. data/Rakefile +32 -0
  12. data/bin/cf_deploy +10 -0
  13. data/cf_deployer.gemspec +23 -0
  14. data/lib/cf_deployer/application.rb +74 -0
  15. data/lib/cf_deployer/application_error.rb +4 -0
  16. data/lib/cf_deployer/aws_constants.rb +3 -0
  17. data/lib/cf_deployer/cli.rb +111 -0
  18. data/lib/cf_deployer/component.rb +103 -0
  19. data/lib/cf_deployer/config_loader.rb +189 -0
  20. data/lib/cf_deployer/config_validation.rb +138 -0
  21. data/lib/cf_deployer/defaults.rb +10 -0
  22. data/lib/cf_deployer/deployment_strategy/auto_scaling_group_swap.rb +102 -0
  23. data/lib/cf_deployer/deployment_strategy/base.rb +88 -0
  24. data/lib/cf_deployer/deployment_strategy/blue_green.rb +70 -0
  25. data/lib/cf_deployer/deployment_strategy/cname_swap.rb +108 -0
  26. data/lib/cf_deployer/deployment_strategy/create_or_update.rb +57 -0
  27. data/lib/cf_deployer/driver/auto_scaling_group.rb +86 -0
  28. data/lib/cf_deployer/driver/cloud_formation_driver.rb +85 -0
  29. data/lib/cf_deployer/driver/dry_run.rb +27 -0
  30. data/lib/cf_deployer/driver/elb_driver.rb +17 -0
  31. data/lib/cf_deployer/driver/instance.rb +29 -0
  32. data/lib/cf_deployer/driver/route53_driver.rb +79 -0
  33. data/lib/cf_deployer/driver/verisign_driver.rb +21 -0
  34. data/lib/cf_deployer/hook.rb +32 -0
  35. data/lib/cf_deployer/logger.rb +34 -0
  36. data/lib/cf_deployer/stack.rb +154 -0
  37. data/lib/cf_deployer/status_presenter.rb +195 -0
  38. data/lib/cf_deployer/version.rb +3 -0
  39. data/lib/cf_deployer.rb +97 -0
  40. data/spec/fakes/instance.rb +32 -0
  41. data/spec/fakes/route53_client.rb +23 -0
  42. data/spec/fakes/stack.rb +65 -0
  43. data/spec/functional/deploy_spec.rb +73 -0
  44. data/spec/functional/kill_inactive_spec.rb +57 -0
  45. data/spec/functional_spec_helper.rb +3 -0
  46. data/spec/spec_helper.rb +8 -0
  47. data/spec/unit/application_spec.rb +191 -0
  48. data/spec/unit/component_spec.rb +142 -0
  49. data/spec/unit/config_loader_spec.rb +356 -0
  50. data/spec/unit/config_validation_spec.rb +480 -0
  51. data/spec/unit/deployment_strategy/auto_scaling_group_swap_spec.rb +435 -0
  52. data/spec/unit/deployment_strategy/base_spec.rb +44 -0
  53. data/spec/unit/deployment_strategy/cname_swap_spec.rb +294 -0
  54. data/spec/unit/deployment_strategy/create_or_update_spec.rb +113 -0
  55. data/spec/unit/deployment_strategy/deployment_strategy_spec.rb +29 -0
  56. data/spec/unit/driver/auto_scaling_group_spec.rb +127 -0
  57. data/spec/unit/driver/cloud_formation_spec.rb +32 -0
  58. data/spec/unit/driver/elb_spec.rb +11 -0
  59. data/spec/unit/driver/instance_spec.rb +30 -0
  60. data/spec/unit/driver/route53_spec.rb +85 -0
  61. data/spec/unit/driver/verisign_spec.rb +18 -0
  62. data/spec/unit/hook_spec.rb +64 -0
  63. data/spec/unit/stack_spec.rb +150 -0
  64. data/spec/unit/status_presenter_spec.rb +108 -0
  65. metadata +197 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2678998aaac0ea19f9aa0694359f9a54b92331a5
4
+ data.tar.gz: 62266fe192f394c3f1abc15c0002742a09add738
5
+ SHA512:
6
+ metadata.gz: 65bc63a0d516b1aa7a77c94d8cb4269a1231f81c062ea0716c5d737e703eed7cd862c6b04a9dd9a51b38fda39552886161a194602a83defe7436ad9e5e7edd02
7
+ data.tar.gz: 0150e15aa2782cb98d65d7da9439c63724224810eb8eb8b186dbff765157b717b6bd750bceb6a3d18f933f862d5bcec2c0f13fabfb3f01fbf9a38be3d61a0a42
data/.gitignore ADDED
@@ -0,0 +1,29 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ InstalledFiles
7
+ _yardoc
8
+ coverage
9
+ doc/
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ /.rvmrc
17
+ _site
18
+ /TAGS
19
+ /.aws
20
+ *.swp
21
+ temp/*
22
+ tmp/*
23
+ spec_result.html
24
+ vendor
25
+ config/
26
+ *.swo
27
+ tags
28
+ .rbenv-version
29
+ .ruby-version
data/ChangeLog.md ADDED
@@ -0,0 +1,16 @@
1
+ version 1.2.4:
2
+ - Changed the default behavior of Blue/Green deployment strategy to keep previous stack after a new deployment.
3
+ Now the previous deployed stack will be not deleted unless you set keep-previous-stack to false.
4
+
5
+ version 1.2.5:
6
+ - Throw errors when options cannot be recognised in cf_deployer.yml in order to help users to find configure errors early.
7
+ - Added setting raise-error-for-unused-inputs in cf_deployer.yml, which is false by default. When this setting is set to true, errors will be thrown if any inputs defined in cf_deployer.yml or given via command line -i parameters have no co-responding parameters in CloudFormation json templates.
8
+
9
+ version 1.2.6
10
+ - Fixed broken command status and -d (dry-run) options.
11
+
12
+ version 1.2.7
13
+ - Fixed broken option 'capabilities' under components.
14
+
15
+ version 1.2.8
16
+ - Removed configure option validion at root level. Now users can have their own options at the root level in cf_deployer.yml file.
data/DETAILS.md ADDED
@@ -0,0 +1,268 @@
1
+ ##### [README](README.md) - [QUICKSTART](QUICKSTART.md) - [DETAILS](DETAILS.md) - [FAQ](FAQ.md)
2
+
3
+ CFDeployer - Usage Details
4
+ ==============
5
+
6
+ ```shell
7
+ Commands:
8
+ cf_deploy config [ENVIRONMENT] # Show parsed config
9
+ cf_deploy deploy [ENVIRONMENT] [COMPONENT] # Deploy the specified components
10
+ cf_deploy destroy [ENVIRONMENT] [COMPONENT] # Destroy the specified environment/component
11
+ cf_deploy help [COMMAND] # Describe available commands or one specific command
12
+ cf_deploy json [ENVIRONMENT] [COMPONENT] # Show parsed CloudFormation JSON for the target component
13
+ cf_deploy kill_inactive [ENVIRONMENT] [COMPONENT] # Destroy the inactive stack for a given component/environment
14
+ cf_deploy status [ENVIRONMENT] [COMPONENT] # Show the status of the specified Cloud Formation components specified in your yml
15
+ cf_deploy switch [ENVIRONMENT] [COMPONENT] # Switch active and inactive stacks
16
+
17
+ Options:
18
+ -f, [--config-file=CONFIG-FILE] # cf_deployer config file
19
+ # Default: config/cf_deployer.yml
20
+ -l, [--log-level=LOG-LEVEL] # logging level
21
+ # Default: info
22
+ # Possible values: info, debug, aws-debug
23
+ -d, [--dry-run] # Say what we would do but don't actually make changes to anything
24
+ -s, [--settings=key:value] # key:value pair to overwrite setting in config
25
+ -i, [--inputs=key:value] # key:value pair to overwrite in template inputs
26
+ -r, [--region=REGION] # Amazon region
27
+ # Default: us-east-1
28
+
29
+ ```
30
+
31
+ ================
32
+ #### Defaults
33
+
34
+ By default cf_deployer looks at the config/cf_deployer.yml
35
+ * This can be overridden by using the -f flag
36
+ ```shell
37
+ cf_deployer -f samples/my_config.yml
38
+ ```
39
+
40
+ By default cf_deployer will try and deploy all components listed in
41
+ your config file
42
+
43
+ When using Cname Swap it looks for the ELB Name as an output referenced
44
+ by the key 'ELBName'
45
+ When using Auto Scaling Group Swap it looks for the Auto Scaling Group
46
+ name as an output referenced by the key 'AutoScalingGroupName'
47
+
48
+ Default user hook timeout is 10 minutes, this can be overridden as shown
49
+ in the examples below
50
+
51
+ For Blue/Green deployments keep-previous-stack is defaulted to true.
52
+ This means that after a deployment, the previous deployed stack will be kept.
53
+ For non-production environment, you may set it to false to delete the previous stack
54
+ after a deployment for saving cost.
55
+
56
+ If the CloudFormation template has the output named 'AutoScalingGroupName'
57
+ or the cf_deployer.yml has the setting 'auto-scaling-group-name-output',
58
+ CfDeployer knows that auto-scaling groups need to deploy and will warm up
59
+ the auto-scaling groups by checking associated ELB instance status if applicable.
60
+
61
+ ===================
62
+ ### Deployment Strategies
63
+
64
+ There are 3 strategies for deploying with cf_deployer:
65
+ * create_or_update
66
+ * **Non-Blue-Green** - Updates the CloudFormation directly
67
+ * cname_swap
68
+ * **Blue-Green** - Deploy to the inactive stack, then swap the CNAME entry to point to the
69
+ ElbName output from your CloudFormation template.
70
+ * auto_scaling_group_swap
71
+ * **Blue-Green** - Deploy to the inactive stack, then warm up the new auto scaling
72
+ group to the same size as old. Then cool down (set instances to 0) the old auto scaling group.
73
+
74
+ ==================
75
+ ### Settings vs Inputs
76
+
77
+ ##### Settings:
78
+ Used by the gem for blue/green deployments and naming conventions
79
+
80
+ * **For all deploys - These are the settings you can use**
81
+ * application
82
+ * component
83
+ * environment
84
+ * dns-driver (defaults to CfDeployer::Driver::Route53)
85
+ * keep-previous-stack (True/False: for Cname-Swap and Auto Scaling Group Swap, previous stack will be kept after new stack is created by default. Set it to false to delete the previous stack)
86
+ * raise-error-for-unused-inputs (True/False: it is false by default. If it is set to true, errors will be thrown if there are any inputs which are not used as parameters of CloudFormation json templates. If it is set to false or the setting does not exist, warnings will be printed in the console if there are un-used inputs.)
87
+ * auto-scaling-group-swap-name-output
88
+ * **For Components Using the Cname-Swap Deployment Strategy**
89
+ * dns-fqdn
90
+ * dns-zone
91
+ * elb-name-output
92
+
93
+ ##### Inputs:
94
+ Used by CloudFormation in the JSON template (Note: Settings can be used as inputs, but inputs are not used as settings). These can be almost anything. They are defined in the **Parameters** block in the CF template.
95
+
96
+
97
+ ==================
98
+ ### How Termination Works
99
+
100
+ Blue/Green deployments keep at most 2 different stacks up (Blue and
101
+ Green). If both are deployed and Green is active, Blue will be deleted
102
+ before being deployed with the newest version.
103
+
104
+ Components may be deleted several different ways:
105
+
106
+ * By default with Blue/Green deployments, after deploying a color (Green)
107
+ stack, the opposite color (Blue) will be kept.
108
+ * This can be overridden with the keep-previous-stack setting set as
109
+ false.
110
+ * You can use the destroy command and it will delete any versions
111
+ (blue/green) of the specified component that exist (BE CAREFUL!!)
112
+ * You can use the kill_inactive command to delete the 'inactive stack'
113
+ * For cname-swap this is the stack that DNS is _not_ pointing to
114
+ * For asg_swap this is the stack that has an autoscaling group with 0
115
+ instances
116
+
117
+
118
+ =================
119
+ ### Tagging Your Stacks
120
+
121
+ Tags for cf_deployer:application, cf_deployer:environment, and cf_deployer:component are automatically added to the CF stack by cf_deployer. To add your own tags:
122
+
123
+ ```
124
+ components:
125
+ web:
126
+ capabilities:
127
+ - CAPABILITY_IAM
128
+ tags:
129
+ Team: Team Awesome
130
+ OwnerEmail: awesome@domain.com
131
+
132
+ ```
133
+
134
+ ==============
135
+ ### Hooks
136
+
137
+ There are 3 places currently where a user-provided script can be run
138
+ before continuing with the deploy process. (Specified in the cf_deployer.yml) Information about how to add new hooks is at the bottom of this document.
139
+
140
+ * **before-destroy**
141
+ * This runs before a stack is spun down (This happens on delete, as
142
+ well as when spinning down the stack so a new version may be
143
+ deployed)
144
+ * **after-create**
145
+ * CnameSwap: Before the cname is switched to the new version (Smoke
146
+ Test)
147
+ * AutoScalingGroupSwap: Before warming up the new stack and cooling
148
+ down the old
149
+ * **after-swap**
150
+ * CnameSwap: After the cname is switched (Wait Script to ensure DNS
151
+ Switch happened)
152
+ * AutoScalingGroupSwap: After the warming up the new stack, and
153
+ cooling down the old stack
154
+
155
+ #### Examples:
156
+
157
+ ##### Ruby Code:
158
+ components:
159
+ web:
160
+ after-create: raise 'Server is down' unless system('curl -f http://mydomain.com/status')
161
+
162
+ ##### Ruby Code with Timeout:
163
+ components:
164
+ web:
165
+ after-create:
166
+ code: raise 'Server is down' unless system('curl -f http://mydomain.com/status')
167
+ timeout: 1500
168
+
169
+ ##### Ruby Code in a Separate File:
170
+ components:
171
+ web:
172
+ after-create:
173
+ file: smoke_test.rb
174
+
175
+
176
+
177
+ ================
178
+ ### ERB Like a Pro
179
+
180
+ CFDeployer runs its YAML config file and all CF JSON templates through ERB to allow sophisticated templating.
181
+
182
+ #### ERB in cf_deployer.yml
183
+
184
+ ##### ERB Templating in your cf_deployer.yml:
185
+ ```
186
+ <% app_name = 'my_app' %>
187
+
188
+ application: <%= app_name %>
189
+
190
+ settings:
191
+ inputs:
192
+ S3BucketName: <%= app_name %>-<%= environment %>-artifacts
193
+ ```
194
+ * Note that 'environment' is exposed to the template. Other settings and inputs are not available yet because the parsing hasn't happened yet.
195
+
196
+
197
+ ##### This also allows the use of helper classes to abstract organization-specific boilerplate settings:
198
+ ```
199
+ <%
200
+ require 'my_cfd_helper'
201
+ helper = MyCfdHelper::SettingsHelper.new
202
+ %>
203
+
204
+ settings:
205
+ inputs:
206
+ InstanceSubnets: <%= helper.instance_subnets %>
207
+ SecurityGrouops: <%= helper.default_security_groups %>
208
+ ElasticIP: <%= helper.next_available_elastic_ip %>
209
+ ```
210
+
211
+
212
+ #### ERB in component_cf.json
213
+
214
+ ##### Similarly to the cf_deployer.yml example above, ERB can be used with a helper class to abstract boilerplate JSON. This example might be used stand up a basic, ElasticBeanstalk-like web stack:
215
+
216
+ ```
217
+ <%
218
+ require 'my_cfd_helper'
219
+ helper = MyCfdHelper::TemplateHelper.new config
220
+ component_name = config[:settings][:component].capitalize
221
+ %>
222
+ {
223
+ "AWSTemplateFormatVersion": "2010-09-09",
224
+ "Description": "<%= config[:settings][:application] %> Web Stack",
225
+ "Parameters": {
226
+ <%= template_helper.standard_params %>
227
+ ,<%= template_helper.asg_params %>
228
+ ,<%= template_helper.elb_params %>
229
+ },
230
+ "Resources": {
231
+ <%= template_helper.component_role :component_name => component_name %>
232
+ ,<%= template_helper.web_elb :component_name => component_name %>
233
+ ,<%= template_helper.asg :component_name => component_name,
234
+ :elb_name => "#{component_name}ServerELB",
235
+ %>
236
+ },
237
+ "Outputs": {
238
+ <%= template_helper.asg_outputs :component_name => component_name %>
239
+ ,<%= template_helper.elb_outputs :component_name => component_name %>
240
+ }
241
+ }
242
+
243
+ ```
244
+ * Note that the component-specific settings and inputs parsed from the cf_deployer.yml are made available via the 'config' Hash.
245
+ DNS Providers are pluggable based on the dns-driver setting. To supply a new driver, you'll need to implement the find_alias_target and set_alias_target methods. See lib/cf_deployer/dns/ for examples.
246
+
247
+
248
+ ================
249
+ ### Extending CFDeployer
250
+
251
+ #### Adding New Hooks
252
+
253
+ Hooks should be relatively simple to extend. The Hook class should be initialized with the hook information pulled from the config file,
254
+ not hard-coded ruby. Convention is the YAML contains a key with the
255
+ name of the hook as the key. The value can be:
256
+ * Ruby Code
257
+ * A hash containing the :file key (Takes a file relative to the config
258
+ file directory)
259
+ * A hash containing the :code key
260
+
261
+ The instantiated object can then be #run This takes any one parameter (generally a hash, currently a hash with all your settings/inputs/JSON Template information) which
262
+ will then be available in the user defined script/code (Currently the
263
+ hash may be referenced by accessing the 'context' variable that is
264
+ available due to passing the binding to eval in CfDeployer::Hook#execute)
265
+
266
+ #### Adding New DNS Providers
267
+
268
+ DNS Providers are pluggable based on the dns-driver setting. To supply a new driver, you'll need to implement the find_alias_target and set_alias_target methods. See lib/cf_deployer/driver/ for examples.
data/FAQ.md ADDED
@@ -0,0 +1,61 @@
1
+ ##### [README](README.md) - [QUICKSTART](QUICKSTART.md) - [DETAILS](DETAILS.md) - [FAQ](FAQ.md)
2
+
3
+ CFDeployer - FAQ
4
+ =======================================
5
+
6
+ **CFDeployer is *GREAT*! How did you come up with the idea to write it?**
7
+
8
+ We shamelessly stole the original idea from the smart guys at ThoughtWorks Studios who created a gem called [EB Deployer](http://getmingle.io/eb_deployer/) for doing easy, blue/green deployments with ElasticBeanstalk. Thanks for the great work, guys!
9
+
10
+ ==========
11
+
12
+ **If EbD is so great, why bother creating CFD?**
13
+
14
+ EbD **IS** great but it only supports ElasticBeanstalk. EB is fine for pretty simple applications, but if you're writing something complex, with multiple components (including some that aren't web services and don't use ELBs), then it's not really a great fit. CloudFormation gives you a lot more flexibility and power (which is why EB uses it under the covers) but there wasn't an easy way to do blue/green deployments with it.
15
+
16
+ ==========
17
+
18
+ **Ok, so how is CFD different?**
19
+
20
+ * For starters, CFD **only** supports CloudFormation-based deployments, **not** ElasticBeanstalk. If you want to use EB, just use EB Deployer.
21
+
22
+ * CFD understands the concept that an application is often made up of multiple *components* that are deployed separately but are logically part of the same application.
23
+
24
+ * CFD allows your to add business-specific tags to your CF stacks
25
+
26
+ * CFD has a few options for user defined hook scripts: before-destroy, after-create, after-swap. Which allows for more flexibility. (ie. Before destroying an S3 bucket, the user will need to empty it.)
27
+
28
+ * Support for multiple deployment strategies: create-update, cname-swap (Blue/Green), auto-scaling-group-swap (Blue/Green)
29
+
30
+ * CFD will pass your YAML file and CloudFormation JSON template through ERB to allow for more flexibility
31
+
32
+ ===========
33
+
34
+ **So what parts of my application would be separate components?**
35
+
36
+ Because CloudFormation allows you to deploy complex things like a stack with multiple AutoScalingGroups, for example, it can be a little hard to decide what parts of your application should be considered different components for CFD. Generally, the question that really matters is, "What parts of my application must be deployed at the same time?" If you want to be able to deploy your web service independently of your back-end data processing worker, you probably want them to be two different CFD components.
37
+
38
+ ===========
39
+
40
+ **My *cf_deployer.yml* file is awfully repetitive. How can I DRY that up?**
41
+
42
+ Aside from using the usual YAML techniques to reuse common stuff, we pass the **cf_deployer.yml** file through Ruby's built-in templating system, ERB, to process inline Ruby code. With ERB, you could do all kinds of things to clean up that file like pulling parts of it into other files or dynamically generating common values. More info about ERB can found [here](http://www.stuartellis.eu/articles/erb/) and [here](http://www.startuprocket.com/blog/a-quick-introduction-to-embedded-ruby-erb-eruby).
43
+
44
+ ===========
45
+
46
+ **My *CloudFormation JSON templates* are REALLY long. What can I do about that?**
47
+
48
+ The JSON templates are run through ERB too so you can do lots of things. Here at [Manheim](http://www.manheim.com), we wrote a CFD Helper gem to help pull all of the boilerplate JSON out of our individual projects. See the [DETAILS](DETAILS.md) page for an example of what this can look like.
49
+
50
+ ===========
51
+
52
+ **How can I contribute to CFD?**
53
+
54
+ First off, thanks for wanting to help out!
55
+
56
+ 0. Fork it on GitHub
57
+ 0. Create your feature branch: `git checkout -b my-new-feature`
58
+ 0. Make your changes
59
+ 0. Commit your changes: `git commit -am 'Added some feature'`
60
+ 0. Push the branch to GitHub: `git push origin my-new-feature`
61
+ 0. Create a new Pull Request on GitHub
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in eb_deployer.gemspec
4
+ gemspec
5
+
6
+ gem 'yard'
7
+ gem 'pry'
8
+ gem 'rspec'
9
+ gem 'rake'
10
+ gem 'rainbow'
data/Gemfile.lock ADDED
@@ -0,0 +1,51 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cf_deployer (1.2.8)
5
+ aws-sdk
6
+ log4r
7
+ rainbow
8
+ thor
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ aws-sdk (1.41.0)
14
+ json (~> 1.4)
15
+ nokogiri (>= 1.4.4)
16
+ coderay (1.1.0)
17
+ diff-lcs (1.2.5)
18
+ json (1.8.1)
19
+ log4r (1.1.10)
20
+ method_source (0.8.2)
21
+ mini_portile (0.6.0)
22
+ nokogiri (1.6.2.1)
23
+ mini_portile (= 0.6.0)
24
+ pry (0.9.12.6)
25
+ coderay (~> 1.0)
26
+ method_source (~> 0.8)
27
+ slop (~> 3.4)
28
+ rainbow (2.0.0)
29
+ rake (10.3.0)
30
+ rspec (2.14.1)
31
+ rspec-core (~> 2.14.0)
32
+ rspec-expectations (~> 2.14.0)
33
+ rspec-mocks (~> 2.14.0)
34
+ rspec-core (2.14.8)
35
+ rspec-expectations (2.14.5)
36
+ diff-lcs (>= 1.1.3, < 2.0)
37
+ rspec-mocks (2.14.6)
38
+ slop (3.5.0)
39
+ thor (0.19.1)
40
+ yard (0.8.7.4)
41
+
42
+ PLATFORMS
43
+ ruby
44
+
45
+ DEPENDENCIES
46
+ cf_deployer!
47
+ pry
48
+ rainbow
49
+ rake
50
+ rspec
51
+ yard
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Manheim, Inc.
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/QUICKSTART.md ADDED
@@ -0,0 +1,96 @@
1
+ ##### [README](README.md) - [QUICKSTART](QUICKSTART.md) - [DETAILS](DETAILS.md) - [FAQ](FAQ.md)
2
+
3
+ CFDeployer - Quickstart
4
+ ======================
5
+
6
+ ### To start using CFDeployer with your project, you need:
7
+
8
+ * A working CloudFormation JSON template that is able to deploy a working instance of your application
9
+
10
+ * A cf_deployer.yml file that describes the components of your application and how they are deployed
11
+
12
+ This Quickstart will use the files in our [simple sample](samples/simple)
13
+
14
+ ==================
15
+ ### CloudFormation Templates
16
+
17
+ JSON-based CF templates are how you describe to CloudFormation what AWS resources to deploy and how they are configured. There are lots of good resources out there that explain how to write CF templates. CF templates can get pretty complex, depending on what AWS resources your application needs and writing the templates themselves is outside the scope of this documentation. Some good information about CF templates can be found here:
18
+
19
+ * The official [AWS CloudFormation](http://aws.amazon.com/cloudformation/) page
20
+
21
+ * [Getting Started with AWS CloudFormation](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/GettingStarted.html)
22
+
23
+ * [Anatomy of an AWS CloudFormation template](http://www.techrepublic.com/blog/the-enterprise-cloud/anatomy-of-an-aws-cloudformation-template/6117/)
24
+
25
+ * [Bootstrapping Applications via AWS CloudFormation](https://s3.amazonaws.com/cloudformation-examples/BoostrappingApplicationsWithAWSCloudFormation.pdf)
26
+
27
+ * [Create Your AWS Stack From a Recipe](http://aws.typepad.com/aws/2011/02/cloudformation-create-your-aws-stack-from-a-recipe.html)
28
+
29
+ * [Basic examples included with CFDeployer](samples/)
30
+
31
+ * The **ERB Like a Pro** section of our [DETAILS](DETAILS.md) page can show you some techniques for pulling some boilerplate out of your CF templates.
32
+
33
+ Note that you can use ERB and settings/inputs from the cf_deployer.yml file while developing your CloudFormation template by using CFD's **json** command and piping the output to a static CF template file. The static file can then be fed to CF via the AWS console or commandline utilities. Once you have a working CloudFormation template, you're ready to get started with CFDeployer.
34
+
35
+
36
+ ==================
37
+ ### Setting up your project to use CFDeployer
38
+
39
+ * **CFDeployer is a Ruby gem so you'll need a working version of Ruby.** CFDeployer should work with any 1.8.7 or 1.9.X Ruby interpreter. CFDeployer uses the official AWS-published Ruby SDK under the covers which, in turn, uses Nokogiri. We've heard that JRuby projects and Ruby 2.X projects have trouble getting Nokogiri installed so that might be an issue for your if you're using one of those Rubies.
40
+
41
+ * **The use of the [Bundler](http://bundler.io/) gem is strongly encouraged.** Put "gem 'cf_deployer'" into your Gemfile.
42
+
43
+ * **Tell Bundler to install CFDeployer and its dependencies**
44
+ ```shell
45
+ bundle install
46
+ ```
47
+
48
+ * **Make a 'config' directory to store your CloudFormation template and cf_deployer.yml files in.** The cf_deployer.yml file is assumed to be in the same directory as your CF templates. The path to your cf_deployer.yml can be specified with the --config-file (-f) commandline option.
49
+ ```shell
50
+ mkdir config
51
+ ```
52
+
53
+ * **Put your CF templates and cf_deployer.yml file into the config directory**
54
+
55
+
56
+ ==================
57
+ ### Using CFDeployer
58
+
59
+ The examples shown are specifying the 'qa' environment. Our cf_deployer.yml doesn't specify any particular settings or inputs for that environment so CFD uses the defaults from the YAML file, just like it would for any other ad hoc environment.
60
+
61
+ **Showing the parsed and ERBed settings that CFDeployer will use:**
62
+ ```shell
63
+ bundle exec cf_deploy config qa
64
+ ```
65
+
66
+ **Showing the parsed and ERBed CloudFormation template for the 'web' component:**
67
+ ```shell
68
+ bundle exec cf_deploy json qa web
69
+ ```
70
+
71
+ **Deploying a component:**
72
+ ```shell
73
+ bundle exec cf_deploy deploy qa web
74
+ ```
75
+
76
+ **Showing what CloudFormation stacks exist for an environment/component:**
77
+ ```shell
78
+ bundle exec cf_deploy status qa
79
+ ```
80
+
81
+ **Deploying a new version of your application in a blue/green fashion:**
82
+ ```shell
83
+ bundle exec cf_deploy deploy qa web
84
+ ```
85
+ Note that CFD will shut down the inactive stack, if it exists. The new stack will then be made active and the old stack will be made inactive (or terminated, depending on your cf_deployer.yml settings).
86
+
87
+ **Destroying all stacks for one component in an environment:**
88
+ ```shell
89
+ bundle exec cf_deploy destroy qa web
90
+ ```
91
+
92
+ **Destroying all stacks for ALL components in an environment:**
93
+ ```shell
94
+ bundle exec cf_deploy destroy qa
95
+ ```
96
+
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ ##### [README](README.md) - [QUICKSTART](QUICKSTART.md) - [DETAILS](DETAILS.md) - [FAQ](FAQ.md)
2
+
3
+ CFDeployer
4
+ ================
5
+
6
+ ## Installing
7
+
8
+ ```
9
+ $ gem install cf_deployer
10
+ ```
11
+
12
+ ## Basic Help
13
+
14
+ ```shell
15
+ Commands:
16
+ cf_deploy config [ENVIRONMENT] # Show parsed config
17
+ cf_deploy deploy [ENVIRONMENT] [COMPONENT] # Deploy the specified components
18
+ cf_deploy destroy [ENVIRONMENT] [COMPONENT] # Destroy the specified environment/component
19
+ cf_deploy help [COMMAND] # Describe available commands or one specific command
20
+ cf_deploy json [ENVIRONMENT] [COMPONENT] # Show parsed CloudFormation JSON for the target component
21
+ cf_deploy kill_inactive [ENVIRONMENT] [COMPONENT] # Destroy the inactive stack for a given component/environment
22
+ cf_deploy status [ENVIRONMENT] [COMPONENT] # Show the status of the specified Cloud Formation components specified in your yml
23
+ cf_deploy switch [ENVIRONMENT] [COMPONENT] # Switch active and inactive stacks
24
+
25
+ Options:
26
+ -f, [--config-file=CONFIG-FILE] # cf_deployer config file
27
+ # Default: config/cf_deployer.yml
28
+ -l, [--log-level=LOG-LEVEL] # logging level
29
+ # Default: info
30
+ # Possible values: info, debug, aws-debug
31
+ -d, [--dry-run] # Say what we would do but don't actually make changes to anything
32
+ -s, [--settings=key:value] # key:value pair to overwrite setting in config
33
+ -i, [--inputs=key:value] # key:value pair to overwrite in template inputs
34
+ -r, [--region=REGION] # Amazon region
35
+ # Default: us-east-1
36
+ ```
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'bundler/gem_tasks'
4
+
5
+ require 'rspec/core/rake_task'
6
+
7
+ namespace :spec do
8
+ RSPEC_OPTS = ["--format", "nested", "--format", "html", "--out", "spec_result.html", "--colour"]
9
+
10
+ RSpec::Core::RakeTask.new(:file) do |t|
11
+ t.rspec_opts = RSPEC_OPTS
12
+ t.pattern = ENV['SPEC_FILE']
13
+ end
14
+
15
+ RSpec::Core::RakeTask.new(:unit) do |t|
16
+ t.rspec_opts = RSPEC_OPTS
17
+ t.pattern = 'spec/unit/**/*_spec.rb'
18
+ end
19
+
20
+ RSpec::Core::RakeTask.new(:functional) do |t|
21
+ t.rspec_opts = RSPEC_OPTS
22
+ t.pattern = 'spec/functional/**/*_spec.rb'
23
+ end
24
+
25
+ task :all => [:unit, :functional]
26
+ end
27
+
28
+ task :default => 'spec:all'
29
+
30
+ task :clean do
31
+ system "rm -rf pkg/*"
32
+ end
data/bin/cf_deploy ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/cf_deployer'
4
+
5
+ begin
6
+ CfDeployer::CLI.start(ARGV)
7
+ rescue CfDeployer::ApplicationError => e
8
+ puts "Error: #{e.message}"
9
+ exit(1)
10
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/cf_deployer/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Jame Brechtel", "Peter Zhao", "Patrick McFadden", "Rob Sweet"]
6
+ gem.email = ["jbrechtel@gmail.com", "peter.qs.zhao@gmail.com", "pemcfadden@gmail.com", "rob@ldg.net"]
7
+ gem.description = %q{For automatic blue green deployment flow on CloudFormation.}
8
+ gem.summary = %q{Support multiple components deployment using CloudFormation templates with multiple blue green strategies.}
9
+ gem.homepage = "http://github.com/manheim/cf_deployer"
10
+ gem.license = 'MIT'
11
+
12
+ gem.add_runtime_dependency 'aws-sdk'
13
+ gem.add_runtime_dependency 'log4r'
14
+ gem.add_runtime_dependency 'thor'
15
+ gem.add_runtime_dependency 'rainbow'
16
+
17
+ gem.files = `git ls-files`.split($\).reject {|f| f =~ /^samples\// }
18
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
19
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
+ gem.name = "cf_deployer"
21
+ gem.require_paths = ["lib"]
22
+ gem.version = CfDeployer::VERSION
23
+ end