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
@@ -0,0 +1,19 @@
1
+ require 'rspectacular'
2
+ require 'chamber/commands/files'
3
+
4
+ module Chamber
5
+ module Commands
6
+ describe Files do
7
+ let(:rootpath) { ::File.expand_path('./spec/fixtures') }
8
+ let(:options) { { basepath: rootpath,
9
+ rootpath: rootpath } }
10
+
11
+ it 'can return values formatted as environment variables' do
12
+ files = Files.call(options)
13
+
14
+ expect(files.size).to eql 1
15
+ expect(files.first).to include 'spec/fixtures/settings.yml'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ require 'rspectacular'
2
+ require 'chamber/commands/heroku/clear'
3
+
4
+ module Chamber
5
+ module Commands
6
+ module Heroku
7
+ describe Clear do
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'rspectacular'
2
+ require 'chamber/commands/heroku/compare'
3
+
4
+ module Chamber
5
+ module Commands
6
+ module Heroku
7
+ describe Compare do
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'rspectacular'
2
+ require 'chamber/commands/heroku/pull'
3
+
4
+ module Chamber
5
+ module Commands
6
+ module Heroku
7
+ describe Pull do
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'rspectacular'
2
+ require 'chamber/commands/heroku/push'
3
+
4
+ module Chamber
5
+ module Commands
6
+ module Heroku
7
+ describe Push do
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ require 'rspectacular'
2
+ require 'chamber/commands/secure'
3
+
4
+ module Chamber
5
+ module Commands
6
+ describe Secure do
7
+ let(:rootpath) { Pathname.new(::File.expand_path('./spec/fixtures')) }
8
+ let(:settings_filename) { rootpath + 'settings' + 'unencrypted.yml' }
9
+ let(:options) { { basepath: rootpath,
10
+ rootpath: rootpath,
11
+ encryption_key: rootpath + '../spec_key'} }
12
+
13
+ it 'can return values formatted as environment variables' do
14
+ ::File.open(settings_filename, 'w') do |file|
15
+ file.write <<-HEREDOC
16
+ test:
17
+ _secure_my_unencrpyted_setting: hello
18
+ HEREDOC
19
+ end
20
+
21
+ files = Secure.call(options)
22
+
23
+ expect(::File.read(settings_filename)).to match %r{_secure_my_unencrpyted_setting: [A-Za-z0-9\+\/]{342}==}
24
+
25
+ ::File.delete(settings_filename)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,43 @@
1
+ require 'rspectacular'
2
+ require 'chamber/commands/show'
3
+
4
+ module Chamber
5
+ module Commands
6
+ describe Show do
7
+ let(:rootpath) { ::File.expand_path('./spec/fixtures') }
8
+ let(:options) { { basepath: rootpath,
9
+ rootpath: rootpath,
10
+ namespaces: 'test' } }
11
+
12
+ it 'can return values formatted as environment variables' do
13
+ expect(Show.call(options.merge(as_env: true))).to eql(
14
+ <<-HEREDOC.chomp
15
+ ANOTHER_LEVEL_LEVEL_THREE_AN_ARRAY="["item 1", "item 2", "item 3"]"
16
+ ANOTHER_LEVEL_LEVEL_THREE_A_SCALAR="hello"
17
+ ANOTHER_LEVEL_SETTING_ONE="1"
18
+ ANOTHER_LEVEL_SETTING_TWO="2"
19
+ MY_BOOLEAN="false"
20
+ MY_DYNAMIC_SETTING="2"
21
+ MY_SETTING="my_value"
22
+ HEREDOC
23
+ )
24
+ end
25
+
26
+ it 'can return values formatted as a hash' do
27
+ expect(Show.call(options)).to eql(
28
+ <<-HEREDOC.chomp
29
+ {"my_setting"=>"my_value",
30
+ "my_boolean"=>false,
31
+ "my_dynamic_setting"=>2,
32
+ "another_level"=>
33
+ {"setting_one"=>1,
34
+ "setting_two"=>2,
35
+ "level_three"=>
36
+ {"an_array"=>["item 1", "item 2", "item 3"],
37
+ "a_scalar"=>"hello"}}}
38
+ HEREDOC
39
+ )
40
+ end
41
+ end
42
+ end
43
+ end
@@ -3,7 +3,7 @@ require 'chamber/file_set'
3
3
  require 'fileutils'
