elzar 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG.md +6 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +46 -83
  5. data/README.md +19 -17
  6. data/USAGE.md +257 -0
  7. data/bin/elzar +94 -0
  8. data/chef/site-cookbooks/ruby/metadata.rb +3 -1
  9. data/chef/site-cookbooks/ruby/recipes/default.rb +1 -0
  10. data/chef/site-cookbooks/ruby/recipes/path.rb +17 -0
  11. data/elzar.gemspec +4 -0
  12. data/lib/elzar.rb +5 -1
  13. data/lib/elzar/assistant.rb +82 -70
  14. data/lib/elzar/aws_config.rb +46 -0
  15. data/lib/elzar/cli.rb +143 -0
  16. data/lib/elzar/compute.rb +52 -0
  17. data/lib/elzar/core_ext/hash.rb +18 -0
  18. data/lib/elzar/fog.rb +53 -0
  19. data/lib/elzar/ssh_key_locator.rb +37 -0
  20. data/lib/elzar/templates/Gemfile +4 -4
  21. data/lib/elzar/templates/Vagrantfile.erb +1 -1
  22. data/lib/elzar/templates/aws_config.private.yml +13 -0
  23. data/lib/elzar/templates/aws_config.yml +6 -0
  24. data/lib/elzar/templates/data_bags/deploy/authorized_keys.json +4 -5
  25. data/lib/elzar/templates/dna/rails.json +15 -0
  26. data/lib/elzar/templates/gitignore +1 -0
  27. data/lib/elzar/version.rb +1 -1
  28. data/script/ci_nightly +14 -0
  29. data/spec/fixtures/rails_integration_template/add_root_user.rb +9 -0
  30. data/spec/fixtures/rails_integration_template/database.yml +7 -0
  31. data/spec/fixtures/rails_integration_template/deploy.rb +11 -0
  32. data/spec/fixtures/rails_integration_template/template.rb +22 -0
  33. data/spec/integration/rails_spec.rb +190 -0
  34. data/spec/lib/elzar/assistant_spec.rb +30 -0
  35. data/spec/lib/elzar/aws_config_spec.rb +84 -0
  36. data/spec/lib/elzar/ssh_key_locator_spec.rb +51 -0
  37. data/spec/spec_helper.rb +11 -0
  38. data/spec/support/shell_interaction_helpers.rb +33 -0
  39. metadata +107 -7
  40. data/lib/elzar/chef_dna.rb +0 -48
  41. data/lib/elzar/templates/dna.json +0 -25
  42. data/spec/chef_dna_spec.rb +0 -58
data/.gitignore CHANGED
@@ -1 +1,4 @@
1
1
  /.vagrant
2
+ .idea
3
+ pkg
4
+ provision
@@ -1,3 +1,9 @@
1
+ ## 0.2.0
2
+ * Drop support for relevance_rails
3
+ * Update DNA to be opinionated, to support Ruby 1.9.3
4
+ (as opposed to REE) and Postgres (as opposed to MySQL)
5
+ * Update CLI commands and options. (See USAGE.md.)
6
+
1
7
  ## 0.1.0
2
8
  * Initial working version for relevance_rails
3
9
 
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in elzar.gemspec
4
+ gemspec
@@ -1,96 +1,59 @@
1
- GIT
2
- remote: git://github.com/sumbach/knife-github-cookbooks.git
3
- revision: 13d5d7444b468cab24e6fa2d4b07da6ea45ac088
1
+ PATH
2
+ remote: .
4
3
  specs:
5
- knife-github-cookbooks (0.1.5)
6
- chef (~> 0.10.0)
7
- launchy (~> 0.4.0)
4
+ elzar (0.2.0)
5
+ fog (~> 1.5.0)
6
+ gli (~> 2.0.0)
7
+ multi_json (~> 1.3.0)
8
+ slushy (~> 0.1.3)
8
9
 
9
10
  GEM
10
11
  remote: http://rubygems.org/
11
12
  specs:
