cfn-guardian 0.1.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 +7 -0
- data/.gitignore +12 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +52 -0
- data/LICENSE.txt +21 -0
- data/README.md +412 -0
- data/Rakefile +2 -0
- data/cfn-guardian.gemspec +39 -0
- data/exe/cfn-guardian +4 -0
- data/lib/cfnguardian.rb +146 -0
- data/lib/cfnguardian/compile.rb +116 -0
- data/lib/cfnguardian/deploy.rb +144 -0
- data/lib/cfnguardian/log.rb +40 -0
- data/lib/cfnguardian/models/alarm.rb +292 -0
- data/lib/cfnguardian/models/check.rb +114 -0
- data/lib/cfnguardian/models/event.rb +192 -0
- data/lib/cfnguardian/resources/amazonmq_broker.rb +45 -0
- data/lib/cfnguardian/resources/apigateway.rb +34 -0
- data/lib/cfnguardian/resources/application_targetgroup.rb +31 -0
- data/lib/cfnguardian/resources/autoscaling_group.rb +22 -0
- data/lib/cfnguardian/resources/base.rb +116 -0
- data/lib/cfnguardian/resources/cloudfront_distribution.rb +26 -0
- data/lib/cfnguardian/resources/domain_expiry.rb +30 -0
- data/lib/cfnguardian/resources/dynamodb_table.rb +48 -0
- data/lib/cfnguardian/resources/ec2_instance.rb +24 -0
- data/lib/cfnguardian/resources/ecs_cluster.rb +44 -0
- data/lib/cfnguardian/resources/ecs_service.rb +32 -0
- data/lib/cfnguardian/resources/elastic_file_system.rb +17 -0
- data/lib/cfnguardian/resources/elastic_loadbalancer.rb +26 -0
- data/lib/cfnguardian/resources/elasticache_replication_group.rb +45 -0
- data/lib/cfnguardian/resources/http.rb +49 -0
- data/lib/cfnguardian/resources/lambda.rb +38 -0
- data/lib/cfnguardian/resources/network_targetgroup.rb +31 -0
- data/lib/cfnguardian/resources/nrpe.rb +42 -0
- data/lib/cfnguardian/resources/rds_cluster_instance.rb +30 -0
- data/lib/cfnguardian/resources/rds_instance.rb +45 -0
- data/lib/cfnguardian/resources/redshift_cluster.rb +30 -0
- data/lib/cfnguardian/resources/sql.rb +37 -0
- data/lib/cfnguardian/resources/sqs_queue.rb +23 -0
- data/lib/cfnguardian/s3.rb +35 -0
- data/lib/cfnguardian/stacks/main.rb +149 -0
- data/lib/cfnguardian/stacks/resources.rb +80 -0
- data/lib/cfnguardian/string.rb +19 -0
- data/lib/cfnguardian/validate.rb +80 -0
- data/lib/cfnguardian/version.rb +4 -0
- metadata +215 -0
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "cfnguardian/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "cfn-guardian"
|
7
|
+
spec.version = CfnGuardian::VERSION
|
8
|
+
spec.authors = ["Guslington"]
|
9
|
+
spec.email = ["itsupport@base2services.com"]
|
10
|
+
|
11
|
+
spec.summary = %q{Manages AWS cloudwatch alarms with default templates using cloudformation}
|
12
|
+
spec.description = %q{Manages AWS cloudwatch alarms with default templates using cloudformation}
|
13
|
+
spec.homepage = "https://github.com/base2Services/cfn-guardian"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
17
|
+
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
spec.metadata["source_code_uri"] = "https://github.com/base2Services/cfn-guardian"
|
20
|
+
spec.metadata["changelog_uri"] = "https://github.com/base2Services/cfn-guardian"
|
21
|
+
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
+
end
|
27
|
+
spec.bindir = "exe"
|
28
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
29
|
+
spec.require_paths = ["lib"]
|
30
|
+
|
31
|
+
spec.add_dependency "thor", "~> 0.20"
|
32
|
+
spec.add_dependency 'cfndsl', '~> 1.0', '<2'
|
33
|
+
spec.add_dependency "terminal-table", '~> 1', '<2'
|
34
|
+
spec.add_dependency 'aws-sdk-s3', '~> 1', '<2'
|
35
|
+
spec.add_dependency 'aws-sdk-cloudformation', '~> 1', '<2'
|
36
|
+
|
37
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
38
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
39
|
+
end
|
data/exe/cfn-guardian
ADDED
data/lib/cfnguardian.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'terminal-table'
|
3
|
+
require "cfnguardian/log"
|
4
|
+
require "cfnguardian/version"
|
5
|
+
require "cfnguardian/compile"
|
6
|
+
require "cfnguardian/validate"
|
7
|
+
require "cfnguardian/deploy"
|
8
|
+
|
9
|
+
module CfnGuardian
|
10
|
+
class Cli < Thor
|
11
|
+
include Logging
|
12
|
+
|
13
|
+
map %w[--version -v] => :__print_version
|
14
|
+
desc "--version, -v", "print the version"
|
15
|
+
def __print_version
|
16
|
+
puts CfnGuardian::VERSION
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "compile", "Generate monitoring CloudFormation templates"
|
20
|
+
long_desc <<-LONG
|
21
|
+
Generates CloudFormation templates from the alarm configuration and output to the out/ directory.
|
22
|
+
LONG
|
23
|
+
method_option :config, aliases: :c, type: :string, desc: "yaml config file", required: true
|
24
|
+
method_option :validate, type: :boolean, default: true, desc: "validate cfn templates"
|
25
|
+
method_option :bucket, type: :string, desc: "provide custom bucket name, will create a default bucket if not provided"
|
26
|
+
method_option :region, aliases: :r, type: :string, desc: "set the AWS region"
|
27
|
+
|
28
|
+
def compile
|
29
|
+
set_region(options[:region],options[:validate])
|
30
|
+
s3 = CfnGuardian::S3.new(options[:bucket])
|
31
|
+
|
32
|
+
compiler = CfnGuardian::Compile.new(options,s3.bucket)
|
33
|
+
compiler.get_resources
|
34
|
+
compiler.compile_templates
|
35
|
+
logger.info "Clouformation templates compiled successfully in out/ directory"
|
36
|
+
if options[:validate]
|
37
|
+
s3.create_bucket_if_not_exists()
|
38
|
+
validator = CfnGuardian::Validate.new(s3.bucket)
|
39
|
+
if validator.validate
|
40
|
+
logger.error("One or more templates failed to validate")
|
41
|
+
exit(1)
|
42
|
+
else
|
43
|
+
logger.info "Clouformation templates were validated successfully"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
logger.warn "AWS cloudwatch alarms defined in the templates will cost roughly $#{'%.2f' % compiler.cost} per month"
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "deploy", "Generates and deploys monitoring CloudFormation templates"
|
50
|
+
long_desc <<-LONG
|
51
|
+
Generates CloudFormation templates from the alarm configuration and output to the out/ directory.
|
52
|
+
Then copies the files to the s3 bucket and deploys the cloudformation.
|
53
|
+
LONG
|
54
|
+
method_option :config, aliases: :c, type: :string, desc: "yaml config file", required: true
|
55
|
+
method_option :bucket, type: :string, desc: "provide custom bucket name, will create a default bucket if not provided"
|
56
|
+
method_option :region, aliases: :r, type: :string, desc: "set the AWS region"
|
57
|
+
method_option :stack_name, aliases: :r, type: :string, desc: "set the Cloudformation stack name. Defaults to `guardian`"
|
58
|
+
method_option :sns_critical, type: :string, desc: "sns topic arn for the critical alamrs"
|
59
|
+
method_option :sns_warning, type: :string, desc: "sns topic arn for the warning alamrs"
|
60
|
+
method_option :sns_task, type: :string, desc: "sns topic arn for the task alamrs"
|
61
|
+
method_option :sns_informational, type: :string, desc: "sns topic arn for the informational alamrs"
|
62
|
+
|
63
|
+
def deploy
|
64
|
+
set_region(options[:region],true)
|
65
|
+
s3 = CfnGuardian::S3.new(options[:bucket])
|
66
|
+
|
67
|
+
compiler = CfnGuardian::Compile.new(options,s3.bucket)
|
68
|
+
compiler.get_resources
|
69
|
+
compiler.compile_templates
|
70
|
+
logger.info "Clouformation templates compiled successfully in out/ directory"
|
71
|
+
|
72
|
+
s3.create_bucket_if_not_exists
|
73
|
+
validator = CfnGuardian::Validate.new(s3.bucket)
|
74
|
+
if validator.validate
|
75
|
+
logger.error("One or more templates failed to validate")
|
76
|
+
exit(1)
|
77
|
+
else
|
78
|
+
logger.info "Clouformation templates were validated successfully"
|
79
|
+
end
|
80
|
+
|
81
|
+
deployer = CfnGuardian::Deploy.new(options,s3.bucket)
|
82
|
+
deployer.upload_templates
|
83
|
+
change_set, change_set_type = deployer.create_change_set()
|
84
|
+
deployer.wait_for_changeset(change_set.id)
|
85
|
+
deployer.execute_change_set(change_set.id)
|
86
|
+
deployer.wait_for_execute(change_set_type)
|
87
|
+
end
|
88
|
+
|
89
|
+
desc "show-alarms", "Shows alarm settings"
|
90
|
+
long_desc <<-LONG
|
91
|
+
Displays the configured settings for each alarm. Can be filtered by resource group and alarm name.
|
92
|
+
Defaults to show all configured alarms.
|
93
|
+
LONG
|
94
|
+
method_option :config, aliases: :c, type: :string, desc: "yaml config file", required: true
|
95
|
+
method_option :group, aliases: :g, type: :string, desc: "resource group"
|
96
|
+
method_option :name, aliases: :n, type: :string, desc: "alarm name"
|
97
|
+
method_option :resource, aliases: :r, type: :string, desc: "resource id"
|
98
|
+
def show_alarms
|
99
|
+
compiler = CfnGuardian::Compile.new(options,'no-bucket')
|
100
|
+
compiler.get_resources
|
101
|
+
|
102
|
+
alarms = compiler.resources.select{|h| h[:type] == 'Alarm'}
|
103
|
+
groups = alarms.group_by{|h| h[:class]}
|
104
|
+
|
105
|
+
if options[:group]
|
106
|
+
groups = groups.fetch(options[:group],{}).group_by{|h| h[:class]}
|
107
|
+
if options[:resource]
|
108
|
+
groups = groups[options[:group]].select{|h| h[:resource] == options[:resource]}.group_by{|h| h[:class]}
|
109
|
+
end
|
110
|
+
if options[:name]
|
111
|
+
groups = groups[options[:group]].select{|h| h[:name] == options[:name]}.group_by{|h| h[:class]}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
groups.each do |grp,alarms|
|
116
|
+
puts "\n\s\s#{grp}\n"
|
117
|
+
alarms.each do |alarm|
|
118
|
+
rows = alarm.reject {|k,v| [:type,:class,:name].include?(k)}
|
119
|
+
.sort_by {|k,v| k}
|
120
|
+
puts Terminal::Table.new(
|
121
|
+
:title => alarm[:name],
|
122
|
+
:headings => ['property', 'Value'],
|
123
|
+
:rows => rows.map! {|k,v| [k,v.to_s]})
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def set_region(region,required)
|
131
|
+
if !region.nil?
|
132
|
+
Aws.config.update({region: region})
|
133
|
+
elsif !ENV['AWS_REGION'].nil?
|
134
|
+
Aws.config.update({region: ENV['AWS_REGION']})
|
135
|
+
elsif !ENV['AWS_DEFAULT_REGION'].nil?
|
136
|
+
Aws.config.update({region: ENV['AWS_DEFAULT_REGION']})
|
137
|
+
else
|
138
|
+
if required
|
139
|
+
logger.error("No AWS region found. Please suppy the region using option `--region` or setting environment variables `AWS_REGION` `AWS_DEFAULT_REGION`")
|
140
|
+
exit(1)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'cfnguardian/string'
|
3
|
+
require 'cfnguardian/stacks/resources'
|
4
|
+
require 'cfnguardian/stacks/main'
|
5
|
+
require 'cfnguardian/resources/base'
|
6
|
+
require 'cfnguardian/resources/apigateway'
|
7
|
+
require 'cfnguardian/resources/application_targetgroup'
|
8
|
+
require 'cfnguardian/resources/amazonmq_broker'
|
9
|
+
require 'cfnguardian/resources/autoscaling_group'
|
10
|
+
require 'cfnguardian/resources/cloudfront_distribution'
|
11
|
+
require 'cfnguardian/resources/autoscaling_group'
|
12
|
+
require 'cfnguardian/resources/domain_expiry'
|
13
|
+
require 'cfnguardian/resources/dynamodb_table'
|
14
|
+
require 'cfnguardian/resources/ec2_instance'
|
15
|
+
require 'cfnguardian/resources/ecs_cluster'
|
16
|
+
require 'cfnguardian/resources/ecs_service'
|
17
|
+
require 'cfnguardian/resources/elastic_file_system'
|
18
|
+
require 'cfnguardian/resources/elasticache_replication_group'
|
19
|
+
require 'cfnguardian/resources/elastic_loadbalancer'
|
20
|
+
require 'cfnguardian/resources/http'
|
21
|
+
require 'cfnguardian/resources/nrpe'
|
22
|
+
require 'cfnguardian/resources/lambda'
|
23
|
+
require 'cfnguardian/resources/network_targetgroup'
|
24
|
+
require 'cfnguardian/resources/rds_cluster_instance'
|
25
|
+
require 'cfnguardian/resources/rds_instance'
|
26
|
+
require 'cfnguardian/resources/redshift_cluster'
|
27
|
+
require 'cfnguardian/resources/sql'
|
28
|
+
require 'cfnguardian/resources/sqs_queue'
|
29
|
+
|
30
|
+
module CfnGuardian
|
31
|
+
class Compile
|
32
|
+
include Logging
|
33
|
+
|
34
|
+
attr_reader :cost, :resources
|
35
|
+
|
36
|
+
def initialize(opts,bucket)
|
37
|
+
@prefix = opts.fetch(:stack_name,'guardian')
|
38
|
+
@bucket = bucket
|
39
|
+
|
40
|
+
config = YAML.load_file(opts.fetch(:config))
|
41
|
+
@resource_groups = config.fetch('Resources',{})
|
42
|
+
@templates = config.fetch('Templates',{})
|
43
|
+
|
44
|
+
@resources = []
|
45
|
+
@stacks = []
|
46
|
+
@checks = []
|
47
|
+
|
48
|
+
@cost = 0
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_resources
|
52
|
+
@resource_groups.each do |group,resources|
|
53
|
+
resources.each do |resource|
|
54
|
+
|
55
|
+
begin
|
56
|
+
resource_class = Kernel.const_get("CfnGuardian::Resource::#{group}").new(resource)
|
57
|
+
rescue NameError => e
|
58
|
+
if @templates.has_key?(group) && @templates[group].has_key?('Inherit')
|
59
|
+
begin
|
60
|
+
resource_class = Kernel.const_get("CfnGuardian::Resource::#{@templates[group]['Inherit']}").new(resource)
|
61
|
+
logger.debug "Inheritited resource group #{@templates[group]['Inherit']} for group #{group}"
|
62
|
+
rescue NameError => e
|
63
|
+
logger.warn "'#{@templates[group]['Inherit']}' resource group doesn't exist and is unable to be inherited from"
|
64
|
+
next
|
65
|
+
end
|
66
|
+
else
|
67
|
+
logger.error(e)
|
68
|
+
next
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
overides = @templates.has_key?(group) ? @templates[group] : {}
|
73
|
+
@resources.concat resource_class.get_alarms(overides)
|
74
|
+
@resources.concat resource_class.get_events()
|
75
|
+
@checks.concat resource_class.get_checks()
|
76
|
+
|
77
|
+
@cost += resource_class.get_cost
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def split_resources
|
83
|
+
split = @resources.each_slice(200).to_a
|
84
|
+
split.each_with_index do |resources,index|
|
85
|
+
@stacks.push({
|
86
|
+
'Name' => "GuardianStack#{index}",
|
87
|
+
'TemplateURL' => "https://#{@bucket}.s3.amazonaws.com/#{@prefix}/guardian-stack-#{index}.compiled.yaml",
|
88
|
+
'Reference' => index
|
89
|
+
})
|
90
|
+
end
|
91
|
+
return split
|
92
|
+
end
|
93
|
+
|
94
|
+
def compile_templates
|
95
|
+
clean_out_directory()
|
96
|
+
resources = split_resources()
|
97
|
+
|
98
|
+
main_stack = CfnGuardian::Stacks::Main.new()
|
99
|
+
template = main_stack.build_template(@stacks,@checks)
|
100
|
+
valid = template.validate
|
101
|
+
File.write("out/guardian.compiled.yaml", JSON.parse(valid.to_json).to_yaml)
|
102
|
+
|
103
|
+
resources.each_with_index do |resources,index|
|
104
|
+
stack = CfnGuardian::Stacks::Resources.new()
|
105
|
+
template = stack.build_template(resources)
|
106
|
+
valid = template.validate
|
107
|
+
File.write("out/guardian-stack-#{index}.compiled.yaml", JSON.parse(valid.to_json).to_yaml)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def clean_out_directory
|
112
|
+
Dir["out/*.yaml"].each {|file| File.delete(file)}
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'aws-sdk-cloudformation'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'cfnguardian/version'
|
4
|
+
require 'cfnguardian/log'
|
5
|
+
|
6
|
+
module CfnGuardian
|
7
|
+
class Deploy
|
8
|
+
include Logging
|
9
|
+
|
10
|
+
def initialize(opts,bucket)
|
11
|
+
@stack_name = opts.fetch(:stack_name,'guardian')
|
12
|
+
@bucket = bucket
|
13
|
+
@prefix = @stack_name
|
14
|
+
@template_path = "out/guardian.compiled.yaml"
|
15
|
+
@template_url = "https://#{@bucket}.s3.amazonaws.com/#{@prefix}/guardian.compiled.yaml"
|
16
|
+
@parameters = {}
|
17
|
+
|
18
|
+
config = YAML.load_file(opts[:config])
|
19
|
+
if config.has_key?('Topics')
|
20
|
+
@parameters['Critical'] = config['Topics'].fetch('Critical','')
|
21
|
+
@parameters['Warning'] = config['Topics'].fetch('Warning','')
|
22
|
+
@parameters['Task'] = config['Topics'].fetch('Task','')
|
23
|
+
@parameters['Informational'] = config['Topics'].fetch('Informational','')
|
24
|
+
end
|
25
|
+
|
26
|
+
@parameters['Critical'] = opts.fetch(:sns_critical,@parameters['Critical'])
|
27
|
+
@parameters['Warning'] = opts.fetch(:sns_warning,@parameters['Warning'])
|
28
|
+
@parameters['Task'] = opts.fetch(:sns_task,@parameters['Task'])
|
29
|
+
@parameters['Informational'] = opts.fetch(:sns_informational,@parameters['Informational'])
|
30
|
+
|
31
|
+
@client = Aws::CloudFormation::Client.new()
|
32
|
+
end
|
33
|
+
|
34
|
+
def upload_templates
|
35
|
+
Dir["out/*.yaml"].each do |template|
|
36
|
+
prefix = "#{@prefix}/#{template.split('/').last}"
|
37
|
+
body = File.read(template)
|
38
|
+
client = Aws::S3::Client.new()
|
39
|
+
client.put_object({
|
40
|
+
body: body,
|
41
|
+
bucket: @bucket,
|
42
|
+
key: prefix
|
43
|
+
})
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# TODO: check for REVIEW_IN_PROGRESS
|
48
|
+
def does_cf_stack_exist()
|
49
|
+
begin
|
50
|
+
resp = @client.describe_stacks({
|
51
|
+
stack_name: @stack_name,
|
52
|
+
})
|
53
|
+
rescue Aws::CloudFormation::Errors::ValidationError
|
54
|
+
return false
|
55
|
+
end
|
56
|
+
return resp.size > 0
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_change_set_type()
|
60
|
+
return does_cf_stack_exist() ? 'UPDATE' : 'CREATE'
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_change_set()
|
64
|
+
change_set_name = "#{@stack_name}-#{CfnGuardian::CHANGE_SET_VERSION}-#{Time.now.utc.strftime("%Y%m%d%H%M%S")}"
|
65
|
+
change_set_type = get_change_set_type()
|
66
|
+
|
67
|
+
if change_set_type == 'CREATE'
|
68
|
+
params = get_parameters_from_template()
|
69
|
+
else
|
70
|
+
params = get_parameters_from_stack()
|
71
|
+
end
|
72
|
+
|
73
|
+
params.each do |param|
|
74
|
+
if !@parameters[param[:parameter_key]].nil?
|
75
|
+
param[:parameter_value] = @parameters[param[:parameter_key]]
|
76
|
+
param[:use_previous_value] = false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
logger.debug "Creating changeset"
|
81
|
+
change_set = @client.create_change_set({
|
82
|
+
stack_name: @stack_name,
|
83
|
+
template_url: @template_url,
|
84
|
+
capabilities: ["CAPABILITY_IAM"],
|
85
|
+
parameters: params,
|
86
|
+
tags: [
|
87
|
+
{
|
88
|
+
key: "guardian:version",
|
89
|
+
value: CfnGuardian::VERSION,
|
90
|
+
},
|
91
|
+
{
|
92
|
+
key: 'Environment',
|
93
|
+
value: 'guardian'
|
94
|
+
}
|
95
|
+
],
|
96
|
+
change_set_name: change_set_name,
|
97
|
+
change_set_type: change_set_type
|
98
|
+
})
|
99
|
+
return change_set, change_set_type
|
100
|
+
end
|
101
|
+
|
102
|
+
def wait_for_changeset(change_set_id)
|
103
|
+
logger.debug "Waiting for changeset to be created"
|
104
|
+
begin
|
105
|
+
@client.wait_until :change_set_create_complete, change_set_name: change_set_id
|
106
|
+
rescue Aws::Waiters::Errors::FailureStateError => e
|
107
|
+
change_set = get_change_set(change_set_id)
|
108
|
+
logger.error("change set status: #{change_set.status} reason: #{change_set.status_reason}")
|
109
|
+
exit 1
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def get_change_set(change_set_id)
|
114
|
+
@client.describe_change_set({
|
115
|
+
change_set_name: change_set_id,
|
116
|
+
})
|
117
|
+
end
|
118
|
+
|
119
|
+
def execute_change_set(change_set_id)
|
120
|
+
logger.debug "Executing the changeset"
|
121
|
+
stack = @client.execute_change_set({
|
122
|
+
change_set_name: change_set_id
|
123
|
+
})
|
124
|
+
end
|
125
|
+
|
126
|
+
def wait_for_execute(change_set_type)
|
127
|
+
waiter = change_set_type == 'CREATE' ? :stack_create_complete : :stack_update_complete
|
128
|
+
logger.info "Waiting for changeset to #{change_set_type}"
|
129
|
+
resp = @client.wait_until waiter, stack_name: @stack_name
|
130
|
+
end
|
131
|
+
|
132
|
+
def get_parameters_from_stack()
|
133
|
+
resp = @client.get_template_summary({ stack_name: @stack_name })
|
134
|
+
return resp.parameters.collect { |p| { parameter_key: p.parameter_key, use_previous_value: true } }
|
135
|
+
end
|
136
|
+
|
137
|
+
def get_parameters_from_template()
|
138
|
+
template_body = File.read(@template_path)
|
139
|
+
resp = @client.get_template_summary({ template_body: template_body })
|
140
|
+
return resp.parameters.collect { |p| { parameter_key: p.parameter_key, parameter_value: p.default_value } }
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|