chamber 1.0.3 → 2.0.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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +288 -173
  3. data/bin/chamber +2 -288
  4. data/lib/chamber.rb +19 -67
  5. data/lib/chamber/binary/heroku.rb +59 -0
  6. data/lib/chamber/binary/runner.rb +94 -0
  7. data/lib/chamber/binary/travis.rb +23 -0
  8. data/lib/chamber/commands/base.rb +33 -0
  9. data/lib/chamber/commands/comparable.rb +37 -0
  10. data/lib/chamber/commands/compare.rb +46 -0
  11. data/lib/chamber/commands/context_resolver.rb +72 -0
  12. data/lib/chamber/commands/files.rb +12 -0
  13. data/lib/chamber/commands/heroku.rb +30 -0
  14. data/lib/chamber/commands/heroku/clear.rb +25 -0
  15. data/lib/chamber/commands/heroku/compare.rb +31 -0
  16. data/lib/chamber/commands/heroku/pull.rb +30 -0
  17. data/lib/chamber/commands/heroku/push.rb +25 -0
  18. data/lib/chamber/commands/initialize.rb +73 -0
  19. data/lib/chamber/commands/securable.rb +48 -0
  20. data/lib/chamber/commands/secure.rb +16 -0
  21. data/lib/chamber/commands/show.rb +23 -0
  22. data/lib/chamber/commands/travis.rb +14 -0
  23. data/lib/chamber/commands/travis/secure.rb +35 -0
  24. data/lib/chamber/configuration.rb +34 -0
  25. data/lib/chamber/environmentable.rb +23 -0
  26. data/lib/chamber/errors/undecryptable_value_error.rb +6 -0
  27. data/lib/chamber/file.rb +17 -5
  28. data/lib/chamber/file_set.rb +18 -12
  29. data/lib/chamber/filters/boolean_conversion_filter.rb +41 -0
  30. data/lib/chamber/filters/decryption_filter.rb +69 -0
  31. data/lib/chamber/filters/encryption_filter.rb +57 -0
  32. data/lib/chamber/filters/environment_filter.rb +75 -0
  33. data/lib/chamber/filters/namespace_filter.rb +37 -0
  34. data/lib/chamber/filters/secure_filter.rb +39 -0
  35. data/lib/chamber/instance.rb +40 -0
  36. data/lib/chamber/namespace_set.rb +55 -16
  37. data/lib/chamber/rails/railtie.rb +1 -1
  38. data/lib/chamber/settings.rb +103 -42
  39. data/lib/chamber/system_environment.rb +3 -93
  40. data/lib/chamber/version.rb +2 -2
  41. data/spec/fixtures/settings.yml +27 -0
  42. data/spec/lib/chamber/commands/context_resolver_spec.rb +106 -0
  43. data/spec/lib/chamber/commands/files_spec.rb +19 -0
  44. data/spec/lib/chamber/commands/heroku/clear_spec.rb +11 -0
  45. data/spec/lib/chamber/commands/heroku/compare_spec.rb +11 -0
  46. data/spec/lib/chamber/commands/heroku/pull_spec.rb +11 -0
  47. data/spec/lib/chamber/commands/heroku/push_spec.rb +11 -0
  48. data/spec/lib/chamber/commands/secure_spec.rb +29 -0
  49. data/spec/lib/chamber/commands/show_spec.rb +43 -0
  50. data/spec/lib/chamber/file_set_spec.rb +1 -1
  51. data/spec/lib/chamber/file_spec.rb +32 -9
  52. data/spec/lib/chamber/filters/boolean_conversion_filter_spec.rb +44 -0
  53. data/spec/lib/chamber/filters/decryption_filter_spec.rb +55 -0
  54. data/spec/lib/chamber/filters/encryption_filter_spec.rb +48 -0
  55. data/spec/lib/chamber/filters/environment_filter_spec.rb +35 -0
  56. data/spec/lib/chamber/filters/namespace_filter_spec.rb +73 -0
  57. data/spec/lib/chamber/filters/secure_filter_spec.rb +36 -0
  58. data/spec/lib/chamber/namespace_set_spec.rb +61 -18
  59. data/spec/lib/chamber/settings_spec.rb +99 -23
  60. data/spec/lib/chamber/system_environment_spec.rb +1 -71
  61. data/spec/lib/chamber_spec.rb +40 -26
  62. data/spec/rails-2-test/config.ru +0 -0
  63. data/spec/rails-2-test/config/application.rb +5 -0
  64. data/spec/rails-2-test/script/console +0 -0
  65. data/spec/rails-3-test/config.ru +0 -0
  66. data/spec/rails-3-test/config/application.rb +5 -0
  67. data/spec/rails-3-test/script/rails +0 -0
  68. data/spec/rails-4-test/bin/rails +0 -0
  69. data/spec/rails-4-test/config.ru +0 -0
  70. data/spec/rails-4-test/config/application.rb +5 -0
  71. data/spec/spec_key +27 -0
  72. data/spec/spec_key.pub +9 -0
  73. metadata +85 -4