12
- archive-tar-minitar (0.5.2)
13
- bunny (0.7.9)
14
- chef (0.10.8)
15
- bunny (>= 0.6.0)
16
- erubis
17
- highline
18
- json (>= 1.4.4, <= 1.6.1)
19
- mixlib-authentication (>= 1.1.0)
20
- mixlib-cli (>= 1.1.0)
21
- mixlib-config (>= 1.1.2)
22
- mixlib-log (>= 1.3.0)
23
- moneta
24
- net-ssh (~> 2.1.3)
25
- net-ssh-multi (~> 1.1.0)
26
- ohai (>= 0.6.0)
27
- rest-client (>= 1.0.4, < 1.7.0)
28
- treetop (~> 1.4.9)
29
- uuidtools
30
- configuration (1.3.1)
31
- erubis (2.7.0)
32
- ffi (1.0.11)
33
- highline (1.6.11)
34
- i18n (0.6.0)
35
- ipaddress (0.8.0)
36
- json (1.5.2)
37
- knife-solo (0.0.4)
38
- chef (~> 0.10.0)
39
- net-ssh (~> 2.1.3)
40
- launchy (0.4.0)
41
- configuration (>= 0.0.5)
42
- rake (>= 0.8.1)
43
- mime-types (1.18)
44
- mixlib-authentication (1.1.4)
45
- mixlib-log
46
- mixlib-cli (1.2.2)
47
- mixlib-config (1.1.2)
48
- mixlib-log (1.3.0)
49
- moneta (0.6.0)
13
+ bahia (0.7.2)
14
+ open4 (~> 1.3.0)
15
+ builder (3.1.3)
16
+ diff-lcs (1.1.3)
17
+ excon (0.16.2)
18
+ fog (1.5.0)
19
+ builder
20
+ excon (~> 0.14)
21
+ formatador (~> 0.2.0)
22
+ mime-types
23
+ multi_json (~> 1.0)
24
+ net-scp (~> 1.0.4)
25
+ net-ssh (>= 2.1.3)
26
+ nokogiri (~> 1.5.0)
27
+ ruby-hmac
28
+ formatador (0.2.3)
29
+ gli (2.0.0)
30
+ jruby-pageant (1.1.1)
31
+ mime-types (1.19)
32
+ multi_json (1.3.6)
50
33
  net-scp (1.0.4)
51
34
  net-ssh (>= 1.99.1)
52
- net-ssh (2.1.4)
53
- net-ssh-gateway (1.1.0)
54
- net-ssh (>= 1.99.1)
55
- net-ssh-multi (1.1)
56
- net-ssh (>= 2.1.4)
57
- net-ssh-gateway (>= 0.99.0)
58
- ohai (0.6.12)
59
- ipaddress
60
- mixlib-cli
61
- mixlib-config
62
- mixlib-log
63
- systemu
64
- yajl-ruby
65
- polyglot (0.3.3)
35
+ net-ssh (2.6.0)
36
+ jruby-pageant (>= 1.1.1)
37
+ nokogiri (1.5.5)
38
+ open4 (1.3.0)
66
39
  rake (0.9.2.2)
67
- rest-client (1.6.7)
68
- mime-types (>= 1.16)
69
- systemu (2.5.0)
70
- thor (0.14.6)
71
- treetop (1.4.10)
72
- polyglot
73
- polyglot (>= 0.3.1)
74
- uuidtools (2.1.2)
75
- vagrant (0.8.7)
76
- archive-tar-minitar (= 0.5.2)
77
- erubis (~> 2.7.0)
78
- i18n (~> 0.6.0)
79
- json (~> 1.5.1)
80
- net-scp (~> 1.0.4)
81
- net-ssh (~> 2.1.4)
82
- thor (~> 0.14.6)
83
- virtualbox (~> 0.9.1)
84
- virtualbox (0.9.2)
85
- ffi (~> 1.0.9)
86
- yajl-ruby (1.1.0)
40
+ rspec (2.11.0)
41
+ rspec-core (~> 2.11.0)
42
+ rspec-expectations (~> 2.11.0)
43
+ rspec-mocks (~> 2.11.0)
44
+ rspec-core (2.11.1)
45
+ rspec-expectations (2.11.3)
46
+ diff-lcs (~> 1.1.3)
47
+ rspec-mocks (2.11.2)
48
+ ruby-hmac (0.4.0)
49
+ slushy (0.1.3)
87
50
 
88
51
  PLATFORMS
89
52
  ruby
90
53
 
91
54
  DEPENDENCIES
92
- chef (= 0.10.8)
93
- json (= 1.5.2)
94
- knife-github-cookbooks!
95
- knife-solo (= 0.0.4)
96
- vagrant (= 0.8.7)
55
+ bahia
56
+ bundler
57
+ elzar!
58
+ rake (~> 0.9.2.2)
59
+ rspec
data/README.md CHANGED
@@ -1,22 +1,11 @@
1
1
  ## Description
