aws2-ssm-env 0.1.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.
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe AwsSsmEnv::FetcherFactory do
4
+ describe '#create_fetcher' do
5
+ let(:fetcher) { described_class.create_fetcher(args) }
6
+
7
+ context 'when fetch was not set' do
8
+ context 'when begins_with was not set' do
9
+ let(:args) { { path: '/path' } }
10
+
11
+ it 'return AwsSsmEnv::PathFetcher' do
12
+ expect(fetcher).to be_a(AwsSsmEnv::PathFetcher)
13
+ end
14
+ end
15
+
16
+ context 'when begins_with was set' do
17
+ let(:args) { { begins_with: '/path' } }
18
+
19
+ it 'return AwsSsmEnv::BeginsWithFetcher' do
20
+ expect(fetcher).to be_a(AwsSsmEnv::BeginsWithFetcher)
21
+ end
22
+ end
23
+ end
24
+
25
+ context 'when fetch is :path' do
26
+ let(:args) { { fetch: :path, path: '/path' } }
27
+
28
+ it 'return AwsSsmEnv::PathFetcher' do
29
+ expect(fetcher).to be_a(AwsSsmEnv::PathFetcher)
30
+ end
31
+ end
32
+
33
+ context 'when fetch is :begins_with' do
34
+ let(:args) { { fetch: :begins_with, begins_with: '/path' } }
35
+
36
+ it 'return AwsSsmEnv::BeginsWithFetcher' do
37
+ expect(fetcher).to be_a(AwsSsmEnv::BeginsWithFetcher)
38
+ end
39
+ end
40
+
41
+ context 'when fetch is AwsSsmEnv::Fetcher implementation instance' do
42
+ let(:fetcher_class) { Class.new(AwsSsmEnv::Fetcher) { def fetch(_); end } }
43
+ let(:fetcher_instance) { fetcher_class.new }
44
+ let(:args) { { fetch: fetcher_instance } }
45
+
46
+ it 'return it as is' do
47
+ expect(fetcher).to eq(fetcher_instance)
48
+ end
49
+ end
50
+
51
+ context 'when fetch has each method' do
52
+ let(:args) { { fetch: [] } }
53
+
54
+ it 'return it as is' do
55
+ expect(fetcher).to eq([])
56
+ end
57
+ end
58
+
59
+ context 'in other cases' do
60
+ it 'raise error' do
61
+ expect { described_class.create_fetcher(fetch: 'foo') }.to raise_error(ArgumentError)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+ require 'aws-ssm-env/fetchers/path'
3
+
4
+ describe AwsSsmEnv::PathFetcher do
5
+ let(:fetcher) { described_class.new(args) }
6
+ let(:args) { { path: '/path' } }
7
+ let(:base_params) { fetcher.instance_variable_get(:'@base_params') }
8
+
9
+ describe '#initialize' do
10
+ context 'when path was not set' do
11
+ it 'raise error' do
12
+ expect { described_class.new(path: nil) }.to raise_error(ArgumentError)
13
+ end
14
+ end
15
+
16
+ context 'when :path was set' do
17
+ it '@base_params[:path] is argument value' do
18
+ expect(base_params[:path]).to eq('/path')
19
+ end
20
+ end
21
+
22
+ context 'when recursive was not set' do
23
+ it '@base_params[:recursive] is false' do
24
+ expect(base_params[:recursive]).to be_falsey
25
+ end
26
+ end
27
+
28
+ context 'when recursive is truthy string' do
29
+ let(:args) { { path: '/path', recursive: 'TruE' } }
30
+
31
+ it '@base_params[:recursive] is true' do
32
+ expect(base_params[:recursive]).to be_truthy
33
+ end
34
+ end
35
+
36
+ context 'when recursive is not truthy string' do
37
+ let(:args) { { path: '/path', recursive: 'foo' } }
38
+
39
+ it '@base_params[:recursive] is false' do
40
+ expect(base_params[:recursive]).to be_falsey
41
+ end
42
+ end
43
+
44
+ context 'when :fetch_size was set and less than 10' do
45
+ let(:args) { { path: '/path', fetch_size: 5 } }
46
+
47
+ it '@base_params[:max_results] is fetch_size value' do
48
+ expect(base_params[:max_results]).to eq(5)
49
+ end
50
+ end
51
+
52
+ context 'when :fetch_size was not set' do
53
+ it '@base_params[:max_results] is 10' do
54
+ expect(base_params[:max_results]).to eq(10)
55
+ end
56
+ end
57
+
58
+ context 'when :fetch_size is nil' do
59
+ let(:args) { { path: '/path', fetch_size: nil } }
60
+
61
+ it '@base_params[:max_results] is 10' do
62
+ expect(base_params[:max_results]).to eq(10)
63
+ end
64
+ end
65
+
66
+ context 'when :fetch_size > 10' do
67
+ let(:args) { { path: '/path', fetch_size: 11 } }
68
+
69
+ it '@base_params[:max_results] is 10' do
70
+ expect(base_params[:max_results]).to eq(10)
71
+ end
72
+ end
73
+ end
74
+
75
+ describe '#fetch' do
76
+ before do
77
+ allow_any_instance_of(Aws::SSM::Client).to \
78
+ receive(:get_parameters_by_path).and_return(nil)
79
+ end
80
+
81
+ let(:client) { fetcher.send(:client) }
82
+
83
+ context 'when next_token is nil' do
84
+ it 'called get_parameters_by_path without next_token' do
85
+ expect(fetcher.send(:fetch, nil)).to be_nil
86
+ expect(client).to \
87
+ have_received(:get_parameters_by_path).with(base_params).once
88
+ end
89
+ end
90
+
91
+ context 'when next_token is not nil' do
92
+ it 'called get_parameters_by_path with next_token' do
93
+ expect(fetcher.send(:fetch, 'next_token')).to be_nil
94
+ expect(client).to \
95
+ have_received(:get_parameters_by_path)
96
+ .with(base_params.merge(next_token: 'next_token')).once
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ describe AwsSsmEnv::Loader do
4
+ let(:args) { { path: '/foo' } }
5
+
6
+ describe '#initialize' do
7
+ let(:loader) { described_class.new(args) }
8
+
9
+ it 'has fetcher and naming_strategy' do
10
+ expect(loader.instance_variable_get(:@fetcher)).to be_a(AwsSsmEnv::PathFetcher)
11
+ expect(loader.instance_variable_get(:@naming_strategy)).to be_a(AwsSsmEnv::BasenameNamingStrategy)
12
+ end
13
+
14
+ describe 'overwrite option' do
15
+ let(:applier) { loader.instance_variable_get(:@applier) }
16
+
17
+ context 'when overwrite was not set' do
18
+ it '@applier is not overwrite method' do
19
+ expect(applier).to eq(:apply)
20
+ end
21
+ end
22
+
23
+ context 'when overwrite is nil' do
24
+ let(:args) { { path: '/foo', overwrite: nil } }
25
+
26
+ it '@applier is not overwrite method' do
27
+ expect(applier).to eq(:apply)
28
+ end
29
+ end
30
+
31
+ context 'when overwrite is truthy string' do
32
+ let(:args) { { path: '/foo', overwrite: 'truE' } }
33
+
34
+ it '@applier is overwrite method' do
35
+ expect(applier).to eq(:apply!)
36
+ end
37
+ end
38
+
39
+ context 'when overwrite is not truthy string' do
40
+ let(:args) { { path: '/foo', overwrite: 'foo' } }
41
+
42
+ it '@applier is not overwrite method' do
43
+ expect(applier).to eq(:apply)
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '#load' do
50
+ context 'when overwrite is false' do
51
+ it 'environment variables were not overwritten' do
52
+ ENV['foo'] = nil
53
+ ENV['fizz'] = 'fizz'
54
+
55
+ loader = described_class.new(args)
56
+ loader.instance_variable_set(:@fetcher,
57
+ [ Parameter.new('foo', 'bar'), Parameter.new('fizz', 'buzz') ])
58
+
59
+ loader.load
60
+
61
+ expect(ENV['foo']).to eq('bar')
62
+ expect(ENV['fizz']).to eq('fizz')
63
+ end
64
+ end
65
+
66
+ context 'when overwrite is true' do
67
+ let(:args) { { path: '/foo', overwrite: true } }
68
+
69
+ it 'environment variables were overwritten' do
70
+ ENV['foo'] = nil
71
+ ENV['fizz'] = 'fizz'
72
+
73
+ loader = described_class.new(args)
74
+ loader.instance_variable_set(:@fetcher,
75
+ [ Parameter.new('foo', 'bar'), Parameter.new('fizz', 'buzz') ])
76
+
77
+ loader.load
78
+
79
+ expect(ENV['foo']).to eq('bar')
80
+ expect(ENV['fizz']).to eq('buzz')
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ require 'aws-ssm-env/naming_strategies/basename'
3
+
4
+ describe AwsSsmEnv::BasenameNamingStrategy do
5
+ describe '#parse_name' do
6
+ let(:naming_strategy) { described_class.new }
7
+
8
+ it 'return the last element name of the path hierarchy' do
9
+ expect(naming_strategy.parse_name(Parameter.new('/path/to/ENV_NAME'))).to eq('ENV_NAME')
10
+ expect(naming_strategy.parse_name(Parameter.new('env_name'))).to eq('env_name')
11
+ expect(naming_strategy.parse_name(Parameter.new('env/name'))).to eq('name')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe AwsSsmEnv::NamingStrategyFactory do
4
+ describe '#create_naming_strategy' do
5
+ let(:naming_strategy) { described_class.create_naming_strategy(args) }
6
+
7
+ context 'when naming was not set' do
8
+ let(:args) { { naming: nil } }
9
+
10
+ it 'return AwsSsmEnv::BasenameNamingStrategy' do
11
+ expect(naming_strategy).to be_a(AwsSsmEnv::BasenameNamingStrategy)
12
+ end
13
+ end
14
+
15
+ context 'when naming is :basename' do
16
+ let(:args) { { naming: :basename } }
17
+
18
+ it 'return AwsSsmEnv::BasenameNamingStrategy' do
19
+ expect(naming_strategy).to be_a(AwsSsmEnv::BasenameNamingStrategy)
20
+ end
21
+ end
22
+
23
+ context 'when naming is :snakecase' do
24
+ let(:args) { { naming: :snakecase } }
25
+
26
+ it 'return AwsSsmEnv::SnakeCaseNamingStrategy' do
27
+ expect(naming_strategy).to be_a(AwsSsmEnv::SnakeCaseNamingStrategy)
28
+ end
29
+ end
30
+
31
+ context 'when naming is AwsSsmEnv::NamingStrategy implementation instance' do
32
+ let(:naming_class) { Class.new(AwsSsmEnv::NamingStrategy) { def parse_name(_); end } }
33
+ let(:naming_instance) { naming_class.new }
34
+ let(:args) { { naming: naming_instance } }
35
+
36
+ it 'return it as is' do
37
+ expect(naming_strategy).to eq(naming_instance)
38
+ end
39
+ end
40
+
41
+ context 'when naming has parse_name method' do
42
+ let(:naming_class) { Class.new { def parse_name(_); end } }
43
+ let(:naming_instance) { naming_class.new }
44
+ let(:args) { { naming: naming_instance } }
45
+
46
+ it 'return it as is' do
47
+ expect(naming_strategy).to eq(naming_instance)
48
+ end
49
+ end
50
+
51
+ context 'in other cases' do
52
+ it 'raise error' do
53
+ expect { described_class.create_naming_strategy(naming: 'foo') }.to raise_error(ArgumentError)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+ require 'aws-ssm-env/naming_strategies/snakecase'
3
+
4
+ describe AwsSsmEnv::SnakeCaseNamingStrategy do
5
+ let(:strategy) { described_class.new(args) }
6
+ let(:name) { 'path.to.db/password' }
7
+ let(:env_name) { strategy.parse_name(Parameter.new(name)) }
8
+
9
+ describe '#parse_name' do
10
+ context 'when :removed_prefix was not set' do
11
+ context 'when :begins_with was not set' do
12
+ let(:args) { {} }
13
+
14
+ it 'return converted path hierarchy into snake case' do
15
+ expect(env_name).to eq('PATH.TO.DB_PASSWORD')
16
+ end
17
+ end
18
+
19
+ context 'when :begins_with was set' do
20
+ let(:args) { { begins_with: 'path.to.' } }
21
+
22
+ it 'return converted path hierarchy without begins_with into snake case' do
23
+ expect(env_name).to eq('DB_PASSWORD')
24
+ end
25
+ end
26
+
27
+ context 'when :path was set' do
28
+ let(:args) { { path: 'path.to.' } }
29
+
30
+ it 'return converted path hierarchy without begins_with into snake case' do
31
+ expect(env_name).to eq('DB_PASSWORD')
32
+ end
33
+ end
34
+ end
35
+
36
+ context 'when :removed_prefix was set' do
37
+ context 'when :begins_with was not set' do
38
+ let(:args) { { removed_prefix: 'path.' } }
39
+
40
+ it 'return converted path hierarchy without removed_prefix into snake case' do
41
+ expect(env_name).to eq('TO.DB_PASSWORD')
42
+ end
43
+ end
44
+
45
+ context 'when :begins_with was set' do
46
+ let(:args) { { removed_prefix: 'path.', begins_with: 'path.to.' } }
47
+
48
+ it 'return converted path hierarchy without removed_prefix into snake case' do
49
+ expect(env_name).to eq('TO.DB_PASSWORD')
50
+ end
51
+ end
52
+
53
+ context 'when :path was set' do
54
+ let(:args) { { removed_prefix: 'path.', path: 'path.to.' } }
55
+
56
+ it 'return converted path hierarchy without removed_prefix into snake case' do
57
+ expect(env_name).to eq('TO.DB_PASSWORD')
58
+ end
59
+ end
60
+ end
61
+
62
+ context 'when :delimiter was not set' do
63
+ let(:args) { { removed_prefix: 'path.' } }
64
+
65
+ it 'return converted path hierarchy with replace "/" to "_"' do
66
+ expect(env_name).to eq('TO.DB_PASSWORD')
67
+ end
68
+ end
69
+
70
+ context 'when :delimiter was set' do
71
+ let(:args) { { removed_prefix: 'path.', delimiter: %r{[./]} } }
72
+
73
+ it 'return converted path hierarchy with replace "/" or "." to "_"' do
74
+ expect(env_name).to eq('TO_DB_PASSWORD')
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe AwsSsmEnv::NamingStrategy do
4
+ describe '#parse_name' do
5
+ let!(:strategy) { described_class.new }
6
+
7
+ it 'raise error' do
8
+ expect { strategy.parse_name(Parameter.new('foo')) }.to raise_error(NotImplementedError)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ class Parameter
2
+ attr_reader :name, :value
3
+ def initialize(*args)
4
+ @name = args[0]
5
+ @value = args[1]
6
+ end
7
+ end
@@ -0,0 +1,128 @@
1
+ require 'spec_helper'
2
+ require 'logger'
3
+
4
+ describe AwsSsmEnv do
5
+ let(:ssm_client) {
6
+ stub_responses = {
7
+ get_parameters_by_path: {
8
+ parameters: [
9
+ { name: 'foo', value: 'bar', type: 'String', version: 1 },
10
+ { name: 'fizz', value: 'buzz', type: 'String', version: 1 }
11
+ ],
12
+ next_token: nil
13
+ }
14
+ }
15
+ Aws::SSM::Client.new(stub_responses: stub_responses)
16
+ }
17
+ let(:logger) { Logger.new('/dev/null') }
18
+
19
+ describe '#load' do
20
+ context 'when overwrite is false' do
21
+ it 'environment variables were not overwritten' do
22
+ ENV['foo'] = nil
23
+ ENV['fizz'] = 'fizz'
24
+
25
+ described_class.load(client: ssm_client, path: '/path')
26
+
27
+ expect(ENV['foo']).to eq('bar')
28
+ expect(ENV['fizz']).to eq('fizz')
29
+ end
30
+ end
31
+
32
+ context 'when overwrite is true' do
33
+ it 'environment variables were overwritten' do
34
+ ENV['foo'] = nil
35
+ ENV['fizz'] = 'fizz'
36
+
37
+ described_class.load!(client: ssm_client, path: '/path', logger: logger)
38
+
39
+ expect(ENV['foo']).to eq('bar')
40
+ expect(ENV['fizz']).to eq('buzz')
41
+ end
42
+ end
43
+ end
44
+
45
+ # @example Request syntax with placeholder values
46
+ #
47
+ # resp = client.put_parameter({
48
+ # name: "PSParameterName", # required
49
+ # description: "ParameterDescription",
50
+ # value: "PSParameterValue", # required
51
+ # type: "String", # required, accepts String, StringList, SecureString
52
+ # key_id: "ParameterKeyId",
53
+ # overwrite: false,
54
+ # allowed_pattern: "AllowedPattern",
55
+ # })
56
+ #
57
+ describe 'Integration test', integration: true do
58
+ PARAMETERS = [
59
+ { name: "/test/#{RUBY_VERSION}/aws-ssm-env/db_password", value: 'db_password', type: :SecureString },
60
+ { name: "/test/#{RUBY_VERSION}/aws-ssm-env/db/username", value: 'db_username', type: :String },
61
+ { name: "/test/#{RUBY_VERSION}/aws-ssm-env/roles", value: 'admin,guest', type: :StringList },
62
+ { name: "test.#{RUBY_VERSION}.aws-ssm-env.db_password", value: 'db_password', type: :SecureString },
63
+ { name: "test.#{RUBY_VERSION}.aws-ssm-env.username", value: 'db_username', type: :String },
64
+ { name: "test.#{RUBY_VERSION}.aws-ssm-env.roles", value: 'admin,guest', type: :StringList },
65
+ ].freeze
66
+ ENV_NAMES = %w[db_password username roles].freeze
67
+
68
+ def remove_env_all
69
+ ENV_NAMES.each do |name|
70
+ ENV[name] = nil
71
+ ENV[name.upcase] = nil
72
+ end
73
+ end
74
+
75
+ before :all do
76
+ @client = Aws::SSM::Client.new
77
+ PARAMETERS.each do |parameter|
78
+ @client.put_parameter(
79
+ name: parameter[:name],
80
+ value: parameter[:value],
81
+ type: parameter[:type].to_s,
82
+ overwrite: true
83
+ )
84
+ end
85
+ end
86
+
87
+ before do
88
+ remove_env_all
89
+ end
90
+
91
+ after :all do
92
+ @client.delete_parameters(names: PARAMETERS.map { |p| p[:name] })
93
+ end
94
+
95
+ after do
96
+ remove_env_all
97
+ end
98
+
99
+ describe 'path fetcher' do
100
+ context 'when recursive is true' do
101
+ it 'set environment variables from EC2 Parameter Store parameters' do
102
+ described_class.load(path: "/test/#{RUBY_VERSION}/aws-ssm-env", recursive: true, logger: logger)
103
+ expect(ENV['db_password']).to eq('db_password')
104
+ expect(ENV['username']).to eq('db_username')
105
+ expect(ENV['roles']).to eq('admin,guest')
106
+ end
107
+ end
108
+
109
+ context 'when recursive is false' do
110
+ it 'set environment variables from EC2 Parameter Store parameters' do
111
+ described_class.load(path: "/test/#{RUBY_VERSION}/aws-ssm-env", recursive: false, logger: logger)
112
+ expect(ENV['db_password']).to eq('db_password')
113
+ expect(ENV['username']).to be_nil
114
+ expect(ENV['roles']).to eq('admin,guest')
115
+ end
116
+ end
117
+ end
118
+
119
+ describe 'begins_with fetcher' do
120
+ it 'set environment variables from EC2 Parameter Store parameters' do
121
+ described_class.load(begins_with: "test.#{RUBY_VERSION}.aws-ssm-env.", naming: :snakecase, delimiter: '.', logger: logger)
122
+ expect(ENV['DB_PASSWORD']).to eq('db_password')
123
+ expect(ENV['USERNAME']).to eq('db_username')
124
+ expect(ENV['ROLES']).to eq('admin,guest')
125
+ end
126
+ end
127
+ end
128
+ end