knife-cloudformation 0.1.2 → 0.1.4
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.
- 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
|