data/bin/chamber CHANGED
@@ -1,291 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'pp'
4
- require 'thor'
5
- require 'bundler'
6
- require 'chamber'
7
- require 'yaml'
8
- require 'tempfile'
3
+ require 'chamber/binary/runner'
9
4
 
10
- class Chamber
11
- module Commands
12
- class Heroku < Thor
13
- class_option :app,
14
- type: :string,
15
- aliases: '-a',
16
- desc: 'The name of the Heroku application whose config values will be affected'
17
-
18
- desc 'clear', 'Removes all Heroku environment variables which match settings that Chamber knows about'
19
- method_option :dry_run,
20
- type: :boolean,
21
- aliases: '-d',
22
- desc: 'Does not actually remove anything, but instead displays what would change if cleared'
23
- def clear
24
- ::Chamber::Commands::Chamber.init(options)
25
-
26
- keys = ::Chamber.to_environment.keys
27
-
28
- if options[:dry_run]
29
- puts "Running without --dry-run will remove the following Heroku environment variables"
30
-
31
- keys_regex = keys.join('|')
32
- current_heroku_config = heroku("config --shell")
33
-
34
- current_heroku_config.each_line do |line|
35
- puts line if line.match(keys_regex)
36
- end
37
- else
38
- puts heroku("config:unset #{keys.join(' ')}")
39
- end
40
- end
41
-
42
- desc 'push', 'Sends settings to Heroku so that they may be used in the application once it is deployed'
43
- method_option :dry_run,
44
- type: :boolean,
45
- aliases: '-d',
46
- desc: 'Does not actually push anything to Heroku, but instead displays what would change if pushed'
47
- method_option :only_ignored,
48
- type: :boolean,
49
- aliases: '-o',
50
- default: true,
51
- desc: 'Does not push settings up to Heroku unless the file that the setting is contained in has been gitignored'
52
- def push
53
- ::Chamber::Commands::Chamber.init(options)
54
-
55
- if options[:only_ignored]
56
- ignored_settings_files = `git ls-files --other --ignored --exclude-from=.gitignore | sed -e "s|^|${PWD}/|" | grep --colour=never -E '#{::Chamber.filenames.join('|')}'`
57
-
58
- ::Chamber.load files: ignored_settings_files.split("\n"),
59
- namespaces: options[:namespaces]
60
- end
61
-
62
- if options[:dry_run]
63
- puts "Running without --dry-run will set the following Heroku environment variables"
64
-
65
- puts ::Chamber.to_s(pair_separator: "\n")
66
- else
67
- heroku("config:set #{::Chamber.to_s}")
68
- end
69
- end
70
-
71
- desc 'pull', 'Retrieves the environment variables for the application and stores them in a temporary file'
72
- method_option :into,
73
- type: :string,
74
- desc: 'The file into which the Heroku config information should be stored. This file WILL BE OVERRIDDEN.'
75
- def pull
76
- current_heroku_config = heroku("config --shell")
77
-
78
- if options[:into]
79
- ::File.open(options[:into], 'w+') do |file|
80
- file.write current_heroku_config
81
- end
82
- else
83
- puts current_heroku_config
84
- end
85
- end
86
-
87
- desc 'diff', 'Displays the difference between what is currently stored in the Heroku application\'s config and what Chamber knows about locally'
88
- method_option :only_ignored,
89
- type: :boolean,
90
- aliases: '-o',
91
- default: true,
92
- desc: 'When enabled, the diff will only consider settings contained in files which have been gitignored, the rest will be accessed directly'
93
- def diff
94
- ::Chamber::Commands::Chamber.init(options)
95
-
96
- if options[:only_ignored]
97
- ignored_settings_files = `git ls-files --other --ignored --exclude-from=.gitignore | sed -e "s|^|${PWD}/|" | grep --colour=never -E '#{::Chamber.filenames.join('|')}'`
98
-
99
- ::Chamber.load files: ignored_settings_files.split("\n"),
100
- namespaces: options[:namespaces]
101
- end
102
-
103
- current_heroku_config = heroku("config --shell")
104
- current_local_config = ::Chamber.to_s(pair_separator: "\n",
105
- value_surrounder: '')
106
-
107
- heroku_config_file = Tempfile.open('heroku') do |file|
108
- file.write current_heroku_config.chomp
109
- file.to_path
110
- end
111
- local_config_file = Tempfile.open('local') do |file|
112
- file.write current_local_config
113
- file.to_path
114
- end
115
-
116
- system("git diff --no-index #{local_config_file} #{heroku_config_file}")
117
- end
118
-
119
- no_commands do
120
- def app
121
- options[:app] ? " --app #{options[:app]}" : ""
122
- end
123
-
124
- def heroku(command)
125
- Bundler.with_clean_env { `heroku #{command}#{app}` }
126
- end
127
- end
128
- end
129
-
130
- class Travis < Thor
131
- desc 'secure', 'Uses your Travis CI public key to encrypt the settings you have chosen not to commit to the repo'
132
- method_option :dry_run,
133
- type: :boolean,
134
- aliases: '-d',
135
- desc: 'Does not actually encrypt anything to .travis.yml, but instead displays what values would be encrypted'
136
- method_option :only_ignored,
137
- type: :boolean,
138
- aliases: '-o',
139
- default: true,
140
- desc: 'Does not encrpyt settings into .travis.yml unless the file that the setting is contained in has been gitignored'
141
- def secure
142
- ::Chamber::Commands::Chamber.init(options)
143
-
144
- if options[:only_ignored]
145
- ignored_settings_files = `git ls-files --other --ignored --exclude-from=.gitignore | sed -e "s|^|${PWD}/|" | grep --colour=never -E '#{::Chamber.filenames.join('|')}'`
146
-
147
- ::Chamber.load files: ignored_settings_files.split("\n"),
148
- namespaces: options[:namespaces]
149
- end
150
-
151
- setting_values = ::Chamber.to_s(pair_separator: "\n")
152
-
153
- if options[:dry_run]
154
- puts "Running without --dry-run will encrypt the following Travis CI environment variables"
155
-
156
- puts setting_values
157
- else
158
- travis_encrypt('--override ryterutoiuewrtoiuweorit="invalid"')
159
-
160
- setting_values.each_line do |line|
161
- puts "Encrypting: #{line}"
162
- travis_encrypt("--append #{line}")
163
- end
164
- end
165
- end
166
-
167
- no_commands do
168
- def travis_encrypt(command)
169
- Bundler.with_clean_env { `travis encrypt --add 'env.global' #{command}` }
170
- end
171
- end
172
- end
173
-
174
- class Settings < Thor
175
- desc 'show', 'Displays the list of settings and their values'
176
- method_option :as_env,
177
- type: :boolean,
178
- aliases: '-e',
179
- desc: 'Whether the displayed settings should be environment variable compatible'
180
- def show
181
- ::Chamber::Commands::Chamber.init(options)
182
-
183
- if options[:as_env]
184
- puts ::Chamber.to_s(pair_separator: "\n")
185
- else
186
- pp ::Chamber.to_hash
187
- end
188
- end
189
-
190
- desc 'files', 'Lists the settings files which are parsed with the given options'
191
- def files
192
- ::Chamber::Commands::Chamber.init(options)
193
-
194
- pp ::Chamber.filenames
195
- end
196
-
197
- desc 'compare', 'Displays the difference between what is currently stored in the Heroku application\'s config and what Chamber knows about locally'
198
- method_option :keys_only,
199
- type: :boolean,
200
- default: true,
201
- desc: 'Whether or not to only compare the keys but not the values of the two sets of settings'
202
- method_option :first,
203
- type: :array,
204
- desc: 'The list of namespaces which will be used as the source of the comparison'
205
- method_option :second,
206
- type: :array,
207
- desc: 'The list of namespaces which will be used as the destination of the comparison'
208
- def compare
209
- ::Chamber::Commands::Chamber.init(options)
210
-
211
- ::Chamber.load basepath: options[:basepath],
212
- files: options[:files],
213
- namespaces: options[:first]
214
-
215
- first_config = if options[:keys_only]
216
- ::Chamber.to_environment.keys.join("\n")
217
- else
218
- ::Chamber.to_s(pair_separator: "\n")
219
- end
220
-
221
- ::Chamber.load basepath: options[:basepath],
222
- files: options[:files],
223
- namespaces: options[:second]
224
-
225
- second_config = if options[:keys_only]
226
- ::Chamber.to_environment.keys.join("\n")
227
- else
228
- ::Chamber.to_s(pair_separator: "\n")
229
- end
230
-
231
- first_config_file = Tempfile.open('first') do |file|
232
- file.write first_config
233
- file.to_path
234
- end
235
- second_config_file = Tempfile.open('second') do |file|
236
- file.write second_config
237
- file.to_path
238
- end
239
-
240
- system("git diff --no-index #{first_config_file} #{second_config_file}")
241
- end
242
- end
243
-
244
- class Chamber < Thor
245
- class_option :basepath,
246
- type: :string,
247
- aliases: '-b',
248
- desc: 'The base filepath where Chamber will look for the conventional settings files'
249
- class_option :files,
250
- type: :array,
251
- aliases: '-f',
252
- desc: 'The set of file globs that Chamber will use for processing'
253
- class_option :namespaces,
254
- type: :array,
255
- aliases: '-n',
256
- default: [],
257
- desc: 'The set of namespaces that Chamber will use for processing'
258
- class_option :preset,
259
- type: :string,
260
- aliases: '-p',
261
- enum: ['rails'],
262
- desc: 'Used to quickly assign a given scenario to the chamber command (eg Rails apps)'
263
-
264
- desc 'settings SUBCOMMAND ...ARGS', 'For working with Chamber settings'
265
- subcommand 'settings', ::Chamber::Commands::Settings
266
-
267
- desc 'travis SUBCOMMAND ...ARGS', 'For manipulating Travis CI environment variables'
268
- subcommand 'travis', ::Chamber::Commands::Travis
269
-
270
- desc 'heroku SUBCOMMAND ...ARGS', 'For manipulating Heroku environment variables'
271
- subcommand 'heroku', ::Chamber::Commands::Heroku
272
-
273
- no_commands do
274
- def self.init(options)
275
- if options[:preset] == 'rails'
276
- require ::File.expand_path('./config/application')
277
-
278
- options[:basepath] = Rails.root.join('config')
279
- options[:namespaces] = options[:namespaces].empty? ? [Rails.env] : options[:namespaces]
280
- end
281
-
282
- ::Chamber.load basepath: options[:basepath],
283
- files: options[:files],
284
- namespaces: options[:namespaces]
285
- end
286
- end
287
- end
288
- end
289
- end
290
-
291
- Chamber::Commands::Chamber.start
5
+ Chamber::Binary::Runner.start
data/lib/chamber.rb CHANGED
@@ -1,88 +1,40 @@
1
- require 'singleton'
2
- require 'forwardable'
3
- require 'chamber/file_set'
1
+ require 'chamber/instance'
4
2
  require 'chamber/rails'
