stack_master 0.0.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 +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +208 -0
- data/Rakefile +11 -0
- data/apply_demo.gif +0 -0
- data/bin/stack_master +16 -0
- data/example/simple/Gemfile +3 -0
- data/example/simple/parameters/myapp_vpc.yml +1 -0
- data/example/simple/parameters/myapp_web.yml +2 -0
- data/example/simple/stack_master.yml +13 -0
- data/example/simple/templates/myapp_vpc.rb +39 -0
- data/example/simple/templates/myapp_web.rb +16 -0
- data/features/apply.feature +241 -0
- data/features/delete.feature +43 -0
- data/features/diff.feature +191 -0
- data/features/events.feature +38 -0
- data/features/init.feature +6 -0
- data/features/outputs.feature +49 -0
- data/features/region_aliases.feature +66 -0
- data/features/resources.feature +45 -0
- data/features/stack_defaults.feature +88 -0
- data/features/status.feature +124 -0
- data/features/step_definitions/stack_steps.rb +50 -0
- data/features/support/env.rb +14 -0
- data/lib/stack_master.rb +81 -0
- data/lib/stack_master/aws_driver/cloud_formation.rb +56 -0
- data/lib/stack_master/cli.rb +164 -0
- data/lib/stack_master/command.rb +13 -0
- data/lib/stack_master/commands/apply.rb +104 -0
- data/lib/stack_master/commands/delete.rb +53 -0
- data/lib/stack_master/commands/diff.rb +31 -0
- data/lib/stack_master/commands/events.rb +39 -0
- data/lib/stack_master/commands/init.rb +109 -0
- data/lib/stack_master/commands/list_stacks.rb +16 -0
- data/lib/stack_master/commands/outputs.rb +27 -0
- data/lib/stack_master/commands/resources.rb +33 -0
- data/lib/stack_master/commands/status.rb +47 -0
- data/lib/stack_master/commands/validate.rb +17 -0
- data/lib/stack_master/config.rb +86 -0
- data/lib/stack_master/ctrl_c.rb +4 -0
- data/lib/stack_master/parameter_loader.rb +17 -0
- data/lib/stack_master/parameter_resolver.rb +45 -0
- data/lib/stack_master/parameter_resolvers/secret.rb +42 -0
- data/lib/stack_master/parameter_resolvers/security_group.rb +20 -0
- data/lib/stack_master/parameter_resolvers/sns_topic_name.rb +29 -0
- data/lib/stack_master/parameter_resolvers/stack_output.rb +53 -0
- data/lib/stack_master/prompter.rb +14 -0
- data/lib/stack_master/security_group_finder.rb +29 -0
- data/lib/stack_master/sns_topic_finder.rb +27 -0
- data/lib/stack_master/stack.rb +96 -0
- data/lib/stack_master/stack_definition.rb +49 -0
- data/lib/stack_master/stack_differ.rb +80 -0
- data/lib/stack_master/stack_events/fetcher.rb +45 -0
- data/lib/stack_master/stack_events/presenter.rb +27 -0
- data/lib/stack_master/stack_events/streamer.rb +55 -0
- data/lib/stack_master/stack_states.rb +34 -0
- data/lib/stack_master/template_compiler.rb +21 -0
- data/lib/stack_master/test_driver/cloud_formation.rb +139 -0
- data/lib/stack_master/testing.rb +7 -0
- data/lib/stack_master/utils.rb +31 -0
- data/lib/stack_master/validator.rb +25 -0
- data/lib/stack_master/version.rb +3 -0
- data/logo.png +0 -0
- data/script/buildkite/bundle.sh +5 -0
- data/script/buildkite/clean.sh +3 -0
- data/script/buildkite_rspec.sh +27 -0
- data/spec/fixtures/parameters/myapp_vpc.yml +1 -0
- data/spec/fixtures/stack_master.yml +35 -0
- data/spec/fixtures/templates/myapp_vpc.json +1 -0
- data/spec/spec_helper.rb +99 -0
- data/spec/stack_master/commands/apply_spec.rb +92 -0
- data/spec/stack_master/commands/delete_spec.rb +40 -0
- data/spec/stack_master/commands/init_spec.rb +17 -0
- data/spec/stack_master/commands/status_spec.rb +38 -0
- data/spec/stack_master/commands/validate_spec.rb +26 -0
- data/spec/stack_master/config_spec.rb +81 -0
- data/spec/stack_master/parameter_loader_spec.rb +81 -0
- data/spec/stack_master/parameter_resolver_spec.rb +58 -0
- data/spec/stack_master/parameter_resolvers/secret_spec.rb +66 -0
- data/spec/stack_master/parameter_resolvers/security_group_spec.rb +17 -0
- data/spec/stack_master/parameter_resolvers/sns_topic_name_spec.rb +43 -0
- data/spec/stack_master/parameter_resolvers/stack_output_spec.rb +77 -0
- data/spec/stack_master/security_group_finder_spec.rb +49 -0
- data/spec/stack_master/sns_topic_finder_spec.rb +25 -0
- data/spec/stack_master/stack_definition_spec.rb +37 -0
- data/spec/stack_master/stack_differ_spec.rb +34 -0
- data/spec/stack_master/stack_events/fetcher_spec.rb +65 -0
- data/spec/stack_master/stack_events/presenter_spec.rb +18 -0
- data/spec/stack_master/stack_events/streamer_spec.rb +33 -0
- data/spec/stack_master/stack_spec.rb +157 -0
- data/spec/stack_master/template_compiler_spec.rb +48 -0
- data/spec/stack_master/test_driver/cloud_formation_spec.rb +24 -0
- data/spec/stack_master/utils_spec.rb +30 -0
- data/spec/stack_master/validator_spec.rb +38 -0
- data/stack_master.gemspec +38 -0
- data/stacktemplates/parameter_region.yml +3 -0
- data/stacktemplates/parameter_stack_name.yml +3 -0
- data/stacktemplates/stack.json.erb +20 -0
- data/stacktemplates/stack_master.yml.erb +6 -0
- metadata +427 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
module StackMaster
|
|
2
|
+
module Commands
|
|
3
|
+
class Apply
|
|
4
|
+
include Command
|
|
5
|
+
include Commander::UI
|
|
6
|
+
include StackMaster::Prompter
|
|
7
|
+
|
|
8
|
+
def initialize(config, stack_definition, options = {})
|
|
9
|
+
@config = config
|
|
10
|
+
@stack_definition = stack_definition
|
|
11
|
+
@from_time = Time.now
|
|
12
|
+
@updating = false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def perform
|
|
16
|
+
diff_stacks
|
|
17
|
+
unless ask?("Continue and apply the stack (y/n)? ")
|
|
18
|
+
StackMaster.stdout.puts "Stack update aborted"
|
|
19
|
+
return
|
|
20
|
+
end
|
|
21
|
+
begin
|
|
22
|
+
return if stack_too_big
|
|
23
|
+
create_or_update_stack
|
|
24
|
+
tail_stack_events
|
|
25
|
+
rescue StackMaster::CtrlC
|
|
26
|
+
cancel
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def cf
|
|
33
|
+
@cf ||= StackMaster.cloud_formation_driver
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def stack
|
|
37
|
+
@stack ||= Stack.find(@stack_definition.region, @stack_definition.stack_name)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def proposed_stack
|
|
41
|
+
@proposed_stack ||= Stack.generate(@stack_definition, @config)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def stack_exists?
|
|
45
|
+
!stack.nil?
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def diff_stacks
|
|
49
|
+
StackDiffer.new(proposed_stack, stack).output_diff
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def cancel
|
|
53
|
+
if @updating
|
|
54
|
+
if ask?("Cancel stack update?")
|
|
55
|
+
StackMaster.stdout.puts "Attempting to cancel stack update"
|
|
56
|
+
cf.cancel_update_stack({stack_name: @stack_definition.stack_name})
|
|
57
|
+
tail_stack_events
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def create_or_update_stack
|
|
63
|
+
if stack_exists?
|
|
64
|
+
update_stack
|
|
65
|
+
else
|
|
66
|
+
create_stack
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def stack_too_big
|
|
71
|
+
if proposed_stack.too_big?
|
|
72
|
+
StackMaster.stdout.puts 'The (space compressed) stack is larger than the limit set by AWS. See http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-limits.html'
|
|
73
|
+
true
|
|
74
|
+
else
|
|
75
|
+
false
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def update_stack
|
|
80
|
+
@updating = true
|
|
81
|
+
cf.update_stack(stack_options)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def create_stack
|
|
85
|
+
cf.create_stack(stack_options.merge(tags: proposed_stack.aws_tags))
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def stack_options
|
|
89
|
+
{
|
|
90
|
+
stack_name: @stack_definition.stack_name,
|
|
91
|
+
template_body: proposed_stack.maybe_compressed_template_body,
|
|
92
|
+
parameters: proposed_stack.aws_parameters,
|
|
93
|
+
capabilities: ['CAPABILITY_IAM'],
|
|
94
|
+
notification_arns: proposed_stack.notification_arns,
|
|
95
|
+
stack_policy_body: proposed_stack.stack_policy_body
|
|
96
|
+
}
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def tail_stack_events
|
|
100
|
+
StackEvents::Streamer.stream(@stack_definition.stack_name, @stack_definition.region, io: StackMaster.stdout, from: @from_time)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module StackMaster
|
|
2
|
+
module Commands
|
|
3
|
+
class Delete
|
|
4
|
+
include Command
|
|
5
|
+
include StackMaster::Prompter
|
|
6
|
+
|
|
7
|
+
def initialize(region, stack_name)
|
|
8
|
+
@region = region
|
|
9
|
+
@stack_name = stack_name
|
|
10
|
+
@from_time = Time.now
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def perform
|
|
14
|
+
|
|
15
|
+
return unless check_exists
|
|
16
|
+
|
|
17
|
+
unless ask?("Really delete stack (y/n)? ")
|
|
18
|
+
StackMaster.stdout.puts "Stack update aborted"
|
|
19
|
+
return
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
delete_stack
|
|
23
|
+
tail_stack_events
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def delete_stack
|
|
29
|
+
cf.delete_stack({stack_name: @stack_name})
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def check_exists
|
|
33
|
+
cf.describe_stacks({stack_name: @stack_name})
|
|
34
|
+
true
|
|
35
|
+
rescue Aws::CloudFormation::Errors::ValidationError
|
|
36
|
+
StackMaster.stdout.puts "Stack does not exist"
|
|
37
|
+
false
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def cf
|
|
41
|
+
StackMaster.cloud_formation_driver
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def tail_stack_events
|
|
45
|
+
StackEvents::Streamer.stream(@stack_name, @region, io: StackMaster.stdout, from: @from_time)
|
|
46
|
+
StackMaster.stdout.puts "Stack deleted"
|
|
47
|
+
rescue Aws::CloudFormation::Errors::ValidationError
|
|
48
|
+
# Unfortunately the stack as a tendency of going away before we get the final delete event.
|
|
49
|
+
StackMaster.stdout.puts "Stack deleted"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module StackMaster
|
|
2
|
+
module Commands
|
|
3
|
+
class Diff
|
|
4
|
+
include Command
|
|
5
|
+
include Commander::UI
|
|
6
|
+
|
|
7
|
+
def initialize(config, stack_definition, options = {})
|
|
8
|
+
@config = config
|
|
9
|
+
@stack_definition = stack_definition
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def perform
|
|
13
|
+
StackMaster::StackDiffer.new(proposed_stack, stack).output_diff
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def stack_definition
|
|
19
|
+
@stack_definition ||= @config.find_stack(@region, @stack_name)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def stack
|
|
23
|
+
@stack ||= Stack.find(@stack_definition.region, @stack_definition.stack_name)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def proposed_stack
|
|
27
|
+
@proposed_stack ||= Stack.generate(stack_definition, @config)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module StackMaster
|
|
2
|
+
module Commands
|
|
3
|
+
class Events
|
|
4
|
+
include Command
|
|
5
|
+
include Commander::UI
|
|
6
|
+
|
|
7
|
+
def initialize(config, stack_definition, options = {})
|
|
8
|
+
@config = config
|
|
9
|
+
@stack_definition = stack_definition
|
|
10
|
+
@options = options
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def perform
|
|
14
|
+
events = StackEvents::Fetcher.fetch(@stack_definition.stack_name, @stack_definition.region)
|
|
15
|
+
filter_events(events).each do |event|
|
|
16
|
+
StackEvents::Presenter.print_event(StackMaster.stdout, event)
|
|
17
|
+
end
|
|
18
|
+
if @options.tail
|
|
19
|
+
StackEvents::Streamer.stream(@stack_definition.stack_name, @stack_definition.region, io: StackMaster.stdout)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def filter_events(events)
|
|
26
|
+
if @options.all
|
|
27
|
+
events
|
|
28
|
+
else
|
|
29
|
+
n = @options.number || 25
|
|
30
|
+
from = events.count - n
|
|
31
|
+
if from < 0
|
|
32
|
+
from = 0
|
|
33
|
+
end
|
|
34
|
+
events[from..-1]
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
module StackMaster
|
|
2
|
+
module Commands
|
|
3
|
+
class Init
|
|
4
|
+
include Command
|
|
5
|
+
|
|
6
|
+
def initialize(overwrite, region, stack_name)
|
|
7
|
+
@overwrite = overwrite
|
|
8
|
+
@region = region
|
|
9
|
+
@stack_name = stack_name
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def perform
|
|
13
|
+
if check_files
|
|
14
|
+
create_stack_master_yml
|
|
15
|
+
create_stack_json_yml
|
|
16
|
+
create_parameters_yml
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def check_files
|
|
23
|
+
@stack_master_filename = "stack_master.yml"
|
|
24
|
+
@stack_json_filename = "templates/#{@stack_name}.json"
|
|
25
|
+
@parameters_filename = File.join("parameters", "#{underscored_stack_name}.yml")
|
|
26
|
+
@region_parameters_filename = File.join("parameters", @region, "#{underscored_stack_name}.yml")
|
|
27
|
+
|
|
28
|
+
if !@overwrite
|
|
29
|
+
[@stack_master_filename, @stack_json_filename, @parameters_filename, @region_parameters_filename].each do |filename|
|
|
30
|
+
if File.exists?(filename)
|
|
31
|
+
StackMaster.stderr.puts("Aborting: #{filename} already exists. Use --overwrite to force overwriting file.")
|
|
32
|
+
return false
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def create_stack_json_yml
|
|
40
|
+
StackMaster.stdout.puts "Writing #{@stack_json_filename}"
|
|
41
|
+
FileUtils.mkdir_p(File.dirname(@stack_json_filename))
|
|
42
|
+
IO.write(@stack_json_filename, stack_json_output)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def stack_json_output
|
|
46
|
+
render ERB.new(File.read(stack_json_template))
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def stack_json_template
|
|
50
|
+
File.join(StackMaster.base_dir, "stacktemplates", "stack.json.erb")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def create_stack_master_yml
|
|
54
|
+
StackMaster.stdout.puts "Writing #{@stack_master_filename}"
|
|
55
|
+
IO.write("#{@stack_master_filename}", stack_master_yml_output)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def stack_master_yml_output
|
|
59
|
+
render ERB.new(File.read(stack_master_template))
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def stack_master_template
|
|
63
|
+
File.join(StackMaster.base_dir, "stacktemplates", "stack_master.yml.erb")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def create_parameters_yml
|
|
67
|
+
StackMaster.stdout.puts "Writing #{@parameters_filename}"
|
|
68
|
+
StackMaster.stdout.puts "Writing #{@region_parameters_filename}"
|
|
69
|
+
FileUtils.mkdir_p("parameters/#{@region}")
|
|
70
|
+
IO.write(@parameters_filename, parameter_stack_name_yml_output)
|
|
71
|
+
IO.write(@region_parameters_filename, parameter_region_yml_output)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def parameter_stack_name_yml_output
|
|
75
|
+
File.read(parameter_stack_name_template)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def parameter_region_yml_output
|
|
79
|
+
File.read(parameter_region_template)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def parameter_stack_name_template
|
|
83
|
+
File.join(StackMaster.base_dir, "stacktemplates", "parameter_stack_name.yml")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def parameter_region_template
|
|
87
|
+
File.join(StackMaster.base_dir, "stacktemplates", "parameter_region.yml")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def underscored_stack_name
|
|
91
|
+
@stack_name.gsub('-', '_')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def render(renderer)
|
|
95
|
+
binding = InitBinding.new(region: @region, stack_name: @stack_name).get_binding
|
|
96
|
+
renderer.result(binding)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
class InitBinding
|
|
100
|
+
def initialize(region:, stack_name:)
|
|
101
|
+
@region = region
|
|
102
|
+
@stack_name = stack_name
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
attr_reader :region, :stack_name
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module StackMaster
|
|
2
|
+
module Commands
|
|
3
|
+
class Outputs
|
|
4
|
+
include Command
|
|
5
|
+
include Commander::UI
|
|
6
|
+
|
|
7
|
+
def initialize(config, stack_definition, options = {})
|
|
8
|
+
@config = config
|
|
9
|
+
@stack_definition = stack_definition
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def perform
|
|
13
|
+
if stack
|
|
14
|
+
tp stack.outputs, :output_key, :output_value, :description
|
|
15
|
+
else
|
|
16
|
+
StackMaster.stdout.puts "Stack doesn't exist"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def stack
|
|
23
|
+
@stack ||= Stack.find(@stack_definition.region, @stack_definition.stack_name)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module StackMaster
|
|
2
|
+
module Commands
|
|
3
|
+
class Resources
|
|
4
|
+
include Command
|
|
5
|
+
include Commander::UI
|
|
6
|
+
|
|
7
|
+
def initialize(config, stack_definition, options = {})
|
|
8
|
+
@config = config
|
|
9
|
+
@stack_definition = stack_definition
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def perform
|
|
13
|
+
if stack_resources
|
|
14
|
+
tp stack_resources, :logical_resource_id, :resource_type, :timestamp, :resource_status, :resource_status_reason, :description
|
|
15
|
+
else
|
|
16
|
+
StackMaster.stdout.puts "Stack doesn't exist"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def stack_resources
|
|
23
|
+
@stack_resources = cf.describe_stack_resources(stack_name: @stack_definition.stack_name).stack_resources
|
|
24
|
+
rescue Aws::CloudFormation::Errors::ValidationError
|
|
25
|
+
nil
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def cf
|
|
29
|
+
@cf ||= StackMaster.cloud_formation_driver
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module StackMaster
|
|
2
|
+
module Commands
|
|
3
|
+
class Status
|
|
4
|
+
include Command
|
|
5
|
+
|
|
6
|
+
def initialize(config)
|
|
7
|
+
@config = config
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def perform
|
|
11
|
+
tp.set :io, StackMaster.stdout
|
|
12
|
+
tp @config.stacks.map { |stack_definition| get_status(stack_definition) }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def sort_params(hash)
|
|
18
|
+
hash.sort.to_h
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def get_status(stack_definition)
|
|
22
|
+
region = stack_definition.region
|
|
23
|
+
stack_name = stack_definition.stack_name
|
|
24
|
+
begin
|
|
25
|
+
driver = StackMaster.cloud_formation_driver
|
|
26
|
+
driver.set_region(region)
|
|
27
|
+
stack = Stack.find(region, stack_name)
|
|
28
|
+
if stack
|
|
29
|
+
proposed_stack = Stack.generate(stack_definition, @config)
|
|
30
|
+
differ = StackMaster::StackDiffer.new(proposed_stack, stack)
|
|
31
|
+
different = differ.body_different? || differ.params_different?
|
|
32
|
+
stack_status = stack.stack_status
|
|
33
|
+
else
|
|
34
|
+
different = true
|
|
35
|
+
stack_status = nil
|
|
36
|
+
end
|
|
37
|
+
rescue Aws::CloudFormation::Errors::ValidationError
|
|
38
|
+
stack_status = "missing"
|
|
39
|
+
different = true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
{ region: region, stack_name: stack_name, stack_status: stack_status, different: different ? "Yes" : "No" }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|