elzar 0.1.2 → 0.2.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.
- data/.gitignore +3 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +46 -83
- data/README.md +19 -17
- data/USAGE.md +257 -0
- data/bin/elzar +94 -0
- data/chef/site-cookbooks/ruby/metadata.rb +3 -1
- data/chef/site-cookbooks/ruby/recipes/default.rb +1 -0
- data/chef/site-cookbooks/ruby/recipes/path.rb +17 -0
- data/elzar.gemspec +4 -0
- data/lib/elzar.rb +5 -1
- data/lib/elzar/assistant.rb +82 -70
- data/lib/elzar/aws_config.rb +46 -0
- data/lib/elzar/cli.rb +143 -0
- data/lib/elzar/compute.rb +52 -0
- data/lib/elzar/core_ext/hash.rb +18 -0
- data/lib/elzar/fog.rb +53 -0
- data/lib/elzar/ssh_key_locator.rb +37 -0
- data/lib/elzar/templates/Gemfile +4 -4
- data/lib/elzar/templates/Vagrantfile.erb +1 -1
- data/lib/elzar/templates/aws_config.private.yml +13 -0
- data/lib/elzar/templates/aws_config.yml +6 -0
- data/lib/elzar/templates/data_bags/deploy/authorized_keys.json +4 -5
- data/lib/elzar/templates/dna/rails.json +15 -0
- data/lib/elzar/templates/gitignore +1 -0
- data/lib/elzar/version.rb +1 -1
- data/script/ci_nightly +14 -0
- data/spec/fixtures/rails_integration_template/add_root_user.rb +9 -0
- data/spec/fixtures/rails_integration_template/database.yml +7 -0
- data/spec/fixtures/rails_integration_template/deploy.rb +11 -0
- data/spec/fixtures/rails_integration_template/template.rb +22 -0
- data/spec/integration/rails_spec.rb +190 -0
- data/spec/lib/elzar/assistant_spec.rb +30 -0
- data/spec/lib/elzar/aws_config_spec.rb +84 -0
- data/spec/lib/elzar/ssh_key_locator_spec.rb +51 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/support/shell_interaction_helpers.rb +33 -0
- metadata +107 -7
- data/lib/elzar/chef_dna.rb +0 -48
- data/lib/elzar/templates/dna.json +0 -25
- data/spec/chef_dna_spec.rb +0 -58
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -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
data/Gemfile.lock
CHANGED
@@ -1,96 +1,59 @@
|
|
1
|
-
|
2
|
-
remote:
|
3
|
-
revision: 13d5d7444b468cab24e6fa2d4b07da6ea45ac088
|
1
|
+
PATH
|
2
|
+
remote: .
|
4
3
|
specs:
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
net-ssh (
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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.
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
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.
|
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,
|
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
|
-
|
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
|
64
|
+
Please file issues [on GitHub](https://github.com/relevance/elzar/issues).
|
data/USAGE.md
ADDED
@@ -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
|
+
```
|