chamber 2.4.0 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](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)
|