knife-cloudformation 0.1.2 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +6 -0
- data/lib/chef/knife/cloudformation_base.rb +109 -143
- data/lib/chef/knife/cloudformation_create.rb +66 -103
- data/lib/chef/knife/cloudformation_describe.rb +35 -17
- data/lib/chef/knife/cloudformation_destroy.rb +12 -12
- data/lib/chef/knife/cloudformation_events.rb +24 -42
- data/lib/chef/knife/cloudformation_inspect.rb +84 -0
- data/lib/chef/knife/cloudformation_list.rb +5 -17
- data/lib/chef/knife/cloudformation_update.rb +3 -3
- data/lib/knife-cloudformation/aws_commons.rb +118 -0
- data/lib/knife-cloudformation/aws_commons/stack.rb +221 -0
- data/lib/knife-cloudformation/aws_commons/stack_parameter_validator.rb +78 -0
- data/lib/knife-cloudformation/sparkle_formation.rb +38 -7
- data/lib/knife-cloudformation/utils.rb +69 -0
- data/lib/knife-cloudformation/version.rb +1 -1
- metadata +7 -2
data/CHANGELOG.md
CHANGED
@@ -1,85 +1,15 @@
|
|
1
1
|
require 'chef/knife'
|
2
|
+
require 'knife-cloudformation/utils'
|
3
|
+
require 'knife-cloudformation/aws_commons'
|
2
4
|
|
3
|
-
|
4
|
-
class Knife
|
5
|
+
module KnifeCloudformation
|
5
6
|
|
6
|
-
|
7
|
-
# with issues of nils
|
8
|
-
['knife.cloudformation.credentials', 'knife.cloudformation.options'].each do |stack|
|
9
|
-
stack.split('.').inject(Chef::Config) do |memo, item|
|
10
|
-
memo[item.to_sym] = Mash.new unless memo[item.to_sym]
|
11
|
-
memo[item.to_sym]
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
Chef::Config[:knife][:cloudformation] ||= Mash.new
|
16
|
-
|
17
|
-
module CloudformationDefault
|
18
|
-
class << self
|
19
|
-
def included(klass)
|
20
|
-
klass.instance_eval do
|
21
|
-
deps do
|
22
|
-
require 'fog'
|
23
|
-
Chef::Config[:knife][:cloudformation] ||= Mash.new
|
24
|
-
Chef::Config[:knife][:cloudformation][:credentials] ||= Mash.new
|
25
|
-
Chef::Config[:knife][:cloudformation][:options] ||= Mash.new
|
26
|
-
end
|
27
|
-
|
28
|
-
option(:key,
|
29
|
-
:short => '-K KEY',
|
30
|
-
:long => '--key KEY',
|
31
|
-
:description => 'AWS access key id',
|
32
|
-
:proc => lambda {|val|
|
33
|
-
Chef::Config[:knife][:cloudformation][:credentials][:key] = val
|
34
|
-
}
|
35
|
-
)
|
36
|
-
option(:secret,
|
37
|
-
:short => '-S SECRET',
|
38
|
-
:long => '--secret SECRET',
|
39
|
-
:description => 'AWS secret access key',
|
40
|
-
:proc => lambda {|val|
|
41
|
-
Chef::Config[:knife][:cloudformation][:credentials][:secret] = val
|
42
|
-
}
|
43
|
-
)
|
44
|
-
option(:region,
|
45
|
-
:short => '-r REGION',
|
46
|
-
:long => '--region REGION',
|
47
|
-
:description => 'AWS region',
|
48
|
-
:proc => lambda {|val|
|
49
|
-
Chef::Config[:knife][:cloudformation][:credentials][:region] = val
|
50
|
-
}
|
51
|
-
)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
class CloudformationBase < Knife
|
58
|
-
|
59
|
-
class << self
|
60
|
-
def aws_con
|
61
|
-
@connection ||= Fog::AWS::CloudFormation.new(
|
62
|
-
:aws_access_key_id => _key,
|
63
|
-
:aws_secret_access_key => _secret,
|
64
|
-
:region => _region
|
65
|
-
)
|
66
|
-
end
|
67
|
-
|
68
|
-
def _key
|
69
|
-
Chef::Config[:knife][:cloudformation][:credentials][:key] ||
|
70
|
-
Chef::Config[:knife][:aws_access_key_id]
|
71
|
-
end
|
72
|
-
|
73
|
-
def _secret
|
74
|
-
Chef::Config[:knife][:cloudformation][:credentials][:secret] ||
|
75
|
-
Chef::Config[:knife][:aws_secret_access_key]
|
76
|
-
end
|
7
|
+
module KnifeBase
|
77
8
|
|
78
|
-
|
79
|
-
Chef::Config[:knife][:cloudformation][:credentials][:region] ||
|
80
|
-
Chef::Config[:knife][:region]
|
81
|
-
end
|
9
|
+
module InstanceMethods
|
82
10
|
|
11
|
+
def aws
|
12
|
+
self.class.con(ui)
|
83
13
|
end
|
84
14
|
|
85
15
|
def _debug(e, *args)
|
@@ -91,43 +21,8 @@ class Chef
|
|
91
21
|
end
|
92
22
|
end
|
93
23
|
|
94
|
-
def
|
95
|
-
self.class.
|
96
|
-
end
|
97
|
-
|
98
|
-
def stack_status(name)
|
99
|
-
aws_con.describe_stacks('StackName' => name).body['Stacks'].first['StackStatus']
|
100
|
-
end
|
101
|
-
|
102
|
-
def get_titles(thing, format=false)
|
103
|
-
unless(@titles)
|
104
|
-
attrs = allowed_attributes
|
105
|
-
if(attrs.empty?)
|
106
|
-
hash = thing.is_a?(Array) ? thing.first : thing
|
107
|
-
hash ||= {}
|
108
|
-
attrs = hash.keys
|
109
|
-
end
|
110
|
-
@titles = attrs.map do |key|
|
111
|
-
next unless attribute_allowed?(key)
|
112
|
-
key.gsub(/([a-z])([A-Z])/, '\1 \2')
|
113
|
-
end.compact
|
114
|
-
end
|
115
|
-
if(format)
|
116
|
-
@titles.map{|s| ui.color(s, :bold)}
|
117
|
-
else
|
118
|
-
@titles
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def process(things)
|
123
|
-
@event_ids ||= []
|
124
|
-
things.reverse.map do |thing|
|
125
|
-
next if @event_ids.include?(thing['EventId'])
|
126
|
-
@event_ids.push(thing['EventId']).compact!
|
127
|
-
get_titles(thing).map do |key|
|
128
|
-
thing[key.gsub(' ', '')].to_s
|
129
|
-
end
|
130
|
-
end.flatten.compact
|
24
|
+
def stack(name)
|
25
|
+
self.class.con(ui).stack(name)
|
131
26
|
end
|
132
27
|
|
133
28
|
def allowed_attributes
|
@@ -142,15 +37,27 @@ class Chef
|
|
142
37
|
config[:all_attributes] || allowed_attributes.include?(attr)
|
143
38
|
end
|
144
39
|
|
145
|
-
def
|
146
|
-
|
147
|
-
|
40
|
+
def poll_stack(name)
|
41
|
+
knife_events = Chef::Knife::CloudformationEvents.new
|
42
|
+
knife_events.name_args.push(name)
|
43
|
+
Chef::Config[:knife][:cloudformation][:poll] = true
|
44
|
+
knife_events.run
|
45
|
+
end
|
46
|
+
|
47
|
+
def things_output(stack, things, what, *args)
|
48
|
+
unless(args.include?(:no_title))
|
49
|
+
output = aws.get_titles(things, :format => true, :attributes => allowed_attributes)
|
50
|
+
else
|
51
|
+
output = []
|
52
|
+
end
|
53
|
+
columns = allowed_attributes.size
|
54
|
+
output += aws.process(things, :flat => true, :attributes => allowed_attributes)
|
148
55
|
output.compact.flatten
|
149
|
-
if(output.empty?)
|
56
|
+
if(output.empty? && !args.include?(:ignore_empty_output))
|
150
57
|
ui.warn 'No information found'
|
151
58
|
else
|
152
59
|
ui.info "#{what.to_s.capitalize} for stack: #{ui.color(stack, :bold)}" if stack
|
153
|
-
ui.info "#{ui.list(output, :uneven_columns_across,
|
60
|
+
ui.info "#{ui.list(output, :uneven_columns_across, columns)}"
|
154
61
|
end
|
155
62
|
end
|
156
63
|
|
@@ -165,38 +72,97 @@ class Chef
|
|
165
72
|
end
|
166
73
|
end
|
167
74
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
75
|
+
end
|
76
|
+
|
77
|
+
module ClassMethods
|
78
|
+
|
79
|
+
def con(ui=nil)
|
80
|
+
unless(@common)
|
81
|
+
@common = KnifeCloudformation::AwsCommons.new(
|
82
|
+
:ui => ui,
|
83
|
+
:fog => {
|
84
|
+
:aws_access_key_id => _key,
|
85
|
+
:aws_secret_access_key => _secret,
|
86
|
+
:region => _region
|
87
|
+
}
|
88
|
+
)
|
172
89
|
end
|
173
|
-
|
90
|
+
@common
|
174
91
|
end
|
175
|
-
|
176
|
-
def
|
177
|
-
|
178
|
-
Chef::
|
179
|
-
else
|
180
|
-
JSON.dump(thing)
|
181
|
-
end
|
92
|
+
|
93
|
+
def _key
|
94
|
+
Chef::Config[:knife][:cloudformation][:credentials][:key] ||
|
95
|
+
Chef::Config[:knife][:aws_access_key_id]
|
182
96
|
end
|
183
97
|
|
184
|
-
def
|
185
|
-
|
186
|
-
Chef::
|
187
|
-
else
|
188
|
-
JSON.read(thing)
|
189
|
-
end
|
98
|
+
def _secret
|
99
|
+
Chef::Config[:knife][:cloudformation][:credentials][:secret] ||
|
100
|
+
Chef::Config[:knife][:aws_secret_access_key]
|
190
101
|
end
|
191
102
|
|
192
|
-
def
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
103
|
+
def _region
|
104
|
+
Chef::Config[:knife][:cloudformation][:credentials][:region] ||
|
105
|
+
Chef::Config[:knife][:region]
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
class << self
|
111
|
+
def included(klass)
|
112
|
+
klass.instance_eval do
|
113
|
+
|
114
|
+
extend KnifeCloudformation::KnifeBase::ClassMethods
|
115
|
+
include KnifeCloudformation::KnifeBase::InstanceMethods
|
116
|
+
include KnifeCloudformation::Utils::JSON
|
117
|
+
include KnifeCloudformation::Utils::AnimalStrings
|
118
|
+
|
119
|
+
deps do
|
120
|
+
require 'fog'
|
121
|
+
Chef::Config[:knife][:cloudformation] ||= Mash.new
|
122
|
+
Chef::Config[:knife][:cloudformation][:credentials] ||= Mash.new
|
123
|
+
Chef::Config[:knife][:cloudformation][:options] ||= Mash.new
|
124
|
+
end
|
125
|
+
|
126
|
+
option(:key,
|
127
|
+
:short => '-K KEY',
|
128
|
+
:long => '--key KEY',
|
129
|
+
:description => 'AWS access key id',
|
130
|
+
:proc => lambda {|val|
|
131
|
+
Chef::Config[:knife][:cloudformation][:credentials][:key] = val
|
132
|
+
}
|
133
|
+
)
|
134
|
+
option(:secret,
|
135
|
+
:short => '-S SECRET',
|
136
|
+
:long => '--secret SECRET',
|
137
|
+
:description => 'AWS secret access key',
|
138
|
+
:proc => lambda {|val|
|
139
|
+
Chef::Config[:knife][:cloudformation][:credentials][:secret] = val
|
140
|
+
}
|
141
|
+
)
|
142
|
+
option(:region,
|
143
|
+
:short => '-r REGION',
|
144
|
+
:long => '--region REGION',
|
145
|
+
:description => 'AWS region',
|
146
|
+
:proc => lambda {|val|
|
147
|
+
Chef::Config[:knife][:cloudformation][:credentials][:region] = val
|
148
|
+
}
|
149
|
+
)
|
150
|
+
|
151
|
+
|
152
|
+
# Populate up the hashes so they are available for knife config
|
153
|
+
# with issues of nils
|
154
|
+
['knife.cloudformation.credentials', 'knife.cloudformation.options'].each do |stack|
|
155
|
+
stack.split('.').inject(Chef::Config) do |memo, item|
|
156
|
+
memo[item.to_sym] = Mash.new unless memo[item.to_sym]
|
157
|
+
memo[item.to_sym]
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
Chef::Config[:knife][:cloudformation] ||= Mash.new
|
162
|
+
|
198
163
|
end
|
199
164
|
end
|
200
165
|
end
|
201
166
|
end
|
167
|
+
|
202
168
|
end
|
@@ -3,7 +3,9 @@ require 'chef/knife/cloudformation_base'
|
|
3
3
|
|
4
4
|
class Chef
|
5
5
|
class Knife
|
6
|
-
class CloudformationCreate <
|
6
|
+
class CloudformationCreate < Knife
|
7
|
+
|
8
|
+
include KnifeCloudformation::KnifeBase
|
7
9
|
|
8
10
|
banner 'knife cloudformation create NAME'
|
9
11
|
|
@@ -13,7 +15,7 @@ class Chef
|
|
13
15
|
klass.class_eval do
|
14
16
|
|
15
17
|
attr_accessor :action_type
|
16
|
-
|
18
|
+
|
17
19
|
option(:parameter,
|
18
20
|
:short => '-p KEY:VALUE',
|
19
21
|
:long => '--parameter KEY:VALUE',
|
@@ -32,11 +34,13 @@ class Chef
|
|
32
34
|
Chef::Config[:knife][:cloudformation][:options][:timeout_in_minutes] = val
|
33
35
|
}
|
34
36
|
)
|
35
|
-
option(:
|
37
|
+
option(:rollback,
|
36
38
|
:short => '-R',
|
37
|
-
:long => '--
|
38
|
-
:description => '
|
39
|
-
:
|
39
|
+
:long => '--[no]-rollback',
|
40
|
+
:description => 'Rollback on stack creation failure',
|
41
|
+
:boolean => true,
|
42
|
+
:default => true,
|
43
|
+
:proc => lambda {|val| Chef::Config[:knife][:cloudformation][:options][:disable_rollback] = !val }
|
40
44
|
)
|
41
45
|
option(:capability,
|
42
46
|
:short => '-C CAPABILITY',
|
@@ -47,15 +51,19 @@ class Chef
|
|
47
51
|
Chef::Config[:knife][:cloudformation][:options][:capabilities].push(val).uniq!
|
48
52
|
}
|
49
53
|
)
|
50
|
-
option(:
|
51
|
-
:long => '--
|
52
|
-
:description => 'Call the unicorns
|
53
|
-
:
|
54
|
+
option(:processing,
|
55
|
+
:long => '--[no-]processing',
|
56
|
+
:description => 'Call the unicorns and explode the glitter bombs',
|
57
|
+
:boolean => true,
|
58
|
+
:default => false,
|
59
|
+
:proc => lambda {|val| Chef::Config[:knife][:cloudformation][:processing] = val }
|
54
60
|
)
|
55
|
-
option(:
|
56
|
-
:long => '--
|
57
|
-
:description => '
|
58
|
-
:
|
61
|
+
option(:polling,
|
62
|
+
:long => '--[no-]polling',
|
63
|
+
:description => 'Enable stack event polling.',
|
64
|
+
:boolean => true,
|
65
|
+
:default => true,
|
66
|
+
:proc => lambda {|val| Chef::Config[:knife][:cloudformation][:polling] = val }
|
59
67
|
)
|
60
68
|
option(:notifications,
|
61
69
|
:long => '--notification ARN',
|
@@ -73,23 +81,30 @@ class Chef
|
|
73
81
|
Chef::Config[:knife][:cloudformation][:file] = val
|
74
82
|
}
|
75
83
|
)
|
76
|
-
option(:
|
77
|
-
:long => '--no-parameter-prompts',
|
78
|
-
:
|
84
|
+
option(:interactive_parameters,
|
85
|
+
:long => '--[no-]parameter-prompts',
|
86
|
+
:boolean => true,
|
87
|
+
:default => true,
|
88
|
+
:description => 'Do not prompt for input on dynamic parameters',
|
89
|
+
:default => true
|
79
90
|
)
|
80
|
-
|
81
91
|
option(:print_only,
|
82
92
|
:long => '--print-only',
|
83
93
|
:description => 'Print template and exit'
|
84
94
|
)
|
95
|
+
|
96
|
+
%w(rollback polling interactive_parameters).each do |key|
|
97
|
+
if(Chef::Config[:knife][:cloudformation][key].nil?)
|
98
|
+
Chef::Config[:knife][:cloudformation][key] = true
|
99
|
+
end
|
100
|
+
end
|
85
101
|
end
|
86
102
|
end
|
87
103
|
end
|
88
104
|
end
|
89
105
|
|
90
|
-
include CloudformationDefault
|
91
106
|
include Options
|
92
|
-
|
107
|
+
|
93
108
|
def run
|
94
109
|
@action_type = self.class.name.split('::').last.sub('Cloudformation', '').upcase
|
95
110
|
unless(File.exists?(Chef::Config[:knife][:cloudformation][:file].to_s))
|
@@ -97,69 +112,46 @@ class Chef
|
|
97
112
|
exit 1
|
98
113
|
end
|
99
114
|
name = name_args.first
|
100
|
-
if(Chef::Config[:knife][:cloudformation][:
|
115
|
+
if(Chef::Config[:knife][:cloudformation][:processing])
|
101
116
|
file = KnifeCloudformation::SparkleFormation.compile(Chef::Config[:knife][:cloudformation][:file])
|
102
117
|
else
|
103
118
|
file = _from_json(File.read(Chef::Config[:knife][:cloudformation][:file]))
|
104
119
|
end
|
105
|
-
ui.info "#{ui.color('Cloud Formation: ', :bold)} #{ui.color(action_type, :green)}"
|
106
|
-
ui.info " -> #{ui.color('Name:', :bold)} #{name} #{ui.color('Path:', :bold)} #{Chef::Config[:knife][:cloudformation][:file]} #{ui.color('(not pre-processed)', :yellow) if Chef::Config[:knife][:cloudformation][:disable_processing]}"
|
107
|
-
stack = build_stack(file)
|
108
120
|
if(config[:print_only])
|
109
121
|
ui.warn 'Print only requested'
|
110
|
-
ui.info _format_json(
|
122
|
+
ui.info _format_json(file)
|
111
123
|
exit 1
|
112
124
|
end
|
113
|
-
|
114
|
-
|
125
|
+
ui.info "#{ui.color('Cloud Formation: ', :bold)} #{ui.color(action_type, :green)}"
|
126
|
+
ui.info " -> #{ui.color('Name:', :bold)} #{name} #{ui.color('Path:', :bold)} #{Chef::Config[:knife][:cloudformation][:file]} #{ui.color('(not pre-processed)', :yellow) if Chef::Config[:knife][:cloudformation][:disable_processing]}"
|
127
|
+
populate_parameters!(file)
|
128
|
+
stack_def = KnifeCloudformation::AwsCommons::Stack.build_stack_definition(file, Chef::Config[:knife][:cloudformation][:options])
|
129
|
+
aws.create_stack(name, stack_def)
|
130
|
+
if(Chef::Config[:knife][:cloudformation][:polling])
|
115
131
|
poll_stack(name)
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
def build_stack(template)
|
123
|
-
stack = Mash.new
|
124
|
-
populate_parameters!(template)
|
125
|
-
Chef::Config[:knife][:cloudformation][:options].each do |key, value|
|
126
|
-
format_key = key.split('_').map(&:capitalize).join
|
127
|
-
stack[format_key] = value
|
128
|
-
=begin
|
129
|
-
case value
|
130
|
-
when Hash && key.to_sym != :parameters
|
131
|
-
i = 1
|
132
|
-
value.each do |k, v|
|
133
|
-
stack["#{format_key}.member.#{i}.#{format_key[0, (format_key.length - 1)]}Key"] = k
|
134
|
-
stack["#{format_key}.member.#{i}.#{format_key[0, (format_key.length - 1)]}Value"] = v
|
135
|
-
end
|
136
|
-
when Array
|
137
|
-
value.each_with_index do |v, i|
|
138
|
-
stack["#{format_key}.member.#{i+1}"] = v
|
139
|
-
end
|
132
|
+
if(stack(name).success?)
|
133
|
+
ui.info "Stack #{action_type} complete: #{ui.color('SUCCESS', :green)}"
|
134
|
+
knife_output = Chef::Knife::CloudformationDescribe.new
|
135
|
+
knife_output.name_args.push(name)
|
136
|
+
knife_output.config[:outputs] = true
|
137
|
+
knife_output.run
|
140
138
|
else
|
141
|
-
|
139
|
+
ui.fatal "#{action_type} of new stack #{ui.color(name, :bold)}: #{ui.color('FAILED', :red, :bold)}"
|
140
|
+
ui.info ""
|
141
|
+
knife_inspect = Chef::Knife::CloudformationInspect.new
|
142
|
+
knife_inspect.name_args.push(name)
|
143
|
+
knife_inspect.config[:instance_failure] = true
|
144
|
+
knife_inspect.run
|
145
|
+
exit 1
|
142
146
|
end
|
143
|
-
|
147
|
+
else
|
148
|
+
ui.warn 'Stack state polling has been disabled.'
|
149
|
+
ui.info "Stack creation initialized for #{ui.color(name, :green)}"
|
144
150
|
end
|
145
|
-
enable_capabilities!(stack, template)
|
146
|
-
stack['TemplateBody'] = Chef::JSONCompat.to_json(template)
|
147
|
-
stack
|
148
151
|
end
|
149
152
|
|
150
|
-
# Currently only checking for IAM resources since that's all
|
151
|
-
# that is supported for creation
|
152
|
-
def enable_capabilities!(stack, template)
|
153
|
-
found = Array(template['Resources']).detect do |resource_name, resource|
|
154
|
-
resource['Type'].start_with?('AWS::IAM')
|
155
|
-
end
|
156
|
-
if(found)
|
157
|
-
stack['Capabilities'] = ['CAPABILITY_IAM']
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
153
|
def populate_parameters!(stack)
|
162
|
-
|
154
|
+
if(Chef::Config[:knife][:cloudformation][:interactive_parameters])
|
163
155
|
if(stack['Parameters'])
|
164
156
|
Chef::Config[:knife][:cloudformation][:options][:parameters] ||= Mash.new
|
165
157
|
stack['Parameters'].each do |k,v|
|
@@ -167,50 +159,21 @@ class Chef
|
|
167
159
|
until(valid)
|
168
160
|
default = Chef::Config[:knife][:cloudformation][:options][:parameters][k] || v['Default']
|
169
161
|
answer = ui.ask_question("#{k.split(/([A-Z]+[^A-Z]*)/).find_all{|s|!s.empty?}.join(' ')} ", :default => default)
|
170
|
-
|
171
|
-
|
172
|
-
else
|
173
|
-
valid = true
|
174
|
-
end
|
175
|
-
if(valid)
|
162
|
+
validation = KnifeCloudformation::AwsCommons::Stack::ParameterValidator.validate(answer, v)
|
163
|
+
if(validation == true)
|
176
164
|
Chef::Config[:knife][:cloudformation][:options][:parameters][k] = answer
|
165
|
+
valid = true
|
177
166
|
else
|
178
|
-
|
167
|
+
validation.each do |validation_error|
|
168
|
+
ui.error validation_error.last
|
169
|
+
end
|
179
170
|
end
|
180
171
|
end
|
181
172
|
end
|
182
173
|
end
|
183
174
|
end
|
184
175
|
end
|
185
|
-
|
186
|
-
def create_stack(name, stack)
|
187
|
-
begin
|
188
|
-
res = aws_con.create_stack(name, stack)
|
189
|
-
rescue => e
|
190
|
-
ui.fatal "Failed to #{action_type} stack #{name}. Reason: #{e}"
|
191
|
-
_debug(e, "Generated template used:\n#{_format_json(stack['TemplateBody'])}")
|
192
|
-
exit 1
|
193
|
-
end
|
194
|
-
end
|
195
176
|
|
196
|
-
def poll_stack(name)
|
197
|
-
knife_events = Chef::Knife::CloudformationEvents.new
|
198
|
-
knife_events.name_args.push(name)
|
199
|
-
Chef::Config[:knife][:cloudformation][:poll] = true
|
200
|
-
knife_events.run
|
201
|
-
unless(action_successful?(name))
|
202
|
-
ui.fatal "#{action_type} of new stack #{ui.color(name, :bold)}: #{ui.color('FAILED', :red, :bold)}"
|
203
|
-
exit 1
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
def action_in_progress?(name)
|
208
|
-
stack_status(name) == 'CREATE_IN_PROGRESS'
|
209
|
-
end
|
210
|
-
|
211
|
-
def action_successful?(name)
|
212
|
-
stack_status(name) == 'CREATE_COMPLETE'
|
213
|
-
end
|
214
177
|
end
|
215
178
|
end
|
216
179
|
end
|