stack_master 1.5.0 → 1.6.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.
- 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
|