4
4
 
5
5
 
6
- class Chamber
6
+ module Chamber
7
7
  describe FileSet do
8
8
  before(:each) { FileUtils.mkdir '/tmp/settings' unless ::File.exist? '/tmp/settings' }
9
9
  after(:each) { FileUtils.rm_rf '/tmp/settings' if ::File.exist? '/tmp/settings' }
@@ -1,6 +1,7 @@
1
1
  require 'rspectacular'
2
2
  require 'chamber/file'
3
3
  require 'chamber/settings'
4
+ require 'chamber/filters/encryption_filter'
4
5
  require 'tempfile'
5
6
 
6
7
  def create_tempfile_with_content(content)
@@ -10,7 +11,7 @@ def create_tempfile_with_content(content)
10
11
  tempfile
11
12
  end
12
13
 
13
- class Chamber
14
+ module Chamber
14
15
  describe File do
15
16
  it 'can convert file contents to settings' do
16
17
  tempfile = create_tempfile_with_content %Q({ test: settings })
@@ -23,8 +24,10 @@ describe File do
23
24
 
24
25
  expect(file_settings).to eql :settings
25
26
  expect(Settings).to have_received(:new).
26
- with(settings: {'test' => 'settings'},
27
- namespaces: {})
27
+ with(settings: {'test' => 'settings'},
28
+ namespaces: {},
29
+ decryption_key: nil,
30
+ encryption_key: nil)
28
31
  end
29
32
 
30
33
  it 'can convert a file whose contents are empty' do
@@ -38,8 +41,10 @@ describe File do
38
41
 
39
42
  expect(file_settings).to eql :settings
40
43
  expect(Settings).to have_received(:new).
41
- with(settings: {},
42
- namespaces: {})
44
+ with(settings: {},
45
+ namespaces: {},
46
+ decryption_key: nil,
47
+ encryption_key: nil)
43
48
  end
44
49
 
45
50
  it 'throws an error when the file contents are malformed' do
@@ -62,7 +67,9 @@ describe File do
62
67
  expect(Settings).to have_received(:new).
63
68
  with( settings: {'test' => 'settings'},
64
69
  namespaces: {
65
- environment: :development })
70
+ environment: :development },
71
+ decryption_key: nil,
72
+ encryption_key: nil)
66
73
  end
67
74
 
68
75
  it 'can handle files which contain ERB markup' do
@@ -74,7 +81,9 @@ describe File do
74
81
  settings_file.to_settings
75
82
  expect(Settings).to have_received(:new).
76
83
  with( settings: {'test' => 2},
77
- namespaces: {} )
84
+ namespaces: {},
85
+ decryption_key: nil,
86
+ encryption_key: nil)
78
87
  end
79
88
 
80
89
  it 'does not throw an error when attempting to convert a file which does not exist' do
@@ -87,8 +96,22 @@ describe File do
87
96
 
88
97
  expect(file_settings).to eql :settings
89
98
  expect(Settings).to have_received(:new).
90
- with(settings: {},
91
- namespaces: {})
99
+ with(settings: {},
100
+ namespaces: {},
101
+ decryption_key: nil,
102
+ encryption_key: nil)
103
+ end
104
+
105
+ it 'can securely encrypt the settings contained in a file' do
106
+ tempfile = create_tempfile_with_content %Q({ _secure_setting: hello })
107
+ settings_file = File.new path: tempfile.path,
108
+ encryption_key: './spec/spec_key.pub'
109
+
110
+ settings_file.secure
111
+
112
+ settings_file = File.new path: tempfile.path
113
+
114
+ expect(settings_file.to_settings.send(:raw_data)['_secure_setting']).to match Filters::EncryptionFilter::BASE64_STRING_PATTERN
92
115
  end
93
116
  end
94
117
  end
