chamber 2.4.0 → 2.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +16 -930
- data/Rakefile +6 -0
- data/lib/chamber.rb +11 -7
- data/lib/chamber/binary/heroku.rb +45 -25
- data/lib/chamber/binary/runner.rb +82 -44
- data/lib/chamber/binary/travis.rb +14 -8
- data/lib/chamber/commands/base.rb +1 -2
- data/lib/chamber/commands/comparable.rb +0 -1
- data/lib/chamber/commands/compare.rb +1 -1
- data/lib/chamber/commands/files.rb +0 -1
- data/lib/chamber/commands/heroku.rb +2 -3
- data/lib/chamber/commands/heroku/push.rb +1 -1
- data/lib/chamber/commands/initialize.rb +69 -12
- data/lib/chamber/commands/securable.rb +9 -4
- data/lib/chamber/commands/secure.rb +1 -1
- data/lib/chamber/commands/show.rb +20 -4
- data/lib/chamber/commands/travis.rb +0 -1
- data/lib/chamber/configuration.rb +5 -5
- data/lib/chamber/context_resolver.rb +12 -12
- data/lib/chamber/decryption_key.rb +51 -0
- data/lib/chamber/environmentable.rb +4 -1
- data/lib/chamber/errors/decryption_failure.rb +6 -0
- data/lib/chamber/file.rb +7 -8
- data/lib/chamber/file_set.rb +23 -22
- data/lib/chamber/filters/boolean_conversion_filter.rb +1 -2
- data/lib/chamber/filters/decryption_filter.rb +42 -25
- data/lib/chamber/filters/encryption_filter.rb +7 -5
- data/lib/chamber/filters/environment_filter.rb +7 -7
- data/lib/chamber/filters/failed_decryption_filter.rb +41 -0
- data/lib/chamber/filters/namespace_filter.rb +1 -1
- data/lib/chamber/filters/secure_filter.rb +3 -5
- data/lib/chamber/filters/translate_secure_keys_filter.rb +5 -24
- data/lib/chamber/namespace_set.rb +6 -6
- data/lib/chamber/rails.rb +1 -3
- data/lib/chamber/rails/railtie.rb +6 -3
- data/lib/chamber/settings.rb +34 -32
- data/lib/chamber/version.rb +1 -1
- data/spec/fixtures/settings.yml +1 -0
- data/spec/lib/chamber/commands/files_spec.rb +4 -2
- data/spec/lib/chamber/commands/secure_spec.rb +8 -5
- data/spec/lib/chamber/commands/show_spec.rb +18 -3
- data/spec/lib/chamber/context_resolver_spec.rb +38 -18
- data/spec/lib/chamber/file_set_spec.rb +73 -52
- data/spec/lib/chamber/file_spec.rb +37 -23
- data/spec/lib/chamber/filters/boolean_conversion_filter_spec.rb +35 -33
- data/spec/lib/chamber/filters/decryption_filter_spec.rb +142 -21
- data/spec/lib/chamber/filters/encryption_filter_spec.rb +51 -19
- data/spec/lib/chamber/filters/environment_filter_spec.rb +12 -6
- data/spec/lib/chamber/filters/failed_decryption_filter_spec.rb +53 -0
- data/spec/lib/chamber/filters/insecure_filter_spec.rb +38 -18
- data/spec/lib/chamber/filters/namespace_filter_spec.rb +38 -38
- data/spec/lib/chamber/filters/secure_filter_spec.rb +10 -10
- data/spec/lib/chamber/filters/translate_secure_keys_filter_spec.rb +9 -6
- data/spec/lib/chamber/namespace_set_spec.rb +7 -5
- data/spec/lib/chamber/settings_spec.rb +168 -79
- data/spec/lib/chamber_spec.rb +72 -71
- metadata +22 -21
- data/lib/chamber/errors/undecryptable_value_error.rb +0 -6
- data/templates/settings.yml +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4a3d686721e6b3ccbf6352227cfa0a6bdfb2b43
|
4
|
+
data.tar.gz: 798f1cec12ea2648a916d7830739f0ef50647679
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68c4c8c96652a068514f1ac17edda03d06977b11dfc776f06d4b5f39fd75a579efde318806c29d8169d899f562bd75cd41de743b81d088b7721af2afc4adf197
|
7
|
+
data.tar.gz: 0de18f64eb779247df51a06085287f73eaf56acd9662a1643e75a5b5864c4cfc060a46ce6562f2ee67ad23560d9dfab4d39b64fcb3f43fd1d99b5f946b838b89
|
data/README.md
CHANGED
@@ -4,942 +4,28 @@ Chamber is the auto-encrypting, extremely organizable, Heroku-loving, CLI-having
|
|
4
4
|
non-extra-repo-needing, non-Rails-specific-ing, CI-serving configuration
|
5
5
|
management library.
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
We reviewed [some other gems](#alternatives), and while each fit a specific need
|
10
|
-
and each did some things well, none of them met all of the criteria that we felt
|
11
|
-
we (and assumed others) needed.
|
7
|
+
[![TrueFact](https://cloud.githubusercontent.com/assets/285582/4803823/ad8110fa-5e5e-11e4-90d6-59320045a786.png)](https://www.youtube.com/watch?v=NNG1OoH2RwE)
|
12
8
|
|
13
9
|
**Our Ten Commandments of Configuration Management**
|
14
10
|
|
15
11
|
<img src="https://akiajm7spx4gtbhaxe3qcomhaystacksoftwarearp.s3.amazonaws.com/photos/readmes/ten-commandments.png" align="right" />
|
16
12
|
|
17
|
-
1. Thou shalt be configurable, but use conventions so that configuration isn't
|
18
|
-
necessary
|
19
|
-
1. Thou shalt seamlessly work with Heroku or other deployment platforms, where custom
|
20
|
-
settings must be stored in environment variables
|
21
|
-
1. Thou shalt seamlessly work with Travis CI and other cloud CI platforms
|
13
|
+
1. Thou shalt be configurable, but [use conventions so that configuration isn't
|
14
|
+
necessary](https://github.com/thekompanee/chamber/wiki/Basic-Usage#convention-over-configuration)
|
15
|
+
1. Thou shalt [seamlessly work with Heroku](https://github.com/thekompanee/chamber/wiki/Heroku) or other deployment platforms, where custom
|
16
|
+
settings must be stored in [environment variables](https://github.com/thekompanee/chamber/wiki/Environment-Variable-Compatibility)
|
17
|
+
1. Thou shalt seamlessly work with [Travis CI](https://github.com/thekompanee/chamber/wiki/TravisCI) and other cloud CI platforms
|
22
18
|
1. Thou shalt not force users to use arcane
|
23
|
-
|
24
|
-
1. Thou shalt not require users keep a separate repo or cloud share sync just to
|
25
|
-
keep their secure settings updated
|
26
|
-
1. Thou shalt not be bound to a single framework like Rails (it should be usable in
|
27
|
-
plain Ruby projects)
|
28
|
-
1. Thou shalt have an easy-to-use CLI for scripting
|
19
|
+
[long_variables_to_keep_their_settings_organized](https://github.com/thekompanee/chamber/wiki/Accessing-Settings)
|
20
|
+
1. Thou shalt not require users keep a separate repo or cloud share sync [just to
|
21
|
+
keep their secure settings updated](https://github.com/thekompanee/chamber/wiki/Encrypting-Your-Settings)
|
22
|
+
1. Thou shalt not be bound to a single framework like Rails (it should be usable [in
|
23
|
+
plain Ruby projects](https://github.com/thekompanee/chamber/wiki/Basic-Usage#in-a-plain-old-ruby-project))
|
24
|
+
1. Thou shalt have an [easy-to-use CLI](https://github.com/thekompanee/chamber/wiki/Command-Line-Reference) for scripting
|
29
25
|
1. Thou shalt easily integrate with Capistrano for deployments
|
30
|
-
1. Thou shalt be well documented with full test coverage
|
31
|
-
1. Thou shalt not have to worry about accidentally committing secure settings
|
32
|
-
|
33
|
-
## Installation
|
34
|
-
|
35
|
-
Add this line to your application's Gemfile:
|
36
|
-
|
37
|
-
```ruby
|
38
|
-
gem 'chamber'
|
39
|
-
```
|
40
|
-
|
41
|
-
And then execute:
|
42
|
-
|
43
|
-
```sh
|
44
|
-
$ bundle
|
45
|
-
```
|
46
|
-
|
47
|
-
Or install it yourself as:
|
48
|
-
|
49
|
-
```sh
|
50
|
-
$ gem install chamber
|
51
|
-
```
|
52
|
-
|
53
|
-
Once the gem is installed, you'll want to add it to your project. To do this,
|
54
|
-
type:
|
55
|
-
|
56
|
-
```sh
|
57
|
-
chamber init
|
58
|
-
```
|
59
|
-
|
60
|
-
This creates a public/private keypair for you to use with your project. The
|
61
|
-
private key will be called `.chamber.pem`. The public key will be called
|
62
|
-
`.chamber.pem.pub`.
|
63
|
-
|
64
|
-
`.chamber.pem` will be added to your gitignore file so that it is not
|
65
|
-
accidentally checked in. *Keep this file safe* since anyone who has it will be
|
66
|
-
able to decrypt any settings that Chamber encrypts for you.
|
67
|
-
|
68
|
-
Lastly, it will create a sample `settings.yml` file for you which you should
|
69
|
-
modify as needed.
|
70
|
-
|
71
|
-
## Basic Usage
|
72
|
-
|
73
|
-
### Convention Over Configuration
|
74
|
-
|
75
|
-
By default Chamber only needs a base path to look for settings files. From
|
76
|
-
that path it will search for:
|
77
|
-
|
78
|
-
* The file `<basepath>/settings.yml`
|
79
|
-
* A set of files ending in `.yml` in the `<basepath>/settings` directory
|
80
|
-
|
81
|
-
### In Plain Old Ruby
|
82
|
-
|
83
|
-
```ruby
|
84
|
-
Chamber.load basepath: '/path/to/my/application'
|
85
|
-
```
|
86
|
-
|
87
|
-
### In Rails
|
88
|
-
|
89
|
-
You do not have to do anything. Chamber will auto-configure itself to point to
|
90
|
-
the `config` directory.
|
91
|
-
|
92
|
-
### Accessing Settings
|
93
|
-
|
94
|
-
The YAML data will be loaded and you will have access to the settings
|
95
|
-
through the `Chamber` class.
|
96
|
-
|
97
|
-
**Example:**
|
98
|
-
|
99
|
-
Given a `settings.yml` file containing:
|
100
|
-
|
101
|
-
```yaml
|
102
|
-
smtp:
|
103
|
-
server: "example.com"
|
104
|
-
username: "my_user"
|
105
|
-
password: "my_pass"
|
106
|
-
```
|
107
|
-
|
108
|
-
can be accessed as follows:
|
109
|
-
|
110
|
-
```ruby
|
111
|
-
Chamber[:smtp][:server]
|
112
|
-
# => example.com
|
113
|
-
```
|
114
|
-
|
115
|
-
or via object notation syntax:
|
116
|
-
|
117
|
-
```ruby
|
118
|
-
Chamber.env.smtp.server
|
119
|
-
# => example.com
|
120
|
-
```
|
121
|
-
|
122
|
-
### Securing Your Settings
|
123
|
-
|
124
|
-
Certain settings you will want to keep from prying eyes. Unlike other
|
125
|
-
configuration management libraries, Chamber doesn't require you to keep those
|
126
|
-
files separate. You can check *everything* into your repo.
|
127
|
-
|
128
|
-
Why is keeping your secure files separate a pain? Because you must keep those
|
129
|
-
files in sync between all of your team members who are deploying the app.
|
130
|
-
Either you have to use a separate private repo, or you have to use something
|
131
|
-
like a Dropbox share. In either case, you'd then symlink the files from their
|
132
|
-
locations into your application. What. A. Pain.
|
133
|
-
|
134
|
-
Chamber uses public/private encryption keys to seamlessly store any of your
|
135
|
-
configuration values as encrypted text. The only file that needs to be synced
|
136
|
-
*once* between developers is the private key. And even that file would only be
|
137
|
-
needed by the users deploying the application. If you're deploying via CI,
|
138
|
-
Github, etc, then technically no developer needs it.
|
139
|
-
|
140
|
-
#### Working With Secure Configuration Settings
|
141
|
-
|
142
|
-
After running `chamber init` as described above, the hard work is done. From
|
143
|
-
here on out, Chamber makes working with secure settings almost an afterthought.
|
144
|
-
|
145
|
-
When you create your configuration YAML file (or add a new setting to an
|
146
|
-
existing one), you can add a secure key by prefixing the key name with
|
147
|
-
`_secure_`, like so:
|
148
|
-
|
149
|
-
```yaml
|
150
|
-
# settings.yml
|
151
|
-
|
152
|
-
_secure_my_secure_key_name: 'my secure value'
|
153
|
-
```
|
154
|
-
|
155
|
-
To encrypt the secret with your key pair, use the `chamber secure` command:
|
156
|
-
|
157
|
-
```sh
|
158
|
-
$ chamber secure
|
159
|
-
```
|
160
|
-
|
161
|
-
This will replace the plaintext secret with an encrypted version, looking
|
162
|
-
something like this:
|
163
|
-
|
164
|
-
```yaml
|
165
|
-
# settings.yml
|
166
|
-
|
167
|
-
_secure_my_secure_key_name: 8239f293r9283r9823r92hf9823hf9uehfksdhviwuehf923uhrehf9238
|
168
|
-
```
|
169
|
-
|
170
|
-
Now, only users with the private key file can access the secret value. Once
|
171
|
-
the private key is in your application's root directory, you can access the
|
172
|
-
secret by name:
|
173
|
-
|
174
|
-
```ruby
|
175
|
-
Chamber.env.my_secure_key_name
|
176
|
-
# => 'my secure value'
|
177
|
-
```
|
178
|
-
|
179
|
-
### Using Existing Environment Variables
|
180
|
-
|
181
|
-
If deploying to a system which has all of your environment variables already set
|
182
|
-
(eg Heroku), you're not going to use all of the values stored in the YAML files.
|
183
|
-
Instead, you're going to want to pull certain values from environment variables.
|
184
|
-
|
185
|
-
**Example:**
|
186
|
-
|
187
|
-
Given a `settings.yml` file containing:
|
188
|
-
|
189
|
-
```yaml
|
190
|
-
smtp:
|
191
|
-
server: "example.com"
|
192
|
-
username: "my_user"
|
193
|
-
password: "my_pass"
|
194
|
-
```
|
195
|
-
|
196
|
-
If an environment variable is already set like so:
|
197
|
-
|
198
|
-
```sh
|
199
|
-
export SMTP_SERVER="myotherserverisapentium.com"
|
200
|
-
```
|
201
|
-
|
202
|
-
Then, when you ask Chamber to give you the SMTP server:
|
203
|
-
|
204
|
-
```ruby
|
205
|
-
Chamber[:smtp][:server]
|
206
|
-
# => "myotherserverisapentium.com"
|
207
|
-
```
|
208
|
-
|
209
|
-
It will return not what is in the YAML file, but what is in the environment
|
210
|
-
variable.
|
211
|
-
|
212
|
-
## Deploying to Heroku
|
213
|
-
|
214
|
-
If you're deploying to Heroku, they won't let you upload custom config files. If
|
215
|
-
you do not have your config files all stored in your repo, or some of your
|
216
|
-
settings are encrypted, it becomes more difficult to gain access to that
|
217
|
-
information on Heroku.
|
218
|
-
|
219
|
-
To solve this problem, Heroku allows you to set environment variables in your
|
220
|
-
application. Unfortunately this has the nasty side effect of being a pain to
|
221
|
-
deal with. For one, you have to deal with environment variables with unwieldy
|
222
|
-
names (eg `MY_THIRD_PARTY_SERVICE_DEV_API_KEY`). For another, it makes the
|
223
|
-
organization of those variables difficult.
|
224
|
-
|
225
|
-
Fortunately, Chamber allows you to organize your environment variables in
|
226
|
-
separate files and access them easily using hash or object notation, however at
|
227
|
-
the same time, it provides a convenient way to push all of those sensitive
|
228
|
-
configuration settings up to Heroku as environment variables.
|
229
|
-
|
230
|
-
When Chamber accesses those same hash/object notated config values, it will
|
231
|
-
first look to see if an associated environment variable exists. If it does, it
|
232
|
-
will use that in place of any values inside of the config files as [described
|
233
|
-
above](#using-existing-environment-variables).
|
234
|
-
|
235
|
-
To update Heroku with all the proper environment variables so that your app
|
236
|
-
works as expected, run the following from the root of your app:
|
237
|
-
|
238
|
-
```sh
|
239
|
-
chamber heroku push
|
240
|
-
```
|
241
|
-
|
242
|
-
And all of your settings will be converted to environment variable versions
|
243
|
-
and set on your Heroku app.
|
244
|
-
|
245
|
-
_**Note:** For the full set of options, see [The chamber Command Line
|
246
|
-
App](#the-chamber-command-line-app) below._
|
247
|
-
|
248
|
-
## Deploying to Travis CI
|
249
|
-
|
250
|
-
When deploying to Travis CI, it has similar environment variable requirements as
|
251
|
-
Heroku, however Travis allows the encryption of environment variables before
|
252
|
-
they are stored in the .travis.yml file. This allows for that file to be
|
253
|
-
checked into git without worrying about prying eyes figuring out your secret
|
254
|
-
information.
|
255
|
-
|
256
|
-
To execute this, simply run:
|
257
|
-
|
258
|
-
```sh
|
259
|
-
chamber travis secure
|
260
|
-
```
|
261
|
-
|
262
|
-
This will add `secure` entries into your `.travis.yml` file. Each one will
|
263
|
-
contain one environment variable.
|
264
|
-
|
265
|
-
_**Warning:** Each time you execute this command it will delete all secure
|
266
|
-
entries under 'env.global' in your `.travis.yml` file._
|
267
|
-
|
268
|
-
_**Note:** For the full set of options, see [The chamber Command Line
|
269
|
-
App](#the-chamber-command-line-app) below._
|
270
|
-
|
271
|
-
## Advanced Usage
|
272
|
-
|
273
|
-
### Explicitly Specifying Settings Files
|
274
|
-
|
275
|
-
Using convention over configuration, Chamber handles the 90% case by default,
|
276
|
-
however there may be times at which you would like to explicitly specify which
|
277
|
-
settings files are loaded. In these cases, Chamber has you covered:
|
278
|
-
|
279
|
-
```ruby
|
280
|
-
Chamber.load files: [
|
281
|
-
'/path/to/my/application/chamber/credentials.yml',
|
282
|
-
'/path/to/my/application/application*.yml',
|
283
|
-
'/path/to/my/application/chamber/*.yml',
|
284
|
-
]
|
285
|
-
```
|
286
|
-
|
287
|
-
In this case, Chamber will load *only* the `credentials.yml` file *without ever*
|
288
|
-
looking for a namespaced file. Then it will load `application.yml` *and* any
|
289
|
-
associated namespaced files. Finally it will load all \*.yml files in the
|
290
|
-
`chamber` directory *except* `credentials.yml` because it has previously been
|
291
|
-
loaded.
|
292
|
-
|
293
|
-
### Predicate Methods
|
294
|
-
|
295
|
-
When using object notation, all settings have `?` and `_` predicate methods
|
296
|
-
defined on them. They work like so:
|
297
|
-
|
298
|
-
#### '?' Predicates Check For Falsity
|
299
|
-
|
300
|
-
```ruby
|
301
|
-
Chamber.env.my_setting # => nil
|
302
|
-
Chamber.env.my_setting? # => false
|
303
|
-
|
304
|
-
Chamber.env.my_other_setting # => false
|
305
|
-
Chamber.env.my_other_setting? # => false
|
306
|
-
|
307
|
-
Chamber.env.another_setting # => 'my value'
|
308
|
-
Chamber.env.another_setting? # => true
|
309
|
-
```
|
310
|
-
|
311
|
-
#### '\_' Predicates Allow for Multi-Level Testing
|
312
|
-
|
313
|
-
```ruby
|
314
|
-
Chamber.env.empty? # => true
|
315
|
-
Chamber.env.my_setting_group_.my_setting? # => false
|
316
|
-
```
|
317
|
-
|
318
|
-
#### 'key?' Checks For Existence
|
319
|
-
|
320
|
-
The `?` method will return false if a key has been set to `false` or `nil`. In
|
321
|
-
order to check if a key has been set at all, use the `key?('some_key')` method
|
322
|
-
instead.
|
323
|
-
|
324
|
-
Notice the difference:
|
325
|
-
|
326
|
-
```ruby
|
327
|
-
Chamber.env.my_setting # => false
|
328
|
-
Chamber.env.my_setting? # => false
|
329
|
-
|
330
|
-
Chamber.env.key?('my_setting') # => true
|
331
|
-
Chamber.env.key?('my_non_existent_key') # => false
|
332
|
-
```
|
333
|
-
|
334
|
-
### ERB Preprocessing
|
335
|
-
|
336
|
-
One of the nice things about Chamber is that it runs each settings file through
|
337
|
-
ERB before it tries to parse it as YAML. The main benefit of this is that you
|
338
|
-
can use settings from previous files in ERB for later files.
|
339
|
-
|
340
|
-
**Example:**
|
341
|
-
|
342
|
-
```yaml
|
343
|
-
# settings.yml
|
344
|
-
|
345
|
-
production:
|
346
|
-
my_secret_key: 123456789
|
347
|
-
```
|
348
|
-
|
349
|
-
```erb
|
350
|
-
<%# settings/some_service-production.yml %>
|
351
|
-
|
352
|
-
my_service_url: http://my_username:<%= Chamber[:my_secret_key] %>@my-url.com
|
353
|
-
```
|
354
|
-
|
355
|
-
Because by default Chamber processes `settings*.yml` settings files before
|
356
|
-
anything in the `settings` subdirectory, this works.
|
357
|
-
|
358
|
-
But it's all ERB so you can do as much crazy ERB stuff in your settings files as
|
359
|
-
you'd like:
|
360
|
-
|
361
|
-
```erb
|
362
|
-
<%# settings.yml %>
|
363
|
-
|
364
|
-
<% %w{development test production}.each do |environment| %>
|
365
|
-
<%= environment %>:
|
366
|
-
hostname_with_subdomain: <%= environment %>.example.com:3000
|
367
|
-
|
368
|
-
<% end %>
|
369
|
-
```
|
370
|
-
|
371
|
-
Would result in the following settings being set:
|
372
|
-
|
373
|
-
```yaml
|
374
|
-
development:
|
375
|
-
hostname_with_subdomain: development.example.com:3000
|
376
|
-
|
377
|
-
test:
|
378
|
-
hostname_with_subdomain: test.example.com:3000
|
379
|
-
|
380
|
-
production:
|
381
|
-
hostname_with_subdomain: production.example.com:3000
|
382
|
-
```
|
383
|
-
|
384
|
-
### Namespacing
|
385
|
-
|
386
|
-
If, when running your app, you would like to have certain files loaded only
|
387
|
-
under specific circumstances, you can use Chamber's namespaces.
|
388
|
-
|
389
|
-
**Example:**
|
390
|
-
|
391
|
-
```ruby
|
392
|
-
Chamber.load( :basepath => Rails.root.join('config'),
|
393
|
-
:namespaces => {
|
394
|
-
:environment => ::Rails.env } )
|
395
|
-
```
|
396
|
-
|
397
|
-
For this class, it will not only try and load the file `config/settings.yml`,
|
398
|
-
it will _also_ try and load the file `config/settings-<environment>.yml`
|
399
|
-
where `<environment>` is whatever Rails environment you happen to be running.
|
400
|
-
|
401
|
-
#### Inline Namespaces
|
402
|
-
|
403
|
-
If having a file per namespace value isn't your thing, you can inline your
|
404
|
-
namespaces. Taking the example from above, rather than having `settings.yml`,
|
405
|
-
`settings-development.yml`, `settings-test.yml`, `settings-staging.yml` and
|
406
|
-
`settings-production.yml`, you could do something like this:
|
407
|
-
|
408
|
-
```yaml
|
409
|
-
# settings.yml
|
410
|
-
|
411
|
-
development:
|
412
|
-
smtp:
|
413
|
-
username: my_development_username
|
414
|
-
password: my_development_password`
|
415
|
-
|
416
|
-
test:
|
417
|
-
smtp:
|
418
|
-
username: my_test_username
|
419
|
-
password: my_test_password`
|
420
|
-
|
421
|
-
staging:
|
422
|
-
smtp:
|
423
|
-
username: my_staging_username
|
424
|
-
password: my_staging_password`
|
425
|
-
|
426
|
-
production:
|
427
|
-
smtp:
|
428
|
-
username: my_production_username
|
429
|
-
password: my_production_password`
|
430
|
-
```
|
431
|
-
|
432
|
-
You can even mix and match.
|
433
|
-
|
434
|
-
```yaml
|
435
|
-
# settings.yml
|
436
|
-
|
437
|
-
development:
|
438
|
-
smtp:
|
439
|
-
username: my_development_username
|
440
|
-
password: my_development_password`
|
441
|
-
|
442
|
-
test:
|
443
|
-
smtp:
|
444
|
-
username: my_test_username
|
445
|
-
password: my_test_password`
|
446
|
-
|
447
|
-
staging:
|
448
|
-
smtp:
|
449
|
-
username: my_staging_username
|
450
|
-
password: my_staging_password`
|
451
|
-
```
|
452
|
-
|
453
|
-
```yaml
|
454
|
-
# settings-production.yml
|
455
|
-
|
456
|
-
smtp:
|
457
|
-
username: my_production_username
|
458
|
-
password: my_production_password`
|
459
|
-
````
|
460
|
-
|
461
|
-
The above will yield the same results, but allows you to keep the production
|
462
|
-
values in a separate file which can be secured separately. Although I would
|
463
|
-
recommend keeping everything together and just [encrpyting your sensitive
|
464
|
-
info](#securing-your-settings)
|
465
|
-
|
466
|
-
If you would like to have items shared among namespaces, you can easily use
|
467
|
-
YAML's built-in merge functionality to do that for you:
|
468
|
-
|
469
|
-
```yaml
|
470
|
-
# settings.yml
|
471
|
-
|
472
|
-
default: &default
|
473
|
-
smtp:
|
474
|
-
headers:
|
475
|
-
X-MYAPP-NAME: My Application Name
|
476
|
-
X-MYAPP-STUFF: Other Stuff
|
477
|
-
|
478
|
-
development:
|
479
|
-
<<: *default
|
480
|
-
smtp:
|
481
|
-
username: my_development_username
|
482
|
-
password: my_development_password`
|
483
|
-
|
484
|
-
test:
|
485
|
-
<<: *default
|
486
|
-
smtp:
|
487
|
-
username: my_test_username
|
488
|
-
password: my_test_password`
|
489
|
-
|
490
|
-
staging:
|
491
|
-
<<: *default
|
492
|
-
smtp:
|
493
|
-
username: my_staging_username
|
494
|
-
password: my_staging_password`
|
495
|
-
```
|
496
|
-
|
497
|
-
#### Multiple Namespaces
|
498
|
-
|
499
|
-
Multiple namespaces can be defined by passing multiple items to the loader:
|
500
|
-
|
501
|
-
```ruby
|
502
|
-
Chamber.load( :basepath => Rails.root.join('config'),
|
503
|
-
:namespaces => {
|
504
|
-
:environment => ::Rails.env,
|
505
|
-
:hostname => ENV['HOST'] } )
|
506
|
-
```
|
507
|
-
|
508
|
-
When accessed within the `test` environment on a system named `tumbleweed`, it
|
509
|
-
will load the following files in the following order:
|
510
|
-
|
511
|
-
* `settings.yml`
|
512
|
-
* `settings-test.yml`
|
513
|
-
* `settings-tumbleweed.yml`
|
514
|
-
|
515
|
-
If a file does not exist, it is skipped.
|
516
|
-
|
517
|
-
#### What Happens With Duplicate Entries?
|
518
|
-
|
519
|
-
Similarly named settings in later files can override settings defined in earlier
|
520
|
-
files.
|
521
|
-
|
522
|
-
If `settings.yml` contains a value:
|
523
|
-
|
524
|
-
```yaml
|
525
|
-
smtp:
|
526
|
-
server: "generalserver.com"
|
527
|
-
```
|
528
|
-
|
529
|
-
And then `settings-test.yml` contains this:
|
530
|
-
|
531
|
-
```yaml
|
532
|
-
smtp:
|
533
|
-
server: "testserver.com"
|
534
|
-
```
|
535
|
-
|
536
|
-
The when you access the value with `Chamber[:smtp][:server]` you will receive
|
537
|
-
`testserver.com`.
|
538
|
-
|
539
|
-
### Outputting Your Settings
|
540
|
-
|
541
|
-
Chamber makes it dead simple to output your environment settings in a variety of
|
542
|
-
formats.
|
543
|
-
|
544
|
-
The simplest is:
|
545
|
-
|
546
|
-
```ruby
|
547
|
-
Chamber.to_s
|
548
|
-
# => MY_SETTING="my value" MY_OTHER_SETTING="my other value"
|
549
|
-
```
|
550
|
-
|
551
|
-
But you can pass other options to customize the string:
|
552
|
-
|
553
|
-
* `pair_separator`
|
554
|
-
* `value_surrounder`
|
555
|
-
* `name_value_separator`
|
556
|
-
|
557
|
-
```ruby
|
558
|
-
Chamber.to_s pair_separator: "\n",
|
559
|
-
value_surrounder: "'",
|
560
|
-
name_value_separator: ': '
|
561
|
-
|
562
|
-
# => MY_SETTING: 'my value'
|
563
|
-
# => MY_OTHER_SETTING: 'my other value'
|
564
|
-
```
|
565
|
-
|
566
|
-
### The chamber Command Line App
|
567
|
-
|
568
|
-
Chamber provides a flexible binary that you can use to make working with your
|
569
|
-
configurations easier. Let's take a look:
|
570
|
-
|
571
|
-
#### Common Options
|
572
|
-
|
573
|
-
Each of the commands described below takes a few common options.
|
574
|
-
|
575
|
-
* `--preset` (or `-p`): Allows you to quickly set the basepath, files and/or
|
576
|
-
namespaces for a given situation (eg working with a Rails app).
|
577
|
-
|
578
|
-
**Example:** `--preset=rails`
|
579
|
-
|
580
|
-
* `--rootpath` (or `-r`): Allows you to quickly set the rootpath of the
|
581
|
-
application. By default this is the directory that the `chamber` executable is
|
582
|
-
run from.
|
583
|
-
|
584
|
-
**Example:** `--rootpath=/path/to/my/application`
|
585
|
-
|
586
|
-
* `--basepath` (or `-b`): Sets the base path that Chamber will use to look for
|
587
|
-
its [common settings files](#convention-over-configuration).
|
588
|
-
|
589
|
-
**Example:** `--basepath=/path/to/my/application`
|
590
|
-
|
591
|
-
* `--files` (or `-f`): Allows you to specifically set the file patterns that
|
592
|
-
Chamber should look at in determining where to load settings information from.
|
593
|
-
|
594
|
-
**Example:** `--files=/path/to/my/application/secret.yml /path/to/my/application/settings/*.yml`
|
595
|
-
|
596
|
-
* `--namespaces` (or `-n`): The namespace values which will be considered for
|
597
|
-
loading settings files.
|
598
|
-
|
599
|
-
**Example:** `--namespaces=development tumbleweed`
|
600
|
-
|
601
|
-
* `--encryption-key`: The path to the key which will be used for encryption.
|
602
|
-
This is optional unless you need to secure any settings.
|
603
|
-
|
604
|
-
Additionally you may pass in the actual contents of the key for this option.
|
605
|
-
|
606
|
-
**Example:** `--keypair=/path/to/my/app/my_project_rsa.pub`
|
607
|
-
|
608
|
-
* `--decryption-key`: The path to the key which will be used for decryption.
|
609
|
-
This is optional unless you need to decrypt any settings.
|
610
|
-
|
611
|
-
Additionally you may pass in the actual contents of the key for this option.
|
612
|
-
|
613
|
-
**Example:** `--keypair=/path/to/my/app/my_project_rsa`
|
614
|
-
|
615
|
-
_**Note:** `--basepath` and `--files` are mutually exclusive. `--files` will
|
616
|
-
always take precedence._
|
617
|
-
|
618
|
-
#### Somewhat Common Options
|
619
|
-
|
620
|
-
_**Note:** Only select commands support the following options. Use `chamber help
|
621
|
-
SUBCOMMAND` to verify if a particular command does._
|
622
|
-
|
623
|
-
* `--dry-run` (or `-d`): The command will not actually execute, but will show
|
624
|
-
you a summary of what *would* have happened.
|
625
|
-
|
626
|
-
**Example:** `--dry-run`
|
627
|
-
|
628
|
-
* `--only-secured` (or `-o`): This is the default. Because most systems have no
|
629
|
-
issues reading from the config files you have stored in your repo, there is no
|
630
|
-
need to process *all* of your settings. So by default, Chamber will only
|
631
|
-
convert, push, etc those settings which have been gitignored or those which
|
632
|
-
have been encrpyted.
|
633
|
-
|
634
|
-
To process everything, use the `--skip-secure-only` flag.
|
635
|
-
|
636
|
-
**Example:** `--secure-only`, `--skip-secure-only`
|
637
|
-
|
638
|
-
#### Settings
|
639
|
-
|
640
|
-
##### Settings Commands
|
641
|
-
|
642
|
-
###### Show
|
643
|
-
|
644
|
-
Gives users an easy way of looking at all of the settings that Chamber knows
|
645
|
-
about for a given context. It will be output as a hash of hashes by default.
|
646
|
-
|
647
|
-
* `--as-env`: Instead of outputting the settings as a hash of hashes, convert
|
648
|
-
the settings into environment variable-compatible versions.
|
649
|
-
|
650
|
-
**Example:** `--as-env`
|
651
|
-
|
652
|
-
**Example:** `chamber show --as-env`
|
653
|
-
|
654
|
-
###### Files
|
655
|
-
|
656
|
-
Very useful for troubleshooting, this will output all of the files that
|
657
|
-
Chamber considers relevant based on the given options passed.
|
658
|
-
|
659
|
-
Additionally, the order is significant. Chamber will load settings from the
|
660
|
-
top down so any duplicate items in subsequent entries will override items from
|
661
|
-
previous ones.
|
662
|
-
|
663
|
-
**Example:** `chamber files`
|
664
|
-
|
665
|
-
###### Secure
|
666
|
-
|
667
|
-
Will verify that any items which are marked as secure (eg `_secure_my_setting`)
|
668
|
-
have secure values. If it appears that one does not, the user will be prompted
|
669
|
-
as to whether or not they would like to encrpyt it.
|
670
|
-
|
671
|
-
This command differs from other tasks in that it will process all files that
|
672
|
-
match Chamber's conventions and not just those which match the passed in
|
673
|
-
namespaces.
|
674
|
-
|
675
|
-
**Example:** `chamber secure`
|
676
|
-
|
677
|
-
###### Compare
|
678
|
-
|
679
|
-
Will display a diff of the settings for one set of namespaces vs the settings
|
680
|
-
for a second set of namespaces.
|
681
|
-
|
682
|
-
This is extremely handy if, for example, you would like to see whether the
|
683
|
-
settings you're using for development match up with the settings you're using
|
684
|
-
for production, or if you're setting all of the same settings for any two
|
685
|
-
environments.
|
686
|
-
|
687
|
-
* `--keys-only`: This is the default. When performing a comparison, only the
|
688
|
-
keys will be considered since values between namespaces will often (and
|
689
|
-
should often) be different.
|
690
|
-
|
691
|
-
**Example:** `--keys-only`, `--no-keys-only`
|
692
|
-
|
693
|
-
* `--first`: This is an array of the first set of namespace settings that you
|
694
|
-
would like to compare from. You can list one or more.
|
695
|
-
|
696
|
-
**Example:** `--first=development`, `--first=development my_host_name`
|
697
|
-
|
698
|
-
* `--second`: This is an array of the second set of namespace settings that
|
699
|
-
you would like to compare against that specified by `--first`. You can list
|
700
|
-
one or more.
|
701
|
-
|
702
|
-
**Example:** `--second=staging`, `--second=staging my_host_name`
|
703
|
-
|
704
|
-
**Example:** `chamber compare --first=development --second=staging`
|
705
|
-
|
706
|
-
###### Init
|
707
|
-
|
708
|
-
Init can be used to initialize a new application/project with everything that
|
709
|
-
Chamber needs in order to run properly. This includes:
|
710
|
-
|
711
|
-
* Creating a public/private keypair
|
712
|
-
* Setting the proper permissions on the the newly created keypair
|
713
|
-
* Adding the private key to the gitignore file
|
714
|
-
* Creating a template `settings.yml` file
|
715
|
-
|
716
|
-
**Example:** `chamber init`
|
717
|
-
|
718
|
-
#### Heroku
|
719
|
-
|
720
|
-
As we described above, working with Heroku environment variables is tedious at
|
721
|
-
best. Chamber gives you a few ways to help with that.
|
722
|
-
|
723
|
-
##### Heroku Common Options
|
724
|
-
|
725
|
-
* `--app` (or `-a`): Heroku application name for which you would like to affect
|
726
|
-
its environment variables.
|
727
|
-
|
728
|
-
**Example:** `--app=my-heroku-app-name`
|
729
|
-
|
730
|
-
##### Heroku Commands
|
731
|
-
|
732
|
-
###### Push
|
733
|
-
|
734
|
-
As we described above, this command will take your current settings and push
|
735
|
-
them to Heroku as environment variables that Chamber will be able to
|
736
|
-
understand.
|
737
|
-
|
738
|
-
**Example:** `chamber heroku push --namespaces=production --app=my-heroku-app`
|
739
|
-
|
740
|
-
_**Note:** To see exactly how Chamber sees your settings as environment variables, see
|
741
|
-
the [chamber settings show](#settings-commands) command above._
|
742
|
-
|
743
|
-
###### Pull
|
744
|
-
|
745
|
-
Will display the list of environment variables that you have set on your
|
746
|
-
Heroku instance.
|
747
|
-
|
748
|
-
This is similar to just executing `heroku config --shell` except that you can
|
749
|
-
specify the following option:
|
750
|
-
|
751
|
-
* `--into`: The file which the pulled settings will be copied into. This file
|
752
|
-
*will* be overridden.
|
753
|
-
|
754
|
-
_**Note:** Eventually this will be parsed into YAML that Chamber can load
|
755
|
-
straight away, but for now, it's basically just redirecting the output._
|
756
|
-
|
757
|
-
**Example:** `--into=/path/to/my/app/settings/heroku.config`
|
758
|
-
|
759
|
-
**Example:** `chamber heroku pull --app=my-heroku-app --into=/path/to/my/app/heroku.config`
|
760
|
-
|
761
|
-
###### Diff
|
762
|
-
|
763
|
-
Will use git's diff function to display the difference between what Chamber
|
764
|
-
knows about locally and what Heroku currently has set. This is very handy for
|
765
|
-
knowing what changes may be made if `chamber heroku push` is executed.
|
766
|
-
|
767
|
-
**Example:** `chamber heroku diff --namespaces=production --app=my-heroku-app`
|
768
|
-
|
769
|
-
###### Clear
|
770
|
-
|
771
|
-
Will remove any environment variables from Heroku that Chamber knows about.
|
772
|
-
This is useful for clearing out Chamber-related settings without touching
|
773
|
-
Heroku addon-specific items.
|
774
|
-
|
775
|
-
**Example:** `chamber heroku clear --namespaces=production --app=my-heroku-app`
|
776
|
-
|
777
|
-
#### Travis CI
|
778
|
-
|
779
|
-
##### Travis Commands
|
780
|
-
|
781
|
-
###### Secure
|
782
|
-
|
783
|
-
Travis CI allows you to use the public key on your Travis repo to encrypt items
|
784
|
-
as environment variables which you would like for Travis to be able to have
|
785
|
-
access to, but which you wouldn't necessarily want to be in plain text inside of
|
786
|
-
your repo.
|
787
|
-
|
788
|
-
This command takes the settings that Chamber knows about, encrypts them, and
|
789
|
-
puts them inside of your .travis.yml at which point they can be safely
|
790
|
-
committed.
|
791
|
-
|
792
|
-
_**Warning:** This will delete *all* of your previous 'secure' entries under
|
793
|
-
'env.global' in your .travis.yml file._
|
794
|
-
|
795
|
-
**Example:** `chamber travis secure --namespaces=continuous_integration`
|
796
|
-
|
797
|
-
### Basic Boolean Conversion
|
798
|
-
|
799
|
-
One of the things that is a huge pain when dealing with environment variables is
|
800
|
-
that they can only be strings. Unfortunately this is kind of a problem for
|
801
|
-
settings which you would like to use to set whether a specific item is enabled
|
802
|
-
or disabled. Because this:
|
803
|
-
|
804
|
-
```yaml
|
805
|
-
# settings.yml
|
806
|
-
|
807
|
-
my_feature:
|
808
|
-
enabled: false
|
809
|
-
```
|
810
|
-
|
811
|
-
```ruby
|
812
|
-
if Chamber.env.my_feature.enabled?
|
813
|
-
# Do stuff with my feature
|
814
|
-
end
|
815
|
-
```
|
816
|
-
|
817
|
-
Now because environment variables are always strings, `false` becomes `'false'`.
|
818
|
-
And because, as far as Ruby is concerned, any `String` is `true`, `enabled?`
|
819
|
-
would return `true`. Now, you could completely omit the `enabled` key, however
|
820
|
-
this causes issues if you would like to audit your settings (say for each
|
821
|
-
environment) to make sure they are all the same. Some will have the `enabled`
|
822
|
-
setting and some will not, which will give you false positives.
|
823
|
-
|
824
|
-
You could work around it by doing this:
|
825
|
-
|
826
|
-
```ruby
|
827
|
-
if Chamber.env.my_feature.enabled == 'true'
|
828
|
-
# Do stuff with my feature
|
829
|
-
end
|
830
|
-
```
|
831
|
-
|
832
|
-
but that looks awful and isn't very idiomatic.
|
833
|
-
|
834
|
-
To solve this problem, Chamber reviews all of your settings values and, if they
|
835
|
-
are any of the following exact strings (case insensitive):
|
836
|
-
|
837
|
-
* 'false'
|
838
|
-
* 'f'
|
839
|
-
* 'no'
|
840
|
-
* 'true'
|
841
|
-
* 't'
|
842
|
-
* 'yes'
|
843
|
-
|
844
|
-
The value will be converted to the proper Boolean value. In which case the
|
845
|
-
above `Chamber.env.my_feature.enabled?` will work as expected and your
|
846
|
-
environment audit will pass.
|
847
|
-
|
848
|
-
### In Order to Add Advanced Functionality
|
849
|
-
|
850
|
-
In any case that you need to set configuration options or do advanced post
|
851
|
-
processing on your YAML data, you'll want to create your own object for
|
852
|
-
accessing it. Don't worry, Chamber will take you 98% of the way there.
|
853
|
-
|
854
|
-
Just include it like so:
|
855
|
-
|
856
|
-
```ruby
|
857
|
-
class Settings
|
858
|
-
extend Chamber
|
859
|
-
end
|
860
|
-
```
|
861
|
-
|
862
|
-
Now, rather than using `Chamber[:application_host]` to access your
|
863
|
-
environment, you can simply use `Settings[:application_host]`.
|
864
|
-
|
865
|
-
## Best Practices
|
866
|
-
|
867
|
-
### Organizing Your Settings
|
868
|
-
|
869
|
-
We recommend starting with a single `settings.yml` file. Once this file begins
|
870
|
-
to become too unwieldy, you can begin to extract common options (let's say SMTP
|
871
|
-
settings) into another file (perhaps `settings/smtp.yml`).
|
872
|
-
|
873
|
-
### Full Example
|
874
|
-
|
875
|
-
Let's walk through how you might use Chamber to configure your SMTP settings:
|
876
|
-
|
877
|
-
```yaml
|
878
|
-
# config/settings.yml
|
879
|
-
|
880
|
-
stuff:
|
881
|
-
not: "Not Related to SMTP"
|
882
|
-
```
|
883
|
-
|
884
|
-
```yaml
|
885
|
-
# config/settings/smtp.yml
|
886
|
-
|
887
|
-
default: &shared
|
888
|
-
smtp:
|
889
|
-
headers:
|
890
|
-
X-MYAPP-NAME: My Application Name
|
891
|
-
X-MYAPP-STUFF: Other Stuff
|
892
|
-
|
893
|
-
development:
|
894
|
-
<<: *shared
|
895
|
-
smtp:
|
896
|
-
username: my_dev_user
|
897
|
-
password: my_dev_password
|
898
|
-
|
899
|
-
staging:
|
900
|
-
<<: *shared
|
901
|
-
smtp:
|
902
|
-
_secure_username: my_staging_user
|
903
|
-
_secure_password: my_staging_password
|
904
|
-
|
905
|
-
production:
|
906
|
-
<<: *shared
|
907
|
-
smtp:
|
908
|
-
_secure_username: my_production_user
|
909
|
-
_secure_password: my_production_password
|
910
|
-
```
|
911
|
-
|
912
|
-
Now, assuming you're running in staging, you can access both `username` and
|
913
|
-
`headers` off of `smtp` like so:
|
914
|
-
|
915
|
-
```ruby
|
916
|
-
Chamber[:smtp][:headers]
|
917
|
-
# => { X-MYAPP-NAME: 'My Application Name', X-MYAPP-STUFF: 'Other Stuff' }
|
918
|
-
|
919
|
-
Chamber[:smtp][:username]
|
920
|
-
# => my_staging_username
|
921
|
-
|
922
|
-
Chamber[:smtp][:password]
|
923
|
-
# => my_staging_password
|
924
|
-
```
|
925
|
-
|
926
|
-
## Alternatives
|
927
|
-
|
928
|
-
* [dotenv](https://github.com/bkeepers/dotenv)
|
929
|
-
* [figaro](https://github.com/laserlemon/figaro)
|
930
|
-
* [idkfa](https://github.com/bendyworks/idkfa)
|
931
|
-
* [settingslogic](https://github.com/binarylogic/settingslogic)
|
932
|
-
|
933
|
-
## Thanks
|
934
|
-
|
935
|
-
Special thanks to all those gem authors above @binarylogic, @bendyworks,
|
936
|
-
@laserlemon and @bkeepers. They gave us the inspiration to write this gem and
|
937
|
-
we would have made a lot more mistakes without them paving the way. Thanks all!
|
26
|
+
1. Thou shalt be [well documented](https://github.com/thekompanee/chamber/wiki/) with full test coverage
|
27
|
+
1. Thou shalt not have to worry about [accidentally committing secure settings](https://github.com/thekompanee/chamber/wiki/Git-Commit-Hook)
|
938
28
|
|
939
|
-
##
|
29
|
+
## Full Reference
|
940
30
|
|
941
|
-
|
942
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
943
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
944
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
945
|
-
5. Create new Pull Request
|
31
|
+
Visit the [wiki](https://github.com/thekompanee/chamber/wiki)
|