5
3
 
6
- class Chamber
7
- include Singleton
4
+ module Chamber
5
+ extend self
8
6
 
9
- class << self
10
- extend Forwardable
11
-
12
- def_delegators :instance, :[],
13
- :basepath,
14
- :load,
15
- :filenames,
16
- :namespaces,
17
- :settings,
18
- :to_environment,
19
- :to_hash,
20
- :to_s
21
-
22
- alias_method :env, :instance
23
- end
24
-
25
- attr_accessor :basepath,
26
- :files
27
-
28
- def load(options)
29
- self.settings = nil
30
- self.basepath = options[:basepath] || ''
31
- file_patterns = options[:files] || [
32
- self.basepath + 'credentials*.yml',
33
- self.basepath + 'settings*.yml',
34
- self.basepath + 'settings' ]
35
- self.files = FileSet.new files: file_patterns,
36
- namespaces: options.fetch(:namespaces, {})
7
+ def load(options = {})
8
+ self.instance = Instance.new(options)
37
9
  end
38
10
 
39
- def filenames
40
- self.files.filenames
11
+ def to_s(options = {})
12
+ instance.to_s(options)
41
13
  end
42
14
 
43
- def namespaces
44
- settings.namespaces
15
+ def env
16
+ instance.settings
45
17
  end