2
+
2
3
  This gem enables a Rails app to define custom Chef recipes while still using an awesome default set
3
- of Chef recipes. Best used in conjunction with relevance\_rails and slushy. Includes recipes for
4
- ruby 1.9, ree, mysql, postgresql and nginx/passenger.
4
+ of Chef recipes. Includes recipes for Ruby 1.9, postgresql, and nginx/passenger.
5
5
 
6
6
  ## Usage
7
7
 
8
- To use Elzar with your Rails app, just use (relevance_rails)[https://github.com/relevance/relevance_rails].
9
-
10
- But if you'd like to manually do it:
11
-
12
- ```ruby
13
- # Creates a provision/ directory to define app-specific cookbooks
14
- Elzar.create_provision_directory 'provision'
15
-
16
- # To combine Elzar's cookbooks with your app's cookbooks
17
- dir = Elzar.merge_and_create_temp_directory 'provision'
18
- # You now have a directory you can put on a chef node
19
- ```
8
+ To use Elzar with your Rails app, see [USAGE.md](https://github.com/relevance/elzar/blob/master/USAGE.md).
20
9
 
21
10
  ## Local Development
22
11
 
@@ -26,9 +15,12 @@ If you'd like to try these Chef cookbooks with Vagrant:
26
15
  $ git clone git@github.com:relevance/elzar.git
27
16
  $ cd elzar
28
17
  $ gem install bundler
29
- # creates provision/ for local vagrant use
18
+
19
+ # creates a `provision` directory for local vagrant use
30
20
  $ rake bam
21
+
31
22
  $ cd provision
23
+ $ vim dna.json # edit DNA file to give a name to your Rails app with no whitespace (e.g., "my_sample_app")
32
24
  $ bundle install
33
25
 
34
26
  ## Using Vagrant
@@ -40,7 +32,7 @@ your bundle and grab the Ubuntu Lucid VM image.
40
32
  vagrant box add lucid64 http://files.vagrantup.com/lucid64.box
41
33
 
42
34
  ```sh
43
- ## Spin up a new VM
35
+ ## Spin up a new VM and run the Chef recipes on it
44
36
  $ vagrant up
45
37
 
46
38
  ## SSH into the VM
@@ -57,6 +49,16 @@ $ vagrant suspend
57
49
  $ vagrant resume
58
50
  ```
59
51
 
52
+ ### CLI Development
53
+
54
+ The CLI tool (bin/elzar) is built on top of [GLI](https://github.com/davetron5000/gli)
55
+ which is a command line parser modelled after Git. Normally any
56
+ exception that occurs while running a command results in only the error
57
+ message being displayed, not the backtrace. If you would like to view
58
+ the backtrace you must set the env variable `GLI_DEBUG=true`.
59
+
60
+ GLI_DEBUG=true bundle exec bin/elzar foo
61
+
60
62
  ## Issues
61
63
 
62
- Please file issues [on github](https://github.com/relevance/elzar/issues).
64
+ Please file issues [on GitHub](https://github.com/relevance/elzar/issues).
@@ -0,0 +1,257 @@
1
+ Elzar Usage
2
+ ===========
3
+
4
+ ## Rails Tutorial
5
+
6
+ This example assumes that you have a working Rails application that is
7
+ compatible with the default [Rails DNA](/relevance/elzar/tree/master/lib/elzar/templates/dna/rails.json)
8
+ included in Elzar.
9
+
10
+ All commands assume your `RAILS_ROOT` is your current working directory.
11
+
12
+ ### Step 0: Install Elzar
13
+
14
+ ```sh
15
+ gem install elzar
16
+ ```
17
+
18
+
19
+ ### Step 1: Initialize Elzar's Provision Directory
20
+
21
+ This creates a `provision/` directory inside of your project. This
22
+ folder will be used to hold configuration data, custom Chef recipes,
23
+ and the `dna.json` file which specifies how configuration data to
24
+ the Chef recipes themselves.
25
+
26
+ ```sh
27
+ elzar init --dna=rails
28
+ ```
29
+
30
+
31
+ ### Step 2: Configure dna.json
32
+
33
+ The previous command created a `dna.json` template at
34
+ `provision/dna.json`. It will look roughly like so:
35
+
36
+ ```javascript
37
+ {
38
+ "run_list":["role[plumbing]", "role[postgres_database]", "ruby", "passenger", "rails_app"],
39
+ "passenger": {
40
+ "version": "3.0.11",
41
+ "root_path": "/opt/relevance-ruby/lib/ruby/gems/1.9.1/gems/passenger-3.0.11",
42
+ "module_path": "/opt/relevance-ruby/lib/ruby/gems/1.9.1/gems/passenger-3.0.11/ext/apache2/mod_passenger.so"
43
+ },
44
+ "ruby": {
45
+ "version": "1.9.3-p194",
46
+ "url": "http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p194.tar.gz"
47
+ },
48
+ "rails_app": {
49
+ "name": "TODO: Replace with the name of your Rails app"
50
+ }
51
+ }
52
+ ```
53
+
54
+ This file specifies which recipes Chef will run and how they will be
55
+ ran. For example, you can edit the `run_list` to run a custom
56
+ recipe that you have created or swap out one of the default recipes for
57
+ another (e.g. mysql for postgresql).
58
+
59
+ At the very least you will need to specify `rails_app[name]`. For
60
+ example:
61
+
62
+ ```javascript
63
+ "rails_app": {
64
+ "name": "elzar_rails_example"
65
+ }
66
+ ```
67
+
68
+ The `rails_app[name]` in `dna.json` has several implicit effects:
69
+
70
+ * It determines where your app lives on the file system (e.g.,
71
+ `/var/www/apps/elzar_rails_example/`)
72
+ * It determines the name of your database (e.g.,
73
+ `elzar_rails_example_production`)
74
+ * It determines the path of your nginx configuration file (e.g.,
75
+ `/etc/nginx/sites-enabled/elzar_rails_example`)
76
+
77
+ You'll want to consider how your choice of `rails_app` name will operate
78
+ in these contexts (e.g., whether your database engine allows
79
+ dashes in its database names).
80
+
81
+
82
+ ### Step 3: Configure AWS Settings
83
+
84
+ The `init` command also created 2 separate AWS configuration files:
85
+
86
+ * `provision/aws_config.yml` - holds non-sensitive settings, which
87
+ you're comfortable checking into Git
88
+ * `provision/aws_config.private.yml` - holds (wait for it) private
89
+ settings, which you should **not** check into Git
90
+
91
+ These files look like so:
92
+
93
+ ```yaml
94
+ # aws_config.yml
95
+ server:
96
+ creation_config:
97
+ flavor_id: <instance type, e.g. 'm1.large'>
98
+ image_id: <AMI to bootstrap with; must be some Ubuntu server image; e.g., "ami-fd589594" for Ubuntu 11.04>
99
+ groups: <security group to place the new deployment in, e.g. "default">
100
+ key_name: <name of the public/private keypair to start instance with>
101
+ ```
102
+
103
+ ```yaml
104
+ # aws_config.private.yml
105
+ aws_credentials:
106
+ aws_access_key_id: <your aws access key id>
107
+ aws_secret_access_key: <your aws secret access key>
108
+
109
+ server:
110
+ private_key: |
111
+ -----BEGIN RSA PRIVATE KEY-----
112
+ Include the RSA private key here. This should correspond to the keypair indicated
113
+ by server[:creation_config][:key_name] in aws_config.yml.
114
+ -----END RSA PRIVATE KEY-----
115
+ ```
116
+
117
+ Elzar will load both of these files and perform a deep merge on them.
118
+ Any settings in `aws_config.private.yml` will override settings found in
119
+ `aws_config.yml`.
120
+
121
+ Edit these files as appropriate for your project.
122
+
123
+
124
+ ### Step 4: Preheat Your Server
125
+
126
+ This step will provision a new server from AWS using your specified
127
+ credentials and will bootstrap Chef Solo on the box.
128
+
129
+ Note: **A *new* EC2 instance is provisioned each time this script is
130
+ executed**; you'll probably want to clean up those instances if you need
131
+ to re-start for any reason.
132
+
133
+ ```sh
134
+ elzar preheat "ElzarRailsExample Staging"
135
+ ```
136
+
137
+ In this case, Elzar will provision a new instance and tag it with a name
138
+ of "ElzarRailsExample Staging". This is the name that you will see when browsing
139
+ instances in the AWS console. Name your instance accordingly.
140
+
141
+ If this step completes successfully, it will display the ID of the
142
+ instance, which you'll use in the next step, as well as its public IP address. For example:
143
+
144
+ ```
145
+ Finished Provisioning Server
146
+ Instance ID: i-abcdef01
147
+ Instance IP: 42.42.000.42
148
+ ````
149
+
150
+
151
+ ### Step 5: Cook the Recipes
152
+
153
+ This step is responsible for combining your custom recipes (if any) and
154
+ configuration with the default recipes that ship with Elzar. The
155
+ combined payload will be uploaded to the server and placed in
156
+ `/tmp/chef-solo` where they will run.
157
+
158
+
159
+ ```sh
160
+ elzar cook [YOUR-INSTANCE-ID]
161
+ ```
162
+
163
+
164
+ ### Step 6: Configure Capistrano
165
+
166
+ At this point in time, we have a server that is ready to run our app.
167
+ Now, we just need to get our app up there.
168
+
169
+ First off, we need to add Capistrano and [capistrano-relevance](https://github.com/relevance/capistrano-relevance) to our Rails app.
170
+ To do so, add these lines to the `Gemfile` in the Rails application:
171
+
172
+ ```ruby
173
+ group :deployment do
174
+ gem 'capistrano', :git => 'git://github.com/capistrano/capistrano', :ref => 'b31e2f5'
175
+ gem 'capistrano-relevance'
176
+ end
177
+ ```
178
+
179
+ And then execute:
180
+
181
+ ```sh
182
+ bundle
183
+ bundle exec capify .
184
+ ```
185
+
186
+ Next, we need to customize `config/deploy.rb` for our app.
187
+ (For the purposes of this tutorial, we'll assume that we want the default capistrano-relevance configuration. For alternative setups, and for more information on capistrano-relevance, check out its [README](https://github.com/relevance/capistrano-relevance/blob/master/README.md).)
188
+
189
+ *Replace* the existing contents of `config/deploy.rb` with a structure like so:
190
+
191
+ ```ruby
192
+ require 'bundler/capistrano'
193
+ require 'capistrano/relevance/all'
194
+
195
+ set :application, "elzar_rails_example" # TODO Replace with *your* app name
196
+ set :repository, "git://github.com/you/elzar_rails_example" # TODO Replace with *your* repo
197
+
198
+ role :web, "42.42.000.42" # TODO Replace with the IP address for *your* EC2 instance
199
+ role :app, "42.42.000.42" # TODO Replace with the IP address for *your* EC2 instance
200
+ role :db, "42.42.000.42", :primary => true # TODO Replace with the IP address for *your* EC2 instance
201
+ ```
202
+
203
+
204
+ ### Step 7: Prepare to Serve
205
+
206
+ Now that we have a working Capistrano configuration we just need to make a couple of other small tweaks to make the box deployable.
207
+ Specifically, we need to create the directory structure that Capistrano expects and place our database configuration on the box.
208
+
209
+ Best practices (TM) discourage us from checking in any database credentials into our Git repo.
210
+ Instead, we can create a `database.yml` file on the server.
211
+
212
+ ```sh
213
+ bundle exec cap deploy:setup
214
+
215
+ ssh deploy@42.42.000.42
216
+
217
+ # Create the the directory where you will store your shared configuration.
218
+ mkdir /var/www/apps/[YOUR-APP-NAME]/shared/config
219
+
220
+ # Add production settings for the database
221
+ vim /var/www/apps/[YOUR-APP-NAME]/shared/config/database.yml
222
+
223
+ # We're done messing around on the server; let's get outta here
224
+ exit
225
+ ```
226
+
227
+ Your `database.yml` file should look similar to this one, obviously edited to meet your application's needs.
228
+
229
+ ```yaml
230
+ production:
231
+ adapter: postgresql
232
+ encoding: unicode
233
+ database: [YOUR-APP-NAME]_production
234
+ pool: 5
235
+ username: deploy
236
+ password: d3pl0y-p0stgr3s
237
+ ```
238
+
239
+
240
+ ### Step 8: Serve It Up
241
+
242
+ Here comes the exciting part.
243
+ It's time to deploy our Rails app to the box.
244
+ Since this is the first time we've ever deployed to the box we'll need to run a special Capistrano command that does slightly more work than a bare deploy.
245
+
246
+ ```sh
247
+ # execute from RAILS_ROOT on your localhost
248
+ bundle exec cap deploy:cold
249
+ ```
250
+
251
+ Congratulations! You should be able to visit the IP address using your favorite browser and see the application up and running.
252
+
253
+ For subsequent deploys, you can simply run:
254
+
255
+ ```sh
256
+ bundle exec cap deploy
257
+ ```