stack_master 1.5.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -0
- data/lib/stack_master/commands/terminal_helper.rb +14 -1
- data/lib/stack_master/parameter_resolvers/secret.rb +7 -2
- data/lib/stack_master/version.rb +1 -1
- metadata +21 -216
- data/.gitignore +0 -18
- data/.rspec +0 -2
- data/.travis.yml +0 -12
- data/CODE_OF_CONDUCT.md +0 -73
- data/Gemfile +0 -4
- data/LICENSE.txt +0 -22
- data/Rakefile +0 -27
- data/apply_demo.gif +0 -0
- data/example/simple/Gemfile +0 -3
- data/example/simple/parameters/myapp_vpc.yml +0 -1
- data/example/simple/parameters/myapp_web.yml +0 -2
- data/example/simple/stack_master.yml +0 -13
- data/example/simple/templates/myapp_vpc.rb +0 -39
- data/example/simple/templates/myapp_web.rb +0 -16
- data/features/apply.feature +0 -392
- data/features/apply_with_compile_time_parameters.feature +0 -93
- data/features/apply_with_env_parameters.feature +0 -49
- data/features/apply_with_parameter_store_parameters.feature +0 -47
- data/features/apply_with_s3.feature +0 -106
- data/features/delete.feature +0 -29
- data/features/diff.feature +0 -179
- data/features/events.feature +0 -33
- data/features/init.feature +0 -6
- data/features/outputs.feature +0 -45
- data/features/region_aliases.feature +0 -62
- data/features/resources.feature +0 -42
- data/features/stack_defaults.feature +0 -82
- data/features/status.feature +0 -118
- data/features/step_definitions/parameter_store_steps.rb +0 -14
- data/features/step_definitions/stack_steps.rb +0 -71
- data/features/support/env.rb +0 -16
- data/features/validate.feature +0 -46
- data/logo.png +0 -0
- data/script/buildkite/bundle.sh +0 -5
- data/script/buildkite/clean.sh +0 -3
- data/script/buildkite_rspec.sh +0 -27
- data/spec/fixtures/parameters/myapp_vpc.yml +0 -1
- data/spec/fixtures/parameters/myapp_vpc_with_secrets.yml +0 -3
- data/spec/fixtures/sparkle_pack_integration/my_sparkle_pack/lib/my_sparkle_pack.rb +0 -1
- data/spec/fixtures/sparkle_pack_integration/my_sparkle_pack/lib/sparkleformation/dynamics/my_dynamic.rb +0 -5
- data/spec/fixtures/sparkle_pack_integration/templates/dynamics/local_dynamic.rb +0 -5
- data/spec/fixtures/sparkle_pack_integration/templates/template_with_dynamic.rb +0 -3
- data/spec/fixtures/sparkle_pack_integration/templates/template_with_dynamic_from_pack.rb +0 -3
- data/spec/fixtures/stack_master.yml +0 -49
- data/spec/fixtures/templates/json/valid_myapp_vpc.json +0 -53
- data/spec/fixtures/templates/myapp_vpc.json +0 -1
- data/spec/fixtures/templates/rb/cfndsl/sample.json +0 -28
- data/spec/fixtures/templates/rb/cfndsl/sample.rb +0 -16
- data/spec/fixtures/templates/yml/valid_myapp_vpc.yml +0 -35
- data/spec/fixtures/test/.gitkeep +0 -0
- data/spec/spec_helper.rb +0 -102
- data/spec/stack_master/aws_driver/s3_spec.rb +0 -130
- data/spec/stack_master/change_set_spec.rb +0 -70
- data/spec/stack_master/command_spec.rb +0 -66
- data/spec/stack_master/commands/apply_spec.rb +0 -259
- data/spec/stack_master/commands/delete_spec.rb +0 -40
- data/spec/stack_master/commands/init_spec.rb +0 -17
- data/spec/stack_master/commands/status_spec.rb +0 -44
- data/spec/stack_master/commands/validate_spec.rb +0 -27
- data/spec/stack_master/config_spec.rb +0 -153
- data/spec/stack_master/paged_response_accumulator_spec.rb +0 -39
- data/spec/stack_master/parameter_loader_spec.rb +0 -110
- data/spec/stack_master/parameter_resolver_spec.rb +0 -148
- data/spec/stack_master/parameter_resolvers/ami_finder_spec.rb +0 -68
- data/spec/stack_master/parameter_resolvers/env_spec.rb +0 -35
- data/spec/stack_master/parameter_resolvers/latest_ami_by_tags_spec.rb +0 -33
- data/spec/stack_master/parameter_resolvers/latest_ami_spec.rb +0 -46
- data/spec/stack_master/parameter_resolvers/parameter_store_spec.rb +0 -50
- data/spec/stack_master/parameter_resolvers/secret_spec.rb +0 -66
- data/spec/stack_master/parameter_resolvers/security_group_spec.rb +0 -19
- data/spec/stack_master/parameter_resolvers/security_groups_spec.rb +0 -32
- data/spec/stack_master/parameter_resolvers/sns_topic_name_spec.rb +0 -43
- data/spec/stack_master/parameter_resolvers/stack_output_spec.rb +0 -127
- data/spec/stack_master/prompter_spec.rb +0 -23
- data/spec/stack_master/resolver_array_spec.rb +0 -42
- data/spec/stack_master/security_group_finder_spec.rb +0 -49
- data/spec/stack_master/sns_topic_finder_spec.rb +0 -25
- data/spec/stack_master/sparkle_formation/compile_time/allowed_pattern_validator_spec.rb +0 -47
- data/spec/stack_master/sparkle_formation/compile_time/allowed_values_validator_spec.rb +0 -47
- data/spec/stack_master/sparkle_formation/compile_time/definitions_validator_spec.rb +0 -36
- data/spec/stack_master/sparkle_formation/compile_time/empty_validator_spec.rb +0 -47
- data/spec/stack_master/sparkle_formation/compile_time/max_length_validator_spec.rb +0 -37
- data/spec/stack_master/sparkle_formation/compile_time/max_size_validator_spec.rb +0 -27
- data/spec/stack_master/sparkle_formation/compile_time/min_length_validator_spec.rb +0 -36
- data/spec/stack_master/sparkle_formation/compile_time/min_size_validator_spec.rb +0 -28
- data/spec/stack_master/sparkle_formation/compile_time/number_validator_spec.rb +0 -41
- data/spec/stack_master/sparkle_formation/compile_time/parameters_validator_spec.rb +0 -65
- data/spec/stack_master/sparkle_formation/compile_time/state_builder_spec.rb +0 -28
- data/spec/stack_master/sparkle_formation/compile_time/string_validator_spec.rb +0 -35
- data/spec/stack_master/sparkle_formation/compile_time/value_build_spec.rb +0 -52
- data/spec/stack_master/sparkle_formation/compile_time/value_validator_factory_spec.rb +0 -40
- data/spec/stack_master/sparkle_formation/template_file_spec.rb +0 -147
- data/spec/stack_master/stack_definition_spec.rb +0 -70
- data/spec/stack_master/stack_differ_spec.rb +0 -46
- data/spec/stack_master/stack_events/fetcher_spec.rb +0 -40
- data/spec/stack_master/stack_events/presenter_spec.rb +0 -18
- data/spec/stack_master/stack_events/streamer_spec.rb +0 -47
- data/spec/stack_master/stack_spec.rb +0 -184
- data/spec/stack_master/template_compiler_spec.rb +0 -39
- data/spec/stack_master/template_compilers/cfndsl_spec.rb +0 -22
- data/spec/stack_master/template_compilers/json_spec.rb +0 -32
- data/spec/stack_master/template_compilers/sparkle_formation_spec.rb +0 -116
- data/spec/stack_master/template_compilers/yaml_spec.rb +0 -20
- data/spec/stack_master/template_utils_spec.rb +0 -21
- data/spec/stack_master/test_driver/cloud_formation_spec.rb +0 -64
- data/spec/stack_master/test_driver/s3_spec.rb +0 -17
- data/spec/stack_master/utils_spec.rb +0 -30
- data/spec/stack_master/validator_spec.rb +0 -56
- data/spec/stack_master_spec.rb +0 -81
- data/spec/support/gemfiles/Gemfile.activesupport-4.0.0 +0 -5
- data/spec/support/validator_spec.rb +0 -23
- data/stack_master.gemspec +0 -46
- data/stacktemplates/parameter_region.yml +0 -3
- data/stacktemplates/parameter_stack_name.yml +0 -3
- data/stacktemplates/stack.json.erb +0 -20
- data/stacktemplates/stack_master.yml.erb +0 -6
@@ -1,44 +0,0 @@
|
|
1
|
-
RSpec.describe StackMaster::Commands::Status do
|
2
|
-
subject(:status) { described_class.new(config, false) }
|
3
|
-
let(:config) { instance_double(StackMaster::Config, stacks: stacks) }
|
4
|
-
let(:stacks) { [stack_definition_1, stack_definition_2] }
|
5
|
-
let(:stack_definition_1) { double(:stack_definition_1, region: 'us-east-1', stack_name: 'stack1') }
|
6
|
-
let(:stack_definition_2) { double(:stack_definition_2, region: 'us-east-1', stack_name: 'stack2', stack_status: 'CREATE_COMPLETE') }
|
7
|
-
let(:cf) { Aws::CloudFormation::Client.new(region: 'us-east-1') }
|
8
|
-
|
9
|
-
before do
|
10
|
-
allow(Aws::CloudFormation::Client).to receive(:new).with(region: 'us-east-1').and_return cf
|
11
|
-
end
|
12
|
-
|
13
|
-
context "#perform" do
|
14
|
-
before do
|
15
|
-
allow(StackMaster::Stack).to receive(:find).and_return stack1, stack2
|
16
|
-
allow(StackMaster::Stack).to receive(:generate).and_return proposed_stack1, proposed_stack2
|
17
|
-
end
|
18
|
-
|
19
|
-
context "some parameters are different" do
|
20
|
-
let(:stack1) { double(:stack1, template_body: '{}', template_hash: {}, template_format: :json, parameters_with_defaults: {a: 1}, stack_status: 'UPDATE_COMPLETE') }
|
21
|
-
let(:stack2) { double(:stack2, template_body: '{}', template_hash: {}, template_format: :json, parameters_with_defaults: {a: 2}, stack_status: 'CREATE_COMPLETE') }
|
22
|
-
let(:proposed_stack1) { double(:proposed_stack1, template_body: "{}", template_format: :json, parameters_with_defaults: {a: 1}) }
|
23
|
-
let(:proposed_stack2) { double(:proposed_stack2, template_body: "{}", template_format: :json, parameters_with_defaults: {a: 1}) }
|
24
|
-
|
25
|
-
it "returns the status of call stacks" do
|
26
|
-
out = "REGION | STACK_NAME | STACK_STATUS | DIFFERENT\n----------|------------|-----------------|----------\nus-east-1 | stack1 | UPDATE_COMPLETE | No \nus-east-1 | stack2 | CREATE_COMPLETE | Yes \n * No echo parameters can't be diffed\n"
|
27
|
-
expect { status.perform }.to output(out).to_stdout
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
context "some templates are different" do
|
32
|
-
let(:stack1) { double(:stack1, template_body: '{"foo": "bar"}', template_hash: {foo: 'bar'}, template_format: :json, parameters_with_defaults: {a: 1}, stack_status: 'UPDATE_COMPLETE') }
|
33
|
-
let(:stack2) { double(:stack2, template_body: '{}', template_hash: {}, template_format: :json, parameters_with_defaults: {a: 1}, stack_status: 'CREATE_COMPLETE') }
|
34
|
-
let(:proposed_stack1) { double(:proposed_stack1, template_body: "{}", template_format: :json, parameters_with_defaults: {a: 1}) }
|
35
|
-
let(:proposed_stack2) { double(:proposed_stack2, template_body: "{}", template_format: :json, parameters_with_defaults: {a: 1}) }
|
36
|
-
|
37
|
-
it "returns the status of call stacks" do
|
38
|
-
out = "REGION | STACK_NAME | STACK_STATUS | DIFFERENT\n----------|------------|-----------------|----------\nus-east-1 | stack1 | UPDATE_COMPLETE | Yes \nus-east-1 | stack2 | CREATE_COMPLETE | No \n * No echo parameters can't be diffed\n"
|
39
|
-
expect { status.perform }.to output(out).to_stdout
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
RSpec.describe StackMaster::Commands::Validate do
|
2
|
-
|
3
|
-
subject(:validate) { described_class.new(config, stack_definition, options) }
|
4
|
-
let(:config) { instance_double(StackMaster::Config) }
|
5
|
-
let(:region) { "us-east-1" }
|
6
|
-
let(:stack_name) { "mystack" }
|
7
|
-
let(:options) { }
|
8
|
-
let(:stack_definition) do
|
9
|
-
StackMaster::StackDefinition.new(
|
10
|
-
region: region,
|
11
|
-
stack_name: stack_name,
|
12
|
-
template: 'myapp_vpc.json',
|
13
|
-
tags: { 'environment' => 'production' },
|
14
|
-
base_dir: File.expand_path('spec/fixtures')
|
15
|
-
)
|
16
|
-
end
|
17
|
-
|
18
|
-
describe "#perform" do
|
19
|
-
context "can find stack" do
|
20
|
-
it "calls the validator to validate the stack definition" do
|
21
|
-
expect(StackMaster::Validator).to receive(:valid?).with(stack_definition, config)
|
22
|
-
validate.perform
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
@@ -1,153 +0,0 @@
|
|
1
|
-
RSpec.describe StackMaster::Config do
|
2
|
-
subject(:loaded_config) { StackMaster::Config.load!('spec/fixtures/stack_master.yml') }
|
3
|
-
let(:base_dir) { File.expand_path('spec/fixtures') }
|
4
|
-
let(:myapp_vpc_definition) {
|
5
|
-
StackMaster::StackDefinition.new(
|
6
|
-
region: 'us-east-1',
|
7
|
-
region_alias: 'production',
|
8
|
-
stack_name: 'myapp-vpc',
|
9
|
-
template: 'myapp_vpc.json',
|
10
|
-
tags: { 'application' => 'my-awesome-blog', 'environment' => 'production' },
|
11
|
-
s3: { 'bucket' => 'my-bucket', 'region' => 'us-east-1' },
|
12
|
-
notification_arns: ['test_arn', 'test_arn_2'],
|
13
|
-
role_arn: 'test_service_role_arn2',
|
14
|
-
base_dir: base_dir,
|
15
|
-
secret_file: 'production.yml.gpg',
|
16
|
-
stack_policy_file: 'my_policy.json',
|
17
|
-
additional_parameter_lookup_dirs: ['production']
|
18
|
-
)
|
19
|
-
}
|
20
|
-
|
21
|
-
describe ".load!" do
|
22
|
-
it "fails to load the config if no stack_master.yml in parent directories" do
|
23
|
-
expect { StackMaster::Config.load!('stack_master.yml') }.to raise_error Errno::ENOENT
|
24
|
-
end
|
25
|
-
|
26
|
-
it "searches up the tree for stack master yaml" do
|
27
|
-
begin
|
28
|
-
orig_dir = Dir.pwd
|
29
|
-
Dir.chdir './spec/fixtures/templates'
|
30
|
-
expect(StackMaster::Config.load!('stack_master.yml')).to_not be_nil
|
31
|
-
ensure
|
32
|
-
Dir.chdir orig_dir
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe '#find_stack' do
|
38
|
-
it 'returns an object that can find stack definitions' do
|
39
|
-
stack = loaded_config.find_stack('us-east-1', 'myapp-vpc')
|
40
|
-
expect(stack).to eq(myapp_vpc_definition)
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'can find things with underscores instead of hyphens' do
|
44
|
-
stack = loaded_config.find_stack('us_east_1', 'myapp_vpc')
|
45
|
-
expect(stack).to eq(myapp_vpc_definition)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
describe '#filter' do
|
50
|
-
it 'returns a list of stack definitions' do
|
51
|
-
stack = loaded_config.filter('us-east-1', 'myapp-vpc')
|
52
|
-
expect(stack).to eq([myapp_vpc_definition])
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'can filter by region only' do
|
56
|
-
stacks = loaded_config.filter('us-east-1')
|
57
|
-
expect(stacks.size).to eq 3
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'can return all stack definitions with no filters' do
|
61
|
-
stacks = loaded_config.filter
|
62
|
-
expect(stacks.size).to eq 5
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'exposes the base_dir' do
|
67
|
-
expect(loaded_config.base_dir).to eq base_dir
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'loads stack defaults' do
|
71
|
-
expect(loaded_config.stack_defaults).to eq({
|
72
|
-
'tags' => { 'application' => 'my-awesome-blog' },
|
73
|
-
's3' => { 'bucket' => 'my-bucket', 'region' => 'us-east-1' }
|
74
|
-
})
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'loads template compiler mappings' do
|
78
|
-
expect(loaded_config.template_compilers).to eq({
|
79
|
-
rb: :ruby_dsl,
|
80
|
-
json: :json,
|
81
|
-
yml: :yaml,
|
82
|
-
yaml: :yaml,
|
83
|
-
|
84
|
-
})
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'loads region defaults' do
|
88
|
-
expect(loaded_config.region_defaults).to eq({
|
89
|
-
'us-east-1' => {
|
90
|
-
'tags' => { 'environment' => 'production' },
|
91
|
-
'role_arn' => 'test_service_role_arn',
|
92
|
-
'notification_arns' => ['test_arn'],
|
93
|
-
'secret_file' => 'production.yml.gpg',
|
94
|
-
'stack_policy_file' => 'my_policy.json'
|
95
|
-
},
|
96
|
-
'ap-southeast-2' => {
|
97
|
-
'tags' => {'environment' => 'staging', 'test_override' => 1 },
|
98
|
-
'role_arn' => 'test_service_role_arn3',
|
99
|
-
'notification_arns' => ['test_arn_3'],
|
100
|
-
'secret_file' => 'staging.yml.gpg'
|
101
|
-
}
|
102
|
-
})
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'loads region_aliases' do
|
106
|
-
expect(loaded_config.region_aliases).to eq(
|
107
|
-
'production' => 'us-east-1',
|
108
|
-
'staging' => 'ap-southeast-2'
|
109
|
-
)
|
110
|
-
end
|
111
|
-
|
112
|
-
it 'deep merges stack attributes' do
|
113
|
-
expect(loaded_config.find_stack('ap-southeast-2', 'myapp-vpc')).to eq(StackMaster::StackDefinition.new(
|
114
|
-
stack_name: 'myapp-vpc',
|
115
|
-
region: 'ap-southeast-2',
|
116
|
-
region_alias: 'staging',
|
117
|
-
tags: {
|
118
|
-
'application' => 'my-awesome-blog',
|
119
|
-
'environment' => 'staging',
|
120
|
-
'test_override' => 1
|
121
|
-
},
|
122
|
-
s3: { 'bucket' => 'my-bucket', 'region' => 'us-east-1' },
|
123
|
-
role_arn: 'test_service_role_arn4',
|
124
|
-
notification_arns: ['test_arn_3', 'test_arn_4'],
|
125
|
-
template: 'myapp_vpc.rb',
|
126
|
-
base_dir: base_dir,
|
127
|
-
secret_file: 'staging.yml.gpg',
|
128
|
-
additional_parameter_lookup_dirs: ['staging']
|
129
|
-
))
|
130
|
-
expect(loaded_config.find_stack('ap-southeast-2', 'myapp-web')).to eq(StackMaster::StackDefinition.new(
|
131
|
-
stack_name: 'myapp-web',
|
132
|
-
region: 'ap-southeast-2',
|
133
|
-
region_alias: 'staging',
|
134
|
-
tags: {
|
135
|
-
'application' => 'my-awesome-blog',
|
136
|
-
'environment' => 'staging',
|
137
|
-
'test_override' => 2
|
138
|
-
},
|
139
|
-
s3: { 'bucket' => 'my-bucket', 'region' => 'us-east-1' },
|
140
|
-
role_arn: 'test_service_role_arn3',
|
141
|
-
notification_arns: ['test_arn_3'],
|
142
|
-
template: 'myapp_web',
|
143
|
-
base_dir: base_dir,
|
144
|
-
secret_file: 'staging.yml.gpg',
|
145
|
-
additional_parameter_lookup_dirs: ['staging']
|
146
|
-
))
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'allows region aliases in region defaults' do
|
150
|
-
config = StackMaster::Config.new({'region_aliases' => { 'production' => 'us-east-1' }, 'region_defaults' => { 'production' => { 'secret_file' => 'production.yml.gpg' }}, 'stacks' => {}}, '/base')
|
151
|
-
expect(config.region_defaults).to eq('us-east-1' => { 'secret_file' => 'production.yml.gpg' })
|
152
|
-
end
|
153
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
RSpec.describe StackMaster::PagedResponseAccumulator do
|
2
|
-
let(:cf) { Aws::CloudFormation::Client.new }
|
3
|
-
subject(:accumulator) { described_class.new(cf, :describe_stack_events, { stack_name: 'blah' }, :stack_events) }
|
4
|
-
|
5
|
-
context 'with one page' do
|
6
|
-
let(:page_one_events) { [
|
7
|
-
{ event_id: '1', stack_id: '1', stack_name: 'blah', timestamp: Time.now},
|
8
|
-
{ event_id: '2', stack_id: '1', stack_name: 'blah', timestamp: Time.now}
|
9
|
-
] }
|
10
|
-
|
11
|
-
before do
|
12
|
-
cf.stub_responses(:describe_stack_events, { stack_events: page_one_events, next_token: nil })
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'returns the first page' do
|
16
|
-
events = accumulator.call
|
17
|
-
expect(events.stack_events.count).to eq 2
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
context 'with two pages' do
|
22
|
-
let(:page_one_events) { [
|
23
|
-
{ event_id: '1', stack_id: '1', stack_name: 'blah', timestamp: Time.now},
|
24
|
-
{ event_id: '2', stack_id: '1', stack_name: 'blah', timestamp: Time.now}
|
25
|
-
] }
|
26
|
-
let(:page_two_events) { [
|
27
|
-
{ event_id: '3', stack_id: '1', stack_name: 'blah', timestamp: Time.now}
|
28
|
-
] }
|
29
|
-
|
30
|
-
before do
|
31
|
-
cf.stub_responses(:describe_stack_events, { stack_events: page_one_events, next_token: 'blah' }, { stack_events: page_two_events } )
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'returns all the stack events combined' do
|
35
|
-
events = accumulator.call
|
36
|
-
expect(events.stack_events.count).to eq 3
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,110 +0,0 @@
|
|
1
|
-
RSpec.describe StackMaster::ParameterLoader do
|
2
|
-
let(:stack_file_name) { '/base_dir/parameters/stack_name.yml' }
|
3
|
-
let(:region_file_name) { '/base_dir/parameters/us-east-1/stack_name.yml' }
|
4
|
-
|
5
|
-
subject(:parameters) { StackMaster::ParameterLoader.load([stack_file_name, region_file_name]) }
|
6
|
-
|
7
|
-
before do
|
8
|
-
file_mock(stack_file_name, stack_file_returns)
|
9
|
-
file_mock(region_file_name, region_file_returns)
|
10
|
-
end
|
11
|
-
|
12
|
-
context 'no parameter file' do
|
13
|
-
let(:stack_file_returns) { {exists: false} }
|
14
|
-
let(:region_file_returns) { {exists: false} }
|
15
|
-
|
16
|
-
it 'returns empty parameters' do
|
17
|
-
expect(parameters).to eq(template_parameters: {}, compile_time_parameters: {})
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
context 'an empty stack parameter file' do
|
22
|
-
let(:stack_file_returns) { {exists: true, read: ''} }
|
23
|
-
let(:region_file_returns) { {exists: false} }
|
24
|
-
|
25
|
-
it 'returns an empty hash' do
|
26
|
-
expect(parameters).to eq({template_parameters: {}, compile_time_parameters: {}})
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
context 'stack parameter file' do
|
31
|
-
let(:stack_file_returns) { {exists: true, read: 'Param1: value1'} }
|
32
|
-
let(:region_file_returns) { {exists: false} }
|
33
|
-
|
34
|
-
it 'returns params from stack_name.yml' do
|
35
|
-
expect(parameters).to eq(template_parameters: {'Param1' => 'value1'}, compile_time_parameters: {})
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
context 'region parameter file' do
|
40
|
-
let(:stack_file_returns) { {exists: false } }
|
41
|
-
let(:region_file_returns) { {exists: true, read: 'Param2: value2'} }
|
42
|
-
|
43
|
-
it 'returns params from the region base stack_name.yml' do
|
44
|
-
expect(parameters).to eq(template_parameters: {'Param2' => 'value2'}, compile_time_parameters: {})
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
context 'stack and region parameter file' do
|
49
|
-
let(:stack_file_returns) { {exists: true, read: "Param1: value1\nParam2: valueX" } }
|
50
|
-
let(:region_file_returns) { {exists: true, read: 'Param2: value2'} }
|
51
|
-
|
52
|
-
it 'returns params from the region base stack_name.yml' do
|
53
|
-
expect(parameters).to eq(template_parameters: {'Param1' => 'value1', 'Param2' => 'value2'}, compile_time_parameters: {})
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
context 'yml and yaml region parameter files' do
|
58
|
-
let(:stack_file_returns) { {exists: false} }
|
59
|
-
let(:region_file_returns) { {exists: true, read: "Param2: value2"} }
|
60
|
-
let(:region_yaml_file_returns) { {exists: true, read: "Param1: value1\nParam2: valueX"} }
|
61
|
-
let(:region_yaml_file_name) { "/base_dir/parameters/us-east-1/stack_name.yaml" }
|
62
|
-
|
63
|
-
subject(:parameters) { StackMaster::ParameterLoader.load([stack_file_name, region_yaml_file_name, region_file_name]) }
|
64
|
-
|
65
|
-
before do
|
66
|
-
file_mock(region_yaml_file_name, region_yaml_file_returns)
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'returns params from the region base stack_name.yml' do
|
70
|
-
expect(parameters).to eq(template_parameters: {'Param1' => 'value1', 'Param2' => 'value2'}, compile_time_parameters: {})
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
context 'compile time parameters' do
|
75
|
-
|
76
|
-
context 'stack parameter file' do
|
77
|
-
let(:stack_file_returns) { {exists: true, read: "Param1: value1\nCompileTimeParameters:\n Param2: value2" } }
|
78
|
-
let(:region_file_returns) { {exists: false} }
|
79
|
-
|
80
|
-
it 'returns params from stack_name.yml' do
|
81
|
-
expect(parameters).to eq(template_parameters: {'Param1' => 'value1'}, compile_time_parameters: {'Param2' => 'value2'})
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
context 'stack and region parameter file' do
|
86
|
-
let(:stack_file_returns) { {exists: true, read: "Param1: value1\nCompileTimeParameters:\n Param2: valueX" } }
|
87
|
-
let(:region_file_returns) { {exists: true, read: "CompileTimeParameters:\n Param2: value2"} }
|
88
|
-
|
89
|
-
it 'returns params from the region base stack_name.yml' do
|
90
|
-
expect(parameters).to eq(template_parameters: {'Param1' => 'value1'}, compile_time_parameters: {'Param2' => 'value2'})
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
end
|
95
|
-
|
96
|
-
context 'underscored parameter names' do
|
97
|
-
let(:stack_file_returns) { {exists: true, read: 'vpc_id: vpc-xxxxxx' } }
|
98
|
-
let(:region_file_returns) { {exists: false} }
|
99
|
-
|
100
|
-
it 'camelcases them' do
|
101
|
-
expect(parameters).to eq(template_parameters: {'VpcId' => 'vpc-xxxxxx'}, compile_time_parameters: {})
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def file_mock(file_name, exists: false, read: nil)
|
106
|
-
allow(File).to receive(:exists?).with(file_name).and_return(exists)
|
107
|
-
allow(File).to receive(:read).with(file_name).and_return(read) if read
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|
@@ -1,148 +0,0 @@
|
|
1
|
-
RSpec.describe StackMaster::ParameterResolver do
|
2
|
-
subject(:parameter_resolver) { StackMaster::ParameterResolver.new(config, region, params) }
|
3
|
-
let(:params) do
|
4
|
-
{
|
5
|
-
param: { my_resolver: 2 }
|
6
|
-
}
|
7
|
-
end
|
8
|
-
let(:config) { double }
|
9
|
-
let(:region) { 'us-east-1' }
|
10
|
-
let(:my_resolver) {
|
11
|
-
Class.new do
|
12
|
-
def initialize(config, region)
|
13
|
-
end
|
14
|
-
|
15
|
-
def resolve(value)
|
16
|
-
value.to_i * 5
|
17
|
-
end
|
18
|
-
end
|
19
|
-
}
|
20
|
-
let(:bad_resolver) {
|
21
|
-
Class.new do
|
22
|
-
def initialize(config, region)
|
23
|
-
end
|
24
|
-
|
25
|
-
def resolve(value)
|
26
|
-
raise Aws::CloudFormation::Errors::ValidationError.new(nil, "Can't find stack")
|
27
|
-
end
|
28
|
-
end
|
29
|
-
}
|
30
|
-
|
31
|
-
before do
|
32
|
-
stub_const('StackMaster::ParameterResolvers::MyResolver', my_resolver)
|
33
|
-
stub_const('StackMaster::ParameterResolvers::BadResolver', bad_resolver)
|
34
|
-
end
|
35
|
-
|
36
|
-
def resolve(params)
|
37
|
-
StackMaster::ParameterResolver.resolve(config, 'us-east-1', params)
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'returns the same value for strings' do
|
41
|
-
expect(resolve(param1: 'value1')).to eq(param1: 'value1')
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'returns integers as strings' do
|
45
|
-
expect(resolve(param1: 2)).to eq(param1: '2')
|
46
|
-
end
|
47
|
-
|
48
|
-
it 'joins arrays into comma separated strings' do
|
49
|
-
expect(resolve(param1: [1, 2])).to eq(param1: '1,2')
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'converts boolean values to strings' do
|
53
|
-
expect(resolve(param1: true)).to eq(param1: 'true')
|
54
|
-
expect(resolve(param1: false)).to eq(param1: 'false')
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'it throws an error when the hash contains more than one key' do
|
58
|
-
expect {
|
59
|
-
resolve(param: { nested1: 'value1', nested2: 'value2' })
|
60
|
-
}.to raise_error(StackMaster::ParameterResolver::InvalidParameter)
|
61
|
-
end
|
62
|
-
|
63
|
-
it "doesn't throw an error when given an array" do
|
64
|
-
expect {
|
65
|
-
resolve(param: [1, 2])
|
66
|
-
}.to_not raise_error
|
67
|
-
end
|
68
|
-
|
69
|
-
context 'when array values contain resolver hashes' do
|
70
|
-
it 'returns the comma separated string values returned by the resolvers' do
|
71
|
-
expect(resolve(param: [1, { my_resolver: 2 }])).to eq(param: '1,10')
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'returns nested array values' do
|
75
|
-
expect(resolve(param: [[1, { my_resolver: 3 }], { my_resolver: 2 }])).to eq(param: '1,15,10')
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
context 'when given a proper resolve hash' do
|
80
|
-
it 'returns the value returned by the resolver as the parameter value' do
|
81
|
-
expect(resolve(param: { my_resolver: 2 })).to eq(param: 10)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
context 'when the resolver is unknown' do
|
86
|
-
it 'throws an error' do
|
87
|
-
expect {
|
88
|
-
resolve(param: { my_unknown_resolver: 2 })
|
89
|
-
}.to raise_error StackMaster::ParameterResolver::ResolverNotFound
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
context 'when the resolver throws a ValidationError' do
|
94
|
-
it 'throws a invalid parameter error' do
|
95
|
-
expect {
|
96
|
-
resolve(param: { bad_resolver: 2 })
|
97
|
-
}.to raise_error StackMaster::ParameterResolver::InvalidParameter
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
context 'resolver class caching' do
|
102
|
-
it "uses the same instance of the resolver for the duration of the resolve run" do
|
103
|
-
expect(my_resolver).to receive(:new).once.and_call_original
|
104
|
-
expect(resolve(param: { my_resolver: 2 }, param2: { my_resolver: 2 })).to eq(param: 10, param2: 10)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
context 'when the resolver class already exist' do
|
109
|
-
it 'does not try to load it' do
|
110
|
-
expect(parameter_resolver).to receive(:load_parameter_resolver).once.and_call_original
|
111
|
-
expect(parameter_resolver).not_to receive(:require_parameter_resolver)
|
112
|
-
|
113
|
-
parameter_resolver.resolve
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
context 'when the resolver class does not exist' do
|
118
|
-
let(:params) do
|
119
|
-
{
|
120
|
-
param: { dummy_resolver: 2 }
|
121
|
-
}
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'tries to load it' do
|
125
|
-
expect(parameter_resolver).to receive(:load_parameter_resolver).once.and_call_original
|
126
|
-
expect(parameter_resolver).to receive(:require_parameter_resolver).and_return nil
|
127
|
-
expect(parameter_resolver).to receive(:call_resolver).and_return nil
|
128
|
-
|
129
|
-
parameter_resolver.resolve
|
130
|
-
end
|
131
|
-
|
132
|
-
context "using an array resolver" do
|
133
|
-
let(:params) do
|
134
|
-
{
|
135
|
-
param: { other_dummy_resolvers: [1, 2] }
|
136
|
-
}
|
137
|
-
end
|
138
|
-
|
139
|
-
it "tries to load the plural and singular forms" do
|
140
|
-
expect(parameter_resolver).to receive(:require_parameter_resolver).with("other_dummy_resolvers").once.and_call_original.ordered
|
141
|
-
expect(parameter_resolver).to receive(:require_parameter_resolver).with("other_dummy_resolver").once.ordered
|
142
|
-
expect(parameter_resolver).to receive(:call_resolver).and_return nil
|
143
|
-
|
144
|
-
parameter_resolver.resolve
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|