kumo_keisei 2.1.1 → 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|