46
18
 
47
- def settings
48
- @settings ||= -> do
49
- @settings = Settings.new
19
+ protected
50
20
 
51
- files.to_settings do |parsed_settings|
52
- @settings.merge! parsed_settings
53
- end
21
+ def instance
22
+ @@instance ||= Instance.new({})
23
+ end
54
24
 
55
- @settings
56
- end.call
25
+ def instance=(new_instance)
26
+ @@instance = new_instance
57
27
  end
58
28
 
29
+ public
30
+
59
31
  def method_missing(name, *args)
60
- if settings.respond_to?(name)
61
- return settings.public_send(name, *args)
62
- end
32
+ return instance.public_send(name, *args) if instance.respond_to?(name)
63
33
 
64
34
  super
65
35
  end
66
36
 
67
37
  def respond_to_missing?(name, include_private = false)
68
- settings.respond_to?(name, include_private)
69
- end
70
-
71
- def to_s(*args)
72
- settings.to_s(*args)
73
- end
74
-
75
- protected
76
-
77
- attr_writer :settings
78
-
79
- def files
80
- @files ||= FileSet.new files: []
81
- end
82
-
83
- private
84
-
85
- def basepath=(pathlike)
86
- @basepath = pathlike == '' ? '' : Pathname.new(::File.expand_path(pathlike))
38
+ instance.respond_to?(name, include_private)
87
39
  end
