kumo_keisei 2.1.1 → 2.2.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/.rubocop.yml +1156 -0
- data/VERSION +1 -1
- data/lib/kumo_keisei/cloud_formation_stack.rb +1 -1
- data/lib/kumo_keisei/environment_config.rb +93 -90
- data/lib/kumo_keisei/file_loader.rb +18 -6
- data/lib/kumo_keisei/parameter_builder.rb +2 -2
- data/spec/lib/kumo_keisei/environment_config_spec.rb +173 -116
- data/spec/lib/kumo_keisei/file_loader_spec.rb +23 -9
- data/spec/lib/kumo_keisei/parameter_builder_spec.rb +1 -1
- metadata +3 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.2.1
|
@@ -147,7 +147,7 @@ module KumoKeisei
|
|
147
147
|
rescue Aws::CloudFormation::Errors::ValidationError => ex
|
148
148
|
raise ex unless ex.message == "No updates are to be performed."
|
149
149
|
ConsoleJockey.write_line "No changes need to be applied for #{@stack_name}."
|
150
|
-
rescue Aws::Waiters::Errors::FailureStateError
|
150
|
+
rescue Aws::Waiters::Errors::FailureStateError
|
151
151
|
ConsoleJockey.write_line "Failed to apply the environment update. The stack has been rolled back. It is still safe to apply updates."
|
152
152
|
ConsoleJockey.write_line "Find error details in the AWS CloudFormation console: #{stack_events_url}"
|
153
153
|
raise UpdateError.new("Stack update failed for #{@stack_name}.")
|
@@ -5,118 +5,121 @@ require 'yaml'
|
|
5
5
|
require_relative 'file_loader'
|
6
6
|
require_relative 'parameter_builder'
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
binding
|
26
|
-
end
|
8
|
+
module KumoKeisei
|
9
|
+
# Environment Configuration for a cloud formation stack
|
10
|
+
class EnvironmentConfig
|
11
|
+
LOGGER = Logger.new(STDOUT)
|
12
|
+
|
13
|
+
attr_reader :app_name, :env_name
|
14
|
+
|
15
|
+
def initialize(options, logger = LOGGER)
|
16
|
+
@app_name = options[:app_name]
|
17
|
+
@env_name = options[:env_name]
|
18
|
+
@config_dir_path = options[:config_dir_path]
|
19
|
+
@params_template_file_path = options[:params_template_file_path]
|
20
|
+
@injected_config = options[:injected_config] || {}
|
21
|
+
@file_loader = KumoKeisei::FileLoader.new(options)
|
22
|
+
|
23
|
+
@log = logger
|
24
|
+
end
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
def production?
|
27
|
+
env_name == 'production'
|
28
|
+
end
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
def development?
|
31
|
+
!%w(production staging).include? env_name
|
32
|
+
end
|
35
33
|
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
def plain_text_secrets
|
35
|
+
@plain_text_secrets ||= decrypt_secrets(encrypted_secrets)
|
36
|
+
end
|
39
37
|
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
def config
|
39
|
+
# a hash of all settings that apply to this environment
|
40
|
+
@config ||= common_config.merge(env_config).merge(@injected_config)
|
41
|
+
end
|
43
42
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
43
|
+
def cf_params
|
44
|
+
# returns a list of Cfn friendly paramater_value, paramater_key pairs for
|
45
|
+
# consumption by cloudformation.
|
46
|
+
return [] unless params
|
47
|
+
config
|
48
48
|
|
49
|
-
|
49
|
+
stack_params = YAML.load(params.result(binding))
|
50
|
+
KumoKeisei::ParameterBuilder.new(stack_params).params
|
51
|
+
end
|
50
52
|
|
51
|
-
|
52
|
-
@kms ||= KumoKi::KMS.new
|
53
|
-
end
|
53
|
+
private
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
def kms
|
56
|
+
@kms ||= KumoKi::KMS.new
|
57
|
+
end
|
58
58
|
|
59
|
-
|
60
|
-
|
59
|
+
def params
|
60
|
+
return nil unless @params_template_file_path
|
61
|
+
@file_loader.load_erb(@params_template_file_path)
|
62
|
+
end
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
+
def decrypt_secrets(secrets)
|
65
|
+
Hash[
|
66
|
+
secrets.map do |name, cipher_text|
|
67
|
+
@log.debug "Decrypting '#{name}'"
|
68
|
+
decrypt_cipher name, cipher_text
|
69
|
+
end
|
70
|
+
]
|
71
|
+
end
|
64
72
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
rescue
|
73
|
-
@log.error "Error decrypting secret '#{name}'"
|
74
|
-
raise
|
75
|
-
end
|
76
|
-
else
|
77
|
-
[name, cipher_text]
|
73
|
+
def decrypt_cipher(name, cipher_text)
|
74
|
+
if cipher_text.start_with? '[ENC,'
|
75
|
+
begin
|
76
|
+
[name, kms.decrypt(cipher_text[5, cipher_text.size]).to_s]
|
77
|
+
rescue
|
78
|
+
@log.error "Error decrypting secret '#{name}'"
|
79
|
+
raise
|
78
80
|
end
|
81
|
+
else
|
82
|
+
[name, cipher_text]
|
79
83
|
end
|
80
|
-
|
81
|
-
end
|
84
|
+
end
|
82
85
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
+
def env_config_file_name
|
87
|
+
"#{env_name}.yml"
|
88
|
+
end
|
86
89
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
+
def env_secrets_file_name
|
91
|
+
"#{env_name}_secrets.yml"
|
92
|
+
end
|
90
93
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
+
def encrypted_secrets
|
95
|
+
encrypted_common_secrets.merge(encrypted_env_secrets)
|
96
|
+
end
|
94
97
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
+
def encrypted_common_secrets
|
99
|
+
@file_loader.load_hash('common_secrets.yml')
|
100
|
+
end
|
98
101
|
|
99
|
-
|
100
|
-
|
102
|
+
def encrypted_env_secrets
|
103
|
+
secrets = @file_loader.load_hash(env_secrets_file_name)
|
101
104
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
105
|
+
if !secrets.empty?
|
106
|
+
secrets
|
107
|
+
else
|
108
|
+
@file_loader.load_hash('development_secrets.yml')
|
109
|
+
end
|
106
110
|
end
|
107
|
-
end
|
108
111
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
def env_config
|
114
|
-
config = @file_loader.load_config(env_config_file_name)
|
112
|
+
def common_config
|
113
|
+
@file_loader.load_hash('common.yml')
|
114
|
+
end
|
115
115
|
|
116
|
-
|
117
|
-
config
|
118
|
-
|
119
|
-
|
116
|
+
def env_config
|
117
|
+
config = @file_loader.load_hash(env_config_file_name)
|
118
|
+
if !config.empty?
|
119
|
+
config
|
120
|
+
else
|
121
|
+
@file_loader.load_hash('development.yml')
|
122
|
+
end
|
120
123
|
end
|
121
124
|
end
|
122
125
|
end
|
@@ -4,15 +4,27 @@ module KumoKeisei
|
|
4
4
|
@config_dir_path = options[:config_dir_path]
|
5
5
|
end
|
6
6
|
|
7
|
-
def
|
8
|
-
|
9
|
-
|
7
|
+
def load_hash(file_name, optional = true)
|
8
|
+
# reads a file presuming it's a yml in form of key: value, returning it as a hash
|
9
|
+
path = file_path(file_name)
|
10
|
+
|
11
|
+
begin
|
12
|
+
YAML::load(File.read(path))
|
13
|
+
rescue Errno::ENOENT => ex
|
14
|
+
# file not found, return empty dictionary if that is ok
|
15
|
+
return {} if optional
|
16
|
+
raise ex
|
17
|
+
rescue StandardError => ex
|
18
|
+
# this is an error we weren't expecting
|
19
|
+
raise ex
|
20
|
+
end
|
10
21
|
end
|
11
22
|
|
12
|
-
def
|
23
|
+
def load_erb(file_name)
|
24
|
+
# loads a file, constructs an ERB object from it and returns the ERB object
|
25
|
+
# DOES NOT RENDER A RESULT!!
|
13
26
|
path = file_path(file_name)
|
14
|
-
|
15
|
-
load_config!(file_name)
|
27
|
+
ERB.new(File.read(path))
|
16
28
|
end
|
17
29
|
|
18
30
|
private
|
@@ -21,11 +21,11 @@ module KumoKeisei
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def parsed_file_params
|
24
|
-
return [] unless (@file_path && File.
|
24
|
+
return [] unless (@file_path && File.exist?(@file_path))
|
25
25
|
|
26
26
|
file_contents = JSON.parse(File.read(@file_path))
|
27
27
|
|
28
|
-
file_contents.map do |param|
|
28
|
+
file_contents.map do |param|
|
29
29
|
{
|
30
30
|
parameter_key: param["ParameterKey"],
|
31
31
|
parameter_value: param["ParameterValue"]
|
@@ -11,170 +11,227 @@ describe KumoKeisei::EnvironmentConfig do
|
|
11
11
|
}
|
12
12
|
end
|
13
13
|
let(:file_loader) { instance_double(KumoKeisei::FileLoader) }
|
14
|
-
let(:
|
14
|
+
let(:parameters) { ERB.new("") }
|
15
15
|
let(:params_template_file_path) { '/junk.txt' }
|
16
16
|
let(:environment_config_file_name) { "#{env_name}.yml" }
|
17
17
|
let(:kms) { instance_double(KumoKi::KMS) }
|
18
18
|
let(:logger) { double(:test_logger, debug: nil) }
|
19
|
+
let(:environment_config) { described_class.new(options, logger) }
|
19
20
|
|
20
21
|
before do
|
21
22
|
allow(KumoKeisei::FileLoader).to receive(:new).and_return(file_loader)
|
22
23
|
allow(KumoKi::KMS).to receive(:new).and_return(kms)
|
23
|
-
allow(file_loader).to receive(:
|
24
|
+
allow(file_loader).to receive(:load_erb).with(params_template_file_path).and_return(parameters)
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
|
-
|
27
|
+
context 'unit tests' do
|
28
|
+
let(:fake_environment_binding) { binding }
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
{
|
32
|
-
env_name: env_name,
|
33
|
-
config_dir_path: config_dir_path
|
34
|
-
}
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'creates an empty array' do
|
38
|
-
expect(subject).to eq([])
|
39
|
-
end
|
40
|
-
end
|
30
|
+
describe '#cf_params' do
|
31
|
+
subject { environment_config.cf_params }
|
41
32
|
|
42
|
-
|
43
|
-
|
33
|
+
context 'params template file path is not provided' do
|
34
|
+
let(:options) do
|
35
|
+
{
|
36
|
+
env_name: env_name,
|
37
|
+
config_dir_path: config_dir_path
|
38
|
+
}
|
39
|
+
end
|
44
40
|
|
45
|
-
|
46
|
-
|
41
|
+
it 'creates an empty array' do
|
42
|
+
expect(subject).to eq([])
|
43
|
+
end
|
47
44
|
end
|
48
|
-
end
|
49
45
|
|
50
|
-
|
51
|
-
|
46
|
+
context 'params is empty' do
|
47
|
+
let(:parameters) { nil }
|
52
48
|
|
53
|
-
|
54
|
-
|
49
|
+
it 'creates an empty array' do
|
50
|
+
expect(subject).to eq([])
|
51
|
+
end
|
55
52
|
end
|
56
|
-
end
|
57
53
|
|
58
|
-
|
59
|
-
|
54
|
+
context 'a hard-coded param' do
|
55
|
+
let(:parameters) { ERB.new("stack_name: \"foo-stack\"") }
|
56
|
+
let(:parameters) { ERB.new("parameter_key: \"parameter_value\"") }
|
60
57
|
|
61
|
-
|
62
|
-
|
63
|
-
allow(file_loader).to receive(:
|
64
|
-
allow(file_loader).to receive(:
|
58
|
+
before do
|
59
|
+
allow(file_loader).to receive(:load_hash).with('common.yml').and_return({})
|
60
|
+
allow(file_loader).to receive(:load_hash).with('the_jungle.yml').and_return({})
|
61
|
+
allow(file_loader).to receive(:load_hash).with('development.yml').and_return({})
|
62
|
+
end
|
65
63
|
|
66
|
-
|
64
|
+
it 'creates a array containing an aws formatted parameter hash' do
|
65
|
+
expect(subject).to eq([{parameter_key: "parameter_key", parameter_value: "parameter_value"}])
|
67
66
|
end
|
68
67
|
end
|
69
|
-
end
|
70
|
-
end
|
71
68
|
|
72
|
-
|
73
|
-
|
69
|
+
describe "#config" do
|
70
|
+
subject { described_class.new(options, logger).config }
|
74
71
|
|
75
|
-
|
72
|
+
context 'injected config' do
|
76
73
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
74
|
+
let(:options) do
|
75
|
+
{
|
76
|
+
env_name: env_name,
|
77
|
+
config_dir_path: config_dir_path,
|
78
|
+
params_template_file_path: params_template_file_path,
|
79
|
+
injected_config: { "injected" => "yes" }
|
80
|
+
}
|
81
|
+
end
|
85
82
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
83
|
+
let(:common_parameters) { { "stack_name" => "okonomiyaki" } }
|
84
|
+
it 'adds injected config to the config hash' do
|
85
|
+
expect(file_loader).to receive(:load_hash).with('common.yml').and_return(common_parameters)
|
86
|
+
expect(file_loader).to receive(:load_hash).with(environment_config_file_name).and_return({})
|
87
|
+
expect(file_loader).to receive(:load_hash).with("development.yml").and_return({})
|
91
88
|
|
92
|
-
|
93
|
-
|
94
|
-
|
89
|
+
expect(subject).to eq({ "stack_name" => "okonomiyaki", "injected" => "yes" })
|
90
|
+
end
|
91
|
+
end
|
95
92
|
|
96
|
-
|
97
|
-
|
93
|
+
context 'common config' do
|
94
|
+
let(:common_parameters) { { "stack_name" => "okonomiyaki" } }
|
98
95
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
96
|
+
it 'creates a array containing an aws formatted parameter hash' do
|
97
|
+
expect(file_loader).to receive(:load_hash).with('common.yml').and_return(common_parameters)
|
98
|
+
expect(file_loader).to receive(:load_hash).with(environment_config_file_name).and_return({})
|
99
|
+
expect(file_loader).to receive(:load_hash).with("development.yml").and_return({})
|
103
100
|
|
104
|
-
|
101
|
+
expect(subject).to eq('stack_name' => 'okonomiyaki')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'merging common and environment specific configurations' do
|
106
|
+
let(:environment_config) { {'image' => 'ami-5678'} }
|
107
|
+
let(:development_config) { {'image' => 'ami-9999'} }
|
108
|
+
|
109
|
+
context 'with environmental overrides' do
|
110
|
+
let(:parameter_template) { "image: <%= config['image'] %>" }
|
111
|
+
let(:common_config) { {'image' => 'ami-1234'} }
|
112
|
+
let(:env_name) { 'development' }
|
113
|
+
|
114
|
+
it 'replaces the common value with the env value' do
|
115
|
+
expect(file_loader).to receive(:load_hash).with('common.yml').and_return(common_config)
|
116
|
+
expect(file_loader).to receive(:load_hash).with(environment_config_file_name).and_return(environment_config)
|
117
|
+
expect(subject).to eq('image' => 'ami-5678')
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'falls back to a default environment if the requested one does not exist' do
|
122
|
+
expect(file_loader).to receive(:load_hash).with('common.yml').and_return({})
|
123
|
+
expect(file_loader).to receive(:load_hash).with("#{env_name}.yml").and_return({})
|
124
|
+
expect(file_loader).to receive(:load_hash).with("development.yml").and_return(development_config)
|
125
|
+
|
126
|
+
expect(subject).to eq('image' => 'ami-9999')
|
127
|
+
end
|
128
|
+
end
|
105
129
|
end
|
106
|
-
end
|
107
130
|
|
108
|
-
|
109
|
-
|
131
|
+
describe "#plain_text_secrets" do
|
132
|
+
subject { described_class.new(options, logger).plain_text_secrets }
|
110
133
|
|
111
|
-
|
112
|
-
let(:
|
113
|
-
let(:
|
114
|
-
let(:env_name) { 'development' }
|
134
|
+
let(:crypted_password) { 'lookatmyencryptedpasswords' }
|
135
|
+
let(:plain_text_password) { 'plain_text_password' }
|
136
|
+
let(:secrets) { { 'secret_password' => "[ENC,#{crypted_password}" } }
|
115
137
|
|
116
|
-
|
117
|
-
|
118
|
-
|
138
|
+
let(:crypted_env_password) { 'cryptedenvpassword' }
|
139
|
+
let(:plain_text_env_password) { 'plain_text_env_password' }
|
140
|
+
let(:env_secrets) { { 'secret_password' => "[ENC,#{crypted_env_password}"}}
|
119
141
|
|
120
|
-
|
142
|
+
before do
|
143
|
+
allow(kms).to receive(:decrypt).with(crypted_password).and_return(plain_text_password)
|
121
144
|
end
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'falls back to a default environment if the requested one does not exist' do
|
125
|
-
allow(file_loader).to receive(:load_config).with('common.yml').and_return({})
|
126
|
-
allow(file_loader).to receive(:load_config).with("#{env_name}.yml").and_return({})
|
127
|
-
expect(file_loader).to receive(:load_config).with("development.yml").and_return(environment_config)
|
128
145
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
146
|
+
it 'decrypts common secrets' do
|
147
|
+
allow(file_loader).to receive(:load_hash).with('common_secrets.yml').and_return(secrets)
|
148
|
+
allow(file_loader).to receive(:load_hash).with("#{env_name}_secrets.yml").and_return({})
|
149
|
+
allow(file_loader).to receive(:load_hash).with("development_secrets.yml").and_return({})
|
133
150
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
let(:crypted_password) { 'lookatmyencryptedpasswords' }
|
138
|
-
let(:plain_text_password) { 'plain_text_password' }
|
139
|
-
let(:secrets) { { 'secret_password' => "[ENC,#{crypted_password}" } }
|
151
|
+
expect(subject).to eq('secret_password' => plain_text_password)
|
152
|
+
end
|
140
153
|
|
141
|
-
|
142
|
-
|
143
|
-
|
154
|
+
it 'decrypts environment secrets' do
|
155
|
+
allow(file_loader).to receive(:load_hash).with('common_secrets.yml').and_return({})
|
156
|
+
allow(file_loader).to receive(:load_hash).with("#{env_name}_secrets.yml").and_return(secrets)
|
144
157
|
|
145
|
-
|
146
|
-
|
147
|
-
end
|
158
|
+
expect(subject).to eq('secret_password' => plain_text_password)
|
159
|
+
end
|
148
160
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
161
|
+
it 'gives preference to environment secrets' do
|
162
|
+
allow(file_loader).to receive(:load_hash).with('common_secrets.yml').and_return(secrets)
|
163
|
+
allow(file_loader).to receive(:load_hash).with("#{env_name}_secrets.yml").and_return(env_secrets)
|
164
|
+
allow(kms).to receive(:decrypt).with(crypted_env_password).and_return(plain_text_env_password)
|
153
165
|
|
154
|
-
|
155
|
-
|
166
|
+
expect(subject).to eq('secret_password' => plain_text_env_password)
|
167
|
+
end
|
156
168
|
|
157
|
-
|
158
|
-
|
159
|
-
|
169
|
+
it 'falls back to a default environment if the requested one does not exist' do
|
170
|
+
allow(file_loader).to receive(:load_hash).with('common_secrets.yml').and_return({})
|
171
|
+
allow(file_loader).to receive(:load_hash).with("#{env_name}_secrets.yml").and_return({})
|
172
|
+
expect(file_loader).to receive(:load_hash).with("development_secrets.yml").and_return(secrets)
|
160
173
|
|
161
|
-
|
162
|
-
|
174
|
+
expect(subject).to eq('secret_password' => plain_text_password)
|
175
|
+
end
|
176
|
+
end
|
163
177
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
178
|
+
describe '#development?' do
|
179
|
+
%w(production staging).each do |environment|
|
180
|
+
it "returns false for #{environment}" do
|
181
|
+
expect(
|
182
|
+
described_class.new({
|
183
|
+
env_name: environment,
|
184
|
+
config_dir_path: '',
|
185
|
+
params_template_file_path: ''}
|
186
|
+
).development?).to eq false
|
187
|
+
end
|
188
|
+
end
|
168
189
|
|
169
|
-
|
190
|
+
it 'returns true for anything other than production or staging' do
|
191
|
+
expect(
|
192
|
+
described_class.new({
|
193
|
+
env_name: 'fred',
|
194
|
+
config_dir_path: '',
|
195
|
+
params_template_file_path: ''}
|
196
|
+
).development?).to eq true
|
197
|
+
end
|
198
|
+
end
|
170
199
|
end
|
171
200
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
201
|
+
context 'integration tests' do
|
202
|
+
|
203
|
+
describe '#cf_params' do
|
204
|
+
subject { environment_config.cf_params }
|
205
|
+
|
206
|
+
context 'templated params' do
|
207
|
+
let(:parameters) { ERB.new("stack_name: \"<%= config['stack_name'] %>\"" ) }
|
208
|
+
let(:common_config) { { "stack_name" => "common"} }
|
209
|
+
let(:staging_config) { { "stack_name" => "staging" } }
|
210
|
+
let(:development_config) { { "stack_name" => "development" } }
|
211
|
+
|
212
|
+
context 'hiearchy of parameters' do
|
213
|
+
it 'will load values from the common paramater file' do
|
214
|
+
expect(file_loader).to receive(:load_hash).with('common.yml').and_return(common_config)
|
215
|
+
expect(file_loader).to receive(:load_hash).with("development.yml").and_return({})
|
216
|
+
expect(file_loader).to receive(:load_hash).with(environment_config_file_name).and_return({})
|
217
|
+
expect(subject).to eq([{parameter_key: "stack_name", parameter_value: "common"}])
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'will load values from the environment specific file' do
|
221
|
+
expect(file_loader).to receive(:load_hash).with('common.yml').and_return({})
|
222
|
+
expect(file_loader).to receive(:load_hash).with(environment_config_file_name).and_return(staging_config)
|
223
|
+
expect(subject).to eq([{parameter_key: "stack_name", parameter_value: "staging"}])
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'will load values from the shared development file if an environment specific file has no values' do
|
227
|
+
expect(file_loader).to receive(:load_hash).with('common.yml').and_return({})
|
228
|
+
expect(file_loader).to receive(:load_hash).with(environment_config_file_name).and_return({})
|
229
|
+
expect(file_loader).to receive(:load_hash).with("development.yml").and_return(development_config)
|
230
|
+
expect(subject).to eq([{parameter_key: "stack_name", parameter_value: "development"}])
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
178
235
|
end
|
179
236
|
end
|
180
237
|
end
|