@@ -0,0 +1,44 @@
1
+ require 'rspectacular'
2
+ require 'chamber/filters/boolean_conversion_filter'
3
+
4
+ module Chamber
5
+ module Filters
6
+ describe BooleanConversionFilter do
7
+ it 'can convert string boolean values into TrueClass and FalseClass even if they are deeply nested' do
8
+ filtered_data = BooleanConversionFilter.execute(
9
+ data: {
10
+ true_boolean: 'true',
11
+ boolean_group: {
12
+ yes_boolean: 'yes',
13
+ t_boolean: 't',
14
+ non_boolean: 'hello',
15
+ sub_boolean_group: {
16
+ false_boolean: 'false',
17
+ no_boolean: 'no',
18
+ nilly: nil,
19
+ non_boolean: 3, },
20
+ f_boolean: 'f',
21
+ non_boolean: Time.utc(2012, 8, 1),
22
+ nilly: nil, },
23
+ false_boolean: 'false',
24
+ non_boolean: [1, 2, 3] })
25
+
26
+ expect(filtered_data).to eql( true_boolean: true,
27
+ boolean_group: {
28
+ yes_boolean: true,
29
+ t_boolean: true,
30
+ non_boolean: 'hello',
31
+ sub_boolean_group: {
32
+ false_boolean: false,
33
+ no_boolean: false,
34
+ nilly: nil,
35
+ non_boolean: 3, },
36
+ f_boolean: false,
37
+ non_boolean: Time.utc(2012, 8, 1),
38
+ nilly: nil, },
39
+ false_boolean: false,
40
+ non_boolean: [1, 2, 3] )
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,55 @@
1
+ require 'rspectacular'
2
+ require 'chamber/filters/decryption_filter'
3
+
4
+ module Chamber
5
+ module Filters
6
+ describe DecryptionFilter do
7
+ it 'will attempt to decrypt values which are marked as "secure"' do
8
+ filtered_settings = DecryptionFilter.execute( data: {
9
+ _secure_my_secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==' },
10
+ decryption_key: './spec/spec_key' )
11
+
12
+ expect(filtered_settings.my_secure_setting).to eql 'hello'
13
+ end
14
+
15
+ it 'will not attempt to decrypt values which are not marked as "secure"' do
16
+ filtered_settings = DecryptionFilter.execute( data: {
17
+ my_secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==' },
18
+ decryption_key: './spec/spec_key' )
19
+
20
+ expect(filtered_settings.my_secure_setting).to eql 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ=='
21
+ end
22
+
23
+ it 'will not attempt to decrypt values even if they are prefixed with "secure"' do
24
+ filtered_settings = DecryptionFilter.execute( data: {
25
+ secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==' },
26
+ decryption_key: './spec/spec_key' )
27
+
28
+ expect(filtered_settings.secure_setting).to eql 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ=='
29
+ end
30
+
31
+ it 'will not attempt to decrypt values even if they are not properly encoded' do
32
+ filtered_settings = DecryptionFilter.execute( data: {
33
+ _secure_my_secure_setting: 'cJbFe0NI5\wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ==' },
34
+ decryption_key: './spec/spec_key' )
35
+
36
+ expect(filtered_settings.my_secure_setting).to eql 'cJbFe0NI5\wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ=='
37
+ end
38
+
39
+ it 'will not attempt to decrypt values if it guesses that they are not encrpyted' do
40
+ filtered_settings = DecryptionFilter.execute( data: {
41
+ _secure_my_secure_setting: 'hello' },
42
+ decryption_key: './spec/spec_key' )
43
+
44
+ expect(filtered_settings.my_secure_setting).to eql 'hello'
45
+ end
46
+
47
+ it 'will raise an exception if there is an encrypted value that it cannot decrypt' do
48
+ expect { DecryptionFilter.execute(data: {
49
+ _secure_my_secure_setting: 'cJbFe0NI5wknmsp2fVgpC/YeBD2pvcdVD+p0pUdnMoYThaV4mpsspg/ZTBtmjx7kMwcF6cjXFLDVw3FxptTHwzJUd4akun6EZ57m+QzCMJYnfY95gB2/emEAQLSz4/YwsE4LDGydkEjY1ZprfXznf+rU31YGDJUTf34ESz7fsQGSc9DjkBb9ao8Mv4cI7pCXkQZDwS5kLAZDf6agy1GzeL71Z8lrmQzk8QQuf/1kQzxsWVlzpKNXWS7u2CJ0sN5eINMngJBfv5ZFrZgfXc86wdgUKc8aaoX8OQA1kKTcdgbE9NcAhNr1+WfNxMnz84XzmUp2Y0H1jPgGkBKQJKArfQ=='
50
+ }) }.to \
51
+ raise_error(Chamber::Errors::UndecryptableValueError, 'my_secure_setting appears to need decrypting but the decryption key is not available.')
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,48 @@
1
+ require 'rspectacular'
2
+ require 'chamber/filters/encryption_filter'
3
+
4
+ module Chamber
5
+ module Filters
6
+ describe EncryptionFilter do
7
+ it 'will attempt to encrypt values which are marked as "secure"' do
8
+ filtered_settings = EncryptionFilter.execute( data: {
9
+ _secure_my_secure_setting: 'hello' },
10
+ encryption_key: './spec/spec_key.pub' )
11
+
12
+ expect(filtered_settings._secure_my_secure_setting).to match EncryptionFilter::BASE64_STRING_PATTERN
13
+ end
14
+
15
+ it 'will not attempt to encrypt values which are not marked as "secure"' do
16
+ filtered_settings = EncryptionFilter.execute( data: {
17
+ my_secure_setting: 'hello' },
18
+ encryption_key: './spec/spec_key.pub' )
19
+
20
+ expect(filtered_settings.my_secure_setting).to eql 'hello'
21
+ end
22
+
23
+ it 'will not attempt to encrypt values even if they are prefixed with "secure"' do
24
+ filtered_settings = EncryptionFilter.execute( data: {
25
+ secure_setting: 'hello' },
26
+ encryption_key: './spec/spec_key.pub' )
27
+
28
+ expect(filtered_settings.secure_setting).to eql 'hello'
29
+ end
30
+
31
+ it 'will attempt to encrypt values if they are not properly encoded' do
32
+ filtered_settings = EncryptionFilter.execute( data: {
33
+ _secure_my_secure_setting: 'fNI5\jwlBn' },
34
+ encryption_key: './spec/spec_key.pub' )
35
+
36
+ expect(filtered_settings._secure_my_secure_setting).to match EncryptionFilter::BASE64_STRING_PATTERN
37
+ end
38
+
39
+ it 'will not attempt to encrypt values if it guesses that they are already encrpyted' do
40
+ filtered_settings = EncryptionFilter.execute( data: {
41
+ _secure_my_secure_setting: 'fNI5wlBniNhEU4396pmhWwx+A09bRAMJOUASuP7PzprewBX8CXYqL+v/uXOJpIRCLDjwe8quuC+j9iLcPU7HBRMr054gGxeqZexbLevXcPk7SrMis3qeEKmnAuarQGXe7ZAntidMY9Lx4pqSkhYXwQnI48d2Dh44qfaS9w2OrehSkpdFRnuxQeOpCKO/bleB0J88WGkytCohyHCRIpbaEjEC3UD52pnqMeu/ClNm+PBgE6Ci94pu5UUnZuIE/y+P4A3wgD6G/u8hgvAW51JwVryg/im1rayGAwWYNgupQ/5LDmjffwx7Q3fyMH2uF3CDIKRIC6U+mnM5SRMO4Dzysw==' },
42
+ encryption_key: './spec/spec_key.pub' )
43
+
44
+ expect(filtered_settings._secure_my_secure_setting).to eql 'fNI5wlBniNhEU4396pmhWwx+A09bRAMJOUASuP7PzprewBX8CXYqL+v/uXOJpIRCLDjwe8quuC+j9iLcPU7HBRMr054gGxeqZexbLevXcPk7SrMis3qeEKmnAuarQGXe7ZAntidMY9Lx4pqSkhYXwQnI48d2Dh44qfaS9w2OrehSkpdFRnuxQeOpCKO/bleB0J88WGkytCohyHCRIpbaEjEC3UD52pnqMeu/ClNm+PBgE6Ci94pu5UUnZuIE/y+P4A3wgD6G/u8hgvAW51JwVryg/im1rayGAwWYNgupQ/5LDmjffwx7Q3fyMH2uF3CDIKRIC6U+mnM5SRMO4Dzysw=='
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,35 @@
1
+ require 'rspectacular'
2
+ require 'chamber/filters/environment_filter'
3
+
4
+ module Chamber
5
+ module Filters
6
+ describe EnvironmentFilter do
7
+ it 'can extract data from the environment if an existing variable matches the composite key' do
8
+ ENV['TEST_SETTING_GROUP_TEST_SETTING_LEVEL_TEST_SETTING'] = 'value 2'
9
+
10
+ filtered_data = EnvironmentFilter.execute(data: {
11
+ test_setting_group: {
12
+ test_setting_level: {
13
+ test_setting: 'value 1' }}})
14
+
15
+ expect(filtered_data.test_setting_group.test_setting_level.test_setting).to eql 'value 2'
16
+
17
+ ENV.delete('TEST_SETTING_GROUP_TEST_SETTING_LEVEL_TEST_SETTING')
18
+ end
19
+
20
+ it 'does not affect items which are not stored in the environment' do
21
+ ENV['TEST_SETTING_GROUP_TEST_SETTING_LEVEL_TEST_SETTING'] = 'value 2'
22
+
23
+ filtered_data = EnvironmentFilter.execute(data: {
24
+ test_setting_group: {
25
+ test_setting_level: {
26
+ test_setting: 'value 1',
27
+ another_setting: 'value 3', }}})
28
+
29
+ expect(filtered_data.test_setting_group.test_setting_level.another_setting).to eql 'value 3'
30
+
31
+ ENV.delete('TEST_SETTING_GROUP_TEST_SETTING_LEVEL_TEST_SETTING')
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,73 @@
1
+ require 'rspectacular'
2
+ require 'chamber/filters/namespace_filter'
3
+ require 'chamber/namespace_set'
4
+
5
+ module Chamber
6
+ module Filters
7
+ describe NamespaceFilter do
8
+ it 'can filter settings data based on the settings namespaces' do
9
+ filtered_settings = NamespaceFilter.execute(data: {
10
+ namespace_value: {
11
+ namespace_setting: 'value 1' },
12
+ other_namespace_value: {
13
+ other_namespace_setting: 'value 2' }},
14
+ namespaces: [
15
+ 'namespace_value',
16
+ 'other_namespace_value' ])
17
+
18
+ expect(filtered_settings.namespace_setting).to eql 'value 1'
19
+ expect(filtered_settings.other_namespace_setting).to eql 'value 2'
20
+ end
21
+
22
+ it 'ignores data which is not part of a namespace' do
23
+ filtered_settings = NamespaceFilter.execute(data: {
24
+ namespace_value: {
25
+ namespace_setting: 'value 1' },
26
+ non_namespaced_value: {
27
+ non_namespaced_setting: 'value 2' }},
28
+ namespaces: [
29
+ 'namespace_value' ])
30
+
31
+ expect(filtered_settings.namespace_setting).to eql 'value 1'
32
+ expect(filtered_settings.non_namespaced_setting).to be_nil
33
+ end
34
+
35
+ it 'ignores namespaces which do not exist in the data' do
36
+ filtered_settings = NamespaceFilter.execute(data: {
37
+ namespace_value: {
38
+ namespace_setting: 'value 1' }},
39
+ namespaces: [
40
+ 'namespace_value',
41
+ 'other_namespace_value' ])
42
+
43
+ expect(filtered_settings.namespace_setting).to eql 'value 1'
44
+ end
45
+
46
+ it 'does not filter data if it does not include any namespaces' do
47
+ filtered_settings = NamespaceFilter.execute(data: {
48
+ non_namespaced_setting: 'value 1' },
49
+ namespaces: [])
50
+
51
+ expect(filtered_settings.non_namespaced_setting).to eql 'value 1'
52
+ end
53
+
54
+ it 'can filter if it is given NamespaceSets' do
55
+ filtered_settings = NamespaceFilter.execute(data: {
56
+ namespace_value: {
57
+ namespace_setting: 'value 1',
58
+ another_namespace_setting: 'value 2' },
59
+ other_namespace_value: {
60
+ namespace_setting_1: 'value 1',
61
+ another_namespace_setting_2: 'value 2' },
62
+ non_namespaced_value: 'value 3' },
63
+ namespaces:
64
+ NamespaceSet.new(['namespace_value', 'other_namespace_value']) )
65
+
66
+ expect(filtered_settings.to_hash).to eql( 'namespace_setting' => 'value 1',
67
+ 'another_namespace_setting' => 'value 2',
68
+ 'namespace_setting_1' => 'value 1',
69
+ 'another_namespace_setting_2' => 'value 2')
70
+ end
71
+ end
72
+ end
73
+ end