88
40
  end
@@ -0,0 +1,59 @@
1
+ require 'thor'
2
+ require 'chamber/commands/heroku/clear'
3
+ require 'chamber/commands/heroku/push'
4
+ require 'chamber/commands/heroku/pull'
5
+ require 'chamber/commands/heroku/compare'
6
+
7
+ module Chamber
8
+ module Binary
9
+ class Heroku < Thor
10
+
11
+ class_option :app,
12
+ type: :string,
13
+ aliases: '-a',
14
+ required: true,
15
+ desc: 'The name of the Heroku application whose config values will be affected'
16
+
17
+ desc 'clear', 'Removes all Heroku environment variables which match settings that Chamber knows about'
18
+ method_option :dry_run,
19
+ type: :boolean,
20
+ aliases: '-d',
21
+ desc: 'Does not actually remove anything, but instead displays what would change if cleared'
22
+ def clear
23
+ Commands::Heroku::Clear.call(options)
24
+ end
25
+
26
+ desc 'push', 'Sends settings to Heroku so that they may be used in the application once it is deployed'
27
+ method_option :dry_run,
28
+ type: :boolean,
29
+ aliases: '-d',
30
+ desc: 'Does not actually push anything to Heroku, but instead displays what would change if pushed'
31
+ method_option :only_sensitive,
32
+ type: :boolean,
33
+ aliases: '-o',
34
+ default: true,
35
+ desc: 'When enabled, only settings contained in files which have been gitignored or settings which are marked as "_secure" will be pushed'
36
+ def push
37
+ Commands::Heroku::Push.call(options)
38
+ end
39
+
40
+ desc 'pull', 'Retrieves the environment variables for the application and stores them in a temporary file'
41
+ method_option :into,
42
+ type: :string,
43
+ desc: 'The file into which the Heroku config information should be stored. This file WILL BE OVERRIDDEN.'
44
+ def pull
45
+ puts Commands::Heroku::Pull.call(options)
46
+ end
47
+
48
+ desc 'compare', 'Displays the difference between what is currently stored in the Heroku application\'s config and what Chamber knows about locally'
49
+ method_option :only_sensitive,
50
+ type: :boolean,
51
+ aliases: '-o',
52
+ default: true,
53
+ desc: 'When enabled, the diff will only consider settings contained in files which have been gitignored or settings which are marked as "_secure"'
54
+ def compare
55
+ Commands::Heroku::Compare.call(options)
56
+ end
57
+ end
58
+ end
59
+ end