knife-cloudformation 0.2.24 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +16 -0
- data/knife-cloudformation.gemspec +14 -4
- data/lib/knife-cloudformation.rb +0 -28
- data/lib/knife-cloudformation/version.rb +1 -1
- metadata +18 -80
- data/lib/chef/knife/cloudformation_create.rb +0 -147
- data/lib/chef/knife/cloudformation_describe.rb +0 -99
- data/lib/chef/knife/cloudformation_destroy.rb +0 -84
- data/lib/chef/knife/cloudformation_events.rb +0 -117
- data/lib/chef/knife/cloudformation_export.rb +0 -162
- data/lib/chef/knife/cloudformation_import.rb +0 -141
- data/lib/chef/knife/cloudformation_inspect.rb +0 -206
- data/lib/chef/knife/cloudformation_list.rb +0 -72
- data/lib/chef/knife/cloudformation_promote.rb +0 -40
- data/lib/chef/knife/cloudformation_update.rb +0 -137
- data/lib/chef/knife/cloudformation_validate.rb +0 -36
- data/lib/knife-cloudformation/cache.rb +0 -385
- data/lib/knife-cloudformation/knife.rb +0 -9
- data/lib/knife-cloudformation/knife/base.rb +0 -195
- data/lib/knife-cloudformation/knife/stack.rb +0 -197
- data/lib/knife-cloudformation/knife/template.rb +0 -213
- data/lib/knife-cloudformation/monkey_patch.rb +0 -8
- data/lib/knife-cloudformation/monkey_patch/stack.rb +0 -195
- data/lib/knife-cloudformation/provider.rb +0 -225
- data/lib/knife-cloudformation/utils.rb +0 -24
- data/lib/knife-cloudformation/utils/animal_strings.rb +0 -28
- data/lib/knife-cloudformation/utils/debug.rb +0 -31
- data/lib/knife-cloudformation/utils/json.rb +0 -64
- data/lib/knife-cloudformation/utils/object_storage.rb +0 -28
- data/lib/knife-cloudformation/utils/output.rb +0 -79
- data/lib/knife-cloudformation/utils/path_selector.rb +0 -99
- data/lib/knife-cloudformation/utils/ssher.rb +0 -29
- data/lib/knife-cloudformation/utils/stack_exporter.rb +0 -271
- data/lib/knife-cloudformation/utils/stack_parameter_scrubber.rb +0 -37
- data/lib/knife-cloudformation/utils/stack_parameter_validator.rb +0 -124
@@ -1,197 +0,0 @@
|
|
1
|
-
require 'knife-cloudformation'
|
2
|
-
require 'sparkle_formation'
|
3
|
-
|
4
|
-
module KnifeCloudformation
|
5
|
-
module Knife
|
6
|
-
# Stack handling helper methods
|
7
|
-
module Stack
|
8
|
-
|
9
|
-
module InstanceMethods
|
10
|
-
|
11
|
-
# un-packed stack name joiner/identifier
|
12
|
-
UNPACK_NAME_JOINER = '-sfn-'
|
13
|
-
# maximum number of attempts to get valid parameter value
|
14
|
-
MAX_PARAMETER_ATTEMPTS = 5
|
15
|
-
|
16
|
-
# Apply any defined remote stacks
|
17
|
-
#
|
18
|
-
# @param stack [Miasma::Models::Orchestration::Stack]
|
19
|
-
# @return [Miasma::Models::Orchestration::Stack]
|
20
|
-
def apply_stacks!(stack)
|
21
|
-
action = self.class.name.downcase.end_with?('create') ? :create : :update
|
22
|
-
remote_stacks = Chef::Config[:knife][:cloudformation].
|
23
|
-
fetch(action, {}).fetch(:apply_stacks, [])
|
24
|
-
remote_stacks.each do |stack_name|
|
25
|
-
remote_stack = provider.connection.stacks.get(stack_name)
|
26
|
-
apply_nested_stacks!(remote_stack, stack)
|
27
|
-
if(remote_stack)
|
28
|
-
stack.apply_stack(remote_stack)
|
29
|
-
else
|
30
|
-
apply_unpacked_stack!(stack_name, stack)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
stack
|
34
|
-
end
|
35
|
-
|
36
|
-
# Detect nested stacks and apply
|
37
|
-
#
|
38
|
-
# @param remote_stack [Miasma::Models::Orchestration::Stack] nested stack
|
39
|
-
# @param stack [Miasma::Models::Orchestration::Stack] current stack
|
40
|
-
# @return [Miasma::Models::Orchestration::Stack]
|
41
|
-
# @todo ported from a proto branch and needs to be refactored.
|
42
|
-
# this implementation is some what shady
|
43
|
-
def apply_nested_stacks!(remote_stack, stack)
|
44
|
-
remote_stack.resources.all.each do |resource|
|
45
|
-
if(resource.type == 'AWS::CloudFormation::Stack')
|
46
|
-
nested_stack = provider.connection.stacks.get(resource.id)
|
47
|
-
apply_nested_stacks!(nested_stack, stack)
|
48
|
-
stack.apply_stack(nested_stack)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
stack
|
52
|
-
end
|
53
|
-
|
54
|
-
# Apply all stacks from an unpacked stack
|
55
|
-
#
|
56
|
-
# @param stack_name [String] name of parent stack
|
57
|
-
# @param stack [Miasma::Models::Orchestration::Stack]
|
58
|
-
# @return [Miasma::Models::Orchestration::Stack]
|
59
|
-
def apply_unpacked_stack!(stack_name, stack)
|
60
|
-
result = provider.connection.stacks.all.find_all do |remote_stack|
|
61
|
-
remote_stack.name.start_with?("#{stack_name}#{UNPACK_NAME_JOINER}")
|
62
|
-
end.sort_by(&:name).map do |remote_stack|
|
63
|
-
stack.apply_stack(remote_stack)
|
64
|
-
end
|
65
|
-
unless(result.empty?)
|
66
|
-
stack
|
67
|
-
else
|
68
|
-
ui.error "Failed to apply requested stack. Unable to locate. (#{stack_name})"
|
69
|
-
exit 1
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# Unpack nested stack and run action on each stack, applying
|
74
|
-
# the previous stacks automatically
|
75
|
-
#
|
76
|
-
# @param name [String] container stack name
|
77
|
-
# @param file [Hash] stack template
|
78
|
-
# @param action [String] create or update
|
79
|
-
# @return [TrueClass]
|
80
|
-
def unpack_nesting(name, file, action)
|
81
|
-
|
82
|
-
# @todo move this init into setup
|
83
|
-
Chef::Config[:knife][:cloudformation][action.to_sym] ||= Mash.new
|
84
|
-
Chef::Config[:knife][:cloudformation][action.to_sym][:apply_stacks] ||= []
|
85
|
-
|
86
|
-
orig_options = Chef::Config[:knife][:cloudformation][:options].dup
|
87
|
-
stack_count = 0
|
88
|
-
|
89
|
-
file['Resources'].each do |stack_resource_name, stack_resource|
|
90
|
-
|
91
|
-
nested_stack_name = "#{name}#{UNPACK_NAME_JOINER}#{Kernel.sprintf('%0.3d', stack_count)}-#{stack_resource_name}"
|
92
|
-
nested_stack_template = stack_resource['Properties']['Stack']
|
93
|
-
Chef::Config[:knife][:cloudformation][:options] = orig_options.dup
|
94
|
-
|
95
|
-
klass = Chef::Knife.const_get("Cloudformation#{action.to_s.capitalize}")
|
96
|
-
nested_stack_runner = klass.new
|
97
|
-
nested_stack_runner.config = config.dup
|
98
|
-
nested_stack_runner.name_args.push(nested_stack_name)
|
99
|
-
Chef::Config[:knife][:cloudformation][:template] = nested_stack_template
|
100
|
-
nested_stack_runner.run
|
101
|
-
unless(config[:print_only])
|
102
|
-
Chef::Config[:knife][:cloudformation][action.to_sym][:apply_stacks].push(nested_stack_name).uniq!
|
103
|
-
end
|
104
|
-
Chef::Config[:knife][:cloudformation][:template] = nil
|
105
|
-
provider.connection.stacks.reload
|
106
|
-
stack_count += 1
|
107
|
-
|
108
|
-
end
|
109
|
-
|
110
|
-
true
|
111
|
-
end
|
112
|
-
|
113
|
-
# Prompt for parameter values and store result
|
114
|
-
#
|
115
|
-
# @param stack [Hash] stack template
|
116
|
-
# @return [Hash]
|
117
|
-
def populate_parameters!(stack, current_params={})
|
118
|
-
if(Chef::Config[:knife][:cloudformation][:interactive_parameters])
|
119
|
-
if(stack['Parameters'])
|
120
|
-
Chef::Config[:knife][:cloudformation][:options][:parameters] ||= Mash.new
|
121
|
-
stack.fetch('Parameters', {}).each do |k,v|
|
122
|
-
next if Chef::Config[:knife][:cloudformation][:options][:parameters][k]
|
123
|
-
attempt = 0
|
124
|
-
valid = false
|
125
|
-
until(valid)
|
126
|
-
attempt += 1
|
127
|
-
default = Chef::Config[:knife][:cloudformation][:options][:parameters].fetch(
|
128
|
-
k, current_params.fetch(
|
129
|
-
k, v['Default']
|
130
|
-
)
|
131
|
-
)
|
132
|
-
answer = ui.ask_question("#{k.split(/([A-Z]+[^A-Z]*)/).find_all{|s|!s.empty?}.join(' ')}: ", :default => default)
|
133
|
-
validation = KnifeCloudformation::Utils::StackParameterValidator.validate(answer, v)
|
134
|
-
if(validation == true)
|
135
|
-
Chef::Config[:knife][:cloudformation][:options][:parameters][k] = answer
|
136
|
-
valid = true
|
137
|
-
else
|
138
|
-
validation.each do |validation_error|
|
139
|
-
ui.error validation_error.last
|
140
|
-
end
|
141
|
-
end
|
142
|
-
if(attempt > MAX_PARAMETER_ATTEMPTS)
|
143
|
-
ui.fatal 'Failed to receive allowed parameter!'
|
144
|
-
exit 1
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
stack
|
151
|
-
end
|
152
|
-
|
153
|
-
end
|
154
|
-
|
155
|
-
module ClassMethods
|
156
|
-
end
|
157
|
-
|
158
|
-
# Load methods into class and define options
|
159
|
-
#
|
160
|
-
# @param klass [Class]
|
161
|
-
def self.included(klass)
|
162
|
-
klass.class_eval do
|
163
|
-
extend KnifeCloudformation::Knife::Stack::ClassMethods
|
164
|
-
include KnifeCloudformation::Knife::Stack::InstanceMethods
|
165
|
-
|
166
|
-
option(:parameter,
|
167
|
-
:short => '-p KEY:VALUE',
|
168
|
-
:long => '--parameter KEY:VALUE',
|
169
|
-
:description => 'Set parameter. Can be used multiple times.',
|
170
|
-
:proc => lambda {|val|
|
171
|
-
parts = val.split(':')
|
172
|
-
key = parts.first
|
173
|
-
value = parts[1, parts.size].join(':')
|
174
|
-
Chef::Config[:knife][:cloudformation][:options][:parameters] ||= Mash.new
|
175
|
-
Chef::Config[:knife][:cloudformation][:options][:parameters][key] = value
|
176
|
-
}
|
177
|
-
)
|
178
|
-
option(:polling,
|
179
|
-
:long => '--[no-]poll',
|
180
|
-
:description => 'Enable stack event polling.',
|
181
|
-
:boolean => true,
|
182
|
-
:default => true,
|
183
|
-
:proc => lambda {|val| Chef::Config[:knife][:cloudformation][:poll] = val }
|
184
|
-
)
|
185
|
-
option(:interactive_parameters,
|
186
|
-
:long => '--[no-]parameter-prompts',
|
187
|
-
:boolean => true,
|
188
|
-
:default => true,
|
189
|
-
:description => 'Do not prompt for input on dynamic parameters',
|
190
|
-
:proc => lambda{|val| Chef::Config[:knife][:cloudformation][:interactive_parameters] = val }
|
191
|
-
)
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
@@ -1,213 +0,0 @@
|
|
1
|
-
require 'knife-cloudformation'
|
2
|
-
require 'sparkle_formation'
|
3
|
-
|
4
|
-
module KnifeCloudformation
|
5
|
-
module Knife
|
6
|
-
# Template handling helper methods
|
7
|
-
module Template
|
8
|
-
|
9
|
-
# cloudformation directories that should be ignored
|
10
|
-
TEMPLATE_IGNORE_DIRECTORIES = %w(components dynamics registry)
|
11
|
-
|
12
|
-
module InstanceMethods
|
13
|
-
|
14
|
-
# Load the template file
|
15
|
-
#
|
16
|
-
# @param args [Symbol] options (:allow_missing)
|
17
|
-
# @return [Hash] loaded template
|
18
|
-
def load_template_file(*args)
|
19
|
-
unless(Chef::Config[:knife][:cloudformation][:template])
|
20
|
-
set_paths_and_discover_file!
|
21
|
-
unless(File.exists?(Chef::Config[:knife][:cloudformation][:file].to_s))
|
22
|
-
unless(args.include?(:allow_missing))
|
23
|
-
ui.fatal "Invalid formation file path provided: #{Chef::Config[:knife][:cloudformation][:file]}"
|
24
|
-
exit 1
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
if(Chef::Config[:knife][:cloudformation][:template])
|
29
|
-
Chef::Config[:knife][:cloudformation][:template]
|
30
|
-
elsif(Chef::Config[:knife][:cloudformation][:file])
|
31
|
-
if(Chef::Config[:knife][:cloudformation][:processing])
|
32
|
-
sf = SparkleFormation.compile(Chef::Config[:knife][:cloudformation][:file], :sparkle)
|
33
|
-
if(sf.nested? && !sf.isolated_nests?)
|
34
|
-
raise TypeError.new('Template does not contain isolated stack nesting! Cannot process in existing state.')
|
35
|
-
end
|
36
|
-
if(sf.nested? && Chef::Config[:knife][:cloudformation][:apply_nesting])
|
37
|
-
sf.apply_nesting do |stack_name, stack_definition|
|
38
|
-
bucket = provider.connection.api_for(:storage).buckets.get(
|
39
|
-
Chef::Config[:knife][:cloudformation][:nesting_bucket]
|
40
|
-
)
|
41
|
-
if(config[:print_only])
|
42
|
-
"http://example.com/bucket/#{name_args.first}_#{stack_name}.json"
|
43
|
-
else
|
44
|
-
unless(bucket)
|
45
|
-
raise "Failed to locate configured bucket for stack template storage (#{bucket})!"
|
46
|
-
end
|
47
|
-
file = bucket.files.build
|
48
|
-
file.name = "#{name_args.first}_#{stack_name}.json"
|
49
|
-
file.content_type = 'text/json'
|
50
|
-
file.body = MultiJson.dump(KnifeCloudformation::Utils::StackParameterScrubber.scrub!(stack_definition))
|
51
|
-
file.save
|
52
|
-
# TODO: what if we need extra params?
|
53
|
-
url = URI.parse(file.url)
|
54
|
-
"#{url.scheme}://#{url.host}#{url.path}"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
else
|
58
|
-
sf.dump.merge('sfn_nested_stack' => !!sf.nested?)
|
59
|
-
end
|
60
|
-
else
|
61
|
-
_from_json(File.read(Chef::Config[:knife][:cloudformation][:file]))
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# Apply template translation
|
67
|
-
#
|
68
|
-
# @param template [Hash]
|
69
|
-
# @return [Hash]
|
70
|
-
def translate_template(template)
|
71
|
-
if(klass_name = Chef::Config[:knife][:cloudformation][:translate])
|
72
|
-
klass = SparkleFormation::Translation.const_get(camel(klass_name))
|
73
|
-
args = {
|
74
|
-
:parameters => Chef::Config[:knife][:cloudformation][:options][:parameters]
|
75
|
-
}
|
76
|
-
if(chunk_size = Chef::Config[:knife][:cloudformation][:translate_chunk_size])
|
77
|
-
args.merge!(
|
78
|
-
:options => {
|
79
|
-
:serialization_chunk_size => chunk_size
|
80
|
-
}
|
81
|
-
)
|
82
|
-
end
|
83
|
-
translator = klass.new(template, args)
|
84
|
-
translator.translate!
|
85
|
-
template = translator.translated
|
86
|
-
ui.info "#{ui.color('Translation applied:', :bold)} #{ui.color(klass_name, :yellow)}"
|
87
|
-
end
|
88
|
-
template
|
89
|
-
end
|
90
|
-
|
91
|
-
# Set SparkleFormation paths and locate tempate
|
92
|
-
#
|
93
|
-
# @return [TrueClass]
|
94
|
-
def set_paths_and_discover_file!
|
95
|
-
if(Chef::Config[:knife][:cloudformation][:base_directory])
|
96
|
-
SparkleFormation.components_path = File.join(
|
97
|
-
Chef::Config[:knife][:cloudformation][:base_directory], 'components'
|
98
|
-
)
|
99
|
-
SparkleFormation.dynamics_path = File.join(
|
100
|
-
Chef::Config[:knife][:cloudformation][:base_directory], 'dynamics'
|
101
|
-
)
|
102
|
-
end
|
103
|
-
if(!Chef::Config[:knife][:cloudformation][:file] && Chef::Config[:knife][:cloudformation][:file_path_prompt])
|
104
|
-
root = File.expand_path(
|
105
|
-
Chef::Config[:knife][:cloudformation].fetch(:base_directory,
|
106
|
-
File.join(Dir.pwd, 'cloudformation')
|
107
|
-
)
|
108
|
-
).split('/')
|
109
|
-
bucket = root.pop
|
110
|
-
root = root.join('/')
|
111
|
-
directory = File.join(root, bucket)
|
112
|
-
Chef::Config[:knife][:cloudformation][:file] = prompt_for_file(directory,
|
113
|
-
:directories_name => 'Collections',
|
114
|
-
:files_name => 'Templates',
|
115
|
-
:ignore_directories => TEMPLATE_IGNORE_DIRECTORIES
|
116
|
-
)
|
117
|
-
else
|
118
|
-
unless(Pathname(Chef::Config[:knife][:cloudformation][:file].to_s).absolute?)
|
119
|
-
base_dir = Chef::Config[:knife][:cloudformation][:base_directory].to_s
|
120
|
-
file = Chef::Config[:knife][:cloudformation][:file].to_s
|
121
|
-
pwd = Dir.pwd
|
122
|
-
Chef::Config[:knife][:cloudformation][:file] = [
|
123
|
-
File.join(base_dir, file),
|
124
|
-
File.join(pwd, file),
|
125
|
-
File.join(pwd, 'cloudformation', file)
|
126
|
-
].detect do |file_path|
|
127
|
-
File.file?(file_path)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
true
|
132
|
-
end
|
133
|
-
|
134
|
-
end
|
135
|
-
|
136
|
-
module ClassMethods
|
137
|
-
end
|
138
|
-
|
139
|
-
# Load methods into class and define options
|
140
|
-
#
|
141
|
-
# @param klass [Class]
|
142
|
-
def self.included(klass)
|
143
|
-
klass.class_eval do
|
144
|
-
extend KnifeCloudformation::Knife::Template::ClassMethods
|
145
|
-
include KnifeCloudformation::Knife::Template::InstanceMethods
|
146
|
-
include KnifeCloudformation::Utils::PathSelector
|
147
|
-
|
148
|
-
option(:processing,
|
149
|
-
:long => '--[no-]processing',
|
150
|
-
:description => 'Call the unicorns and explode the glitter bombs',
|
151
|
-
:boolean => true,
|
152
|
-
:default => false,
|
153
|
-
:proc => lambda {|val| Chef::Config[:knife][:cloudformation][:processing] = val }
|
154
|
-
)
|
155
|
-
option(:file,
|
156
|
-
:short => '-f PATH',
|
157
|
-
:long => '--file PATH',
|
158
|
-
:description => 'Path to Cloud Formation to process',
|
159
|
-
:proc => lambda {|val|
|
160
|
-
Chef::Config[:knife][:cloudformation][:file] = val
|
161
|
-
}
|
162
|
-
)
|
163
|
-
option(:file_path_prompt,
|
164
|
-
:long => '--[no-]file-path-prompt',
|
165
|
-
:description => 'Interactive prompt for template path discovery',
|
166
|
-
:boolean => true,
|
167
|
-
:default => true,
|
168
|
-
:proc => lambda {|val|
|
169
|
-
Chef::Config[:knife][:cloudformation][:file_path_prompt] = val
|
170
|
-
}
|
171
|
-
)
|
172
|
-
option(:base_directory,
|
173
|
-
:long => '--cloudformation-directory PATH',
|
174
|
-
:description => 'Path to cloudformation directory',
|
175
|
-
:proc => lambda {|val| Chef::Config[:knife][:cloudformation][:base_directory] = val}
|
176
|
-
)
|
177
|
-
option(:no_base_directory,
|
178
|
-
:long => '--no-cloudformation-directory',
|
179
|
-
:description => 'Unset any value used for cloudformation path',
|
180
|
-
:proc => lambda {|*val| Chef::Config[:knife][:cloudformation][:base_directory] = nil}
|
181
|
-
)
|
182
|
-
option(:translate,
|
183
|
-
:long => '--translate PROVIDER',
|
184
|
-
:description => 'Translate generated template to given provider',
|
185
|
-
:proc => lambda {|val| Chef::Config[:knife][:cloudformation][:translate] = val}
|
186
|
-
)
|
187
|
-
option(:translate_chunk,
|
188
|
-
:long => '--translate-chunk-size SIZE',
|
189
|
-
:description => 'Chunk length for serialization',
|
190
|
-
:proc => lambda {|val| Chef::Config[:knife][:cloudformation][:translate_chunk_size] = val}
|
191
|
-
)
|
192
|
-
option(:apply_nesting,
|
193
|
-
:long => '--[no-]apply-nesting',
|
194
|
-
:description => 'Apply stack nesting',
|
195
|
-
:default => false,
|
196
|
-
:boolean => true,
|
197
|
-
:proc => lambda{|val| Chef::Config[:knife][:cloudformation][:apply_nesting] = val}
|
198
|
-
)
|
199
|
-
option(:nesting_bucket,
|
200
|
-
:long => '--nesting-bucket',
|
201
|
-
:description => 'Bucket to use for storing nested stack templates',
|
202
|
-
:proc => lambda{|val| Chef::Config[:knife][:cloudformation][:nesting_bucket] = val}
|
203
|
-
)
|
204
|
-
|
205
|
-
Chef::Config[:knife][:cloudformation][:file_path_prompt] = true
|
206
|
-
|
207
|
-
end
|
208
|
-
|
209
|
-
end
|
210
|
-
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|
@@ -1,195 +0,0 @@
|
|
1
|
-
require 'base64'
|
2
|
-
require 'knife-cloudformation'
|
3
|
-
|
4
|
-
module KnifeCloudformation
|
5
|
-
module MonkeyPatch
|
6
|
-
|
7
|
-
# Expand stack model functionality
|
8
|
-
module Stack
|
9
|
-
|
10
|
-
include KnifeCloudformation::Utils::AnimalStrings
|
11
|
-
|
12
|
-
## Status helpers
|
13
|
-
|
14
|
-
# Check for state suffix
|
15
|
-
#
|
16
|
-
# @param args [String, Symbol] state suffix to check for (multiple allowed)
|
17
|
-
# @return [TrueClass, FalseClass] true if any matches found in argument list
|
18
|
-
def status_ends_with?(*args)
|
19
|
-
stat = status.to_s.downcase
|
20
|
-
!!args.map(&:to_s).map(&:downcase).detect do |suffix|
|
21
|
-
stat.end_with?(suffix)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
# Check for state prefix
|
26
|
-
#
|
27
|
-
# @param args [String, Symbol] state prefix to check for (multiple allowed)
|
28
|
-
# @return [TrueClass, FalseClass] true if any matches found in argument list
|
29
|
-
def status_starts_with?(*args)
|
30
|
-
stat = status.to_s.downcase
|
31
|
-
!!args.map(&:to_s).map(&:downcase).detect do |prefix|
|
32
|
-
stat.start_with?(prefix)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# Check for state inclusion
|
37
|
-
#
|
38
|
-
# @param args [String, Symbol] state string to check for (multiple allowed)
|
39
|
-
# @return [TrueClass, FalseClass] true if any matches found in argument list
|
40
|
-
def status_includes?(*args)
|
41
|
-
stat = status.to_s.downcase
|
42
|
-
!!args.map(&:to_s).map(&:downcase).detect do |string|
|
43
|
-
stat.include?(string)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# @return [TrueClass, FalseClass] stack is in progress
|
48
|
-
def in_progress?
|
49
|
-
status_ends_with?(:in_progress)
|
50
|
-
end
|
51
|
-
|
52
|
-
# @return [TrueClass, FalseClass] stack is in complete state
|
53
|
-
def complete?
|
54
|
-
status_ends_with?(:complete, :failed)
|
55
|
-
end
|
56
|
-
|
57
|
-
# @return [TrueClass, FalseClass] stack is failed state
|
58
|
-
def failed?
|
59
|
-
status_ends_with?(:failed) ||
|
60
|
-
(status_includes?(:rollback) && status_ends_with?(:complete))
|
61
|
-
end
|
62
|
-
|
63
|
-
# @return [TrueClass, FalseClass] stack is in success state
|
64
|
-
def success?
|
65
|
-
!failed? && complete?
|
66
|
-
end
|
67
|
-
|
68
|
-
# @return [TrueClass, FalseClass] stack is creating
|
69
|
-
def creating?
|
70
|
-
in_progress? && status_starts_with?(:create)
|
71
|
-
end
|
72
|
-
|
73
|
-
# @return [TrueClass, FalseClass] stack is deleting
|
74
|
-
def deleting?
|
75
|
-
in_progress? && status_starts_with?(:delete)
|
76
|
-
end
|
77
|
-
|
78
|
-
# @return [TrueClass, FalseClass] stack is updating
|
79
|
-
def updating?
|
80
|
-
in_progress? && status_starts_with?(:update)
|
81
|
-
end
|
82
|
-
|
83
|
-
# @return [TrueClass, FalseClass] stack is rolling back
|
84
|
-
def rollbacking?
|
85
|
-
in_progress? && status_starts_with?(:rollback)
|
86
|
-
end
|
87
|
-
|
88
|
-
# @return [String] action currently being performed
|
89
|
-
def performing
|
90
|
-
if(in_progress?)
|
91
|
-
status.to_s.downcase.split('_').first.to_sym
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
### Color coders
|
96
|
-
|
97
|
-
# @return [TrueClass, FalseClass] stack is in red state
|
98
|
-
def red?
|
99
|
-
failed? || deleting?
|
100
|
-
end
|
101
|
-
|
102
|
-
# @return [TrueClass, FalseClass] stack is in green state
|
103
|
-
def green?
|
104
|
-
success?
|
105
|
-
end
|
106
|
-
|
107
|
-
# @return [TrueClass, FalseClass] stack is in yellow state
|
108
|
-
def yellow?
|
109
|
-
!red? && !green?
|
110
|
-
end
|
111
|
-
|
112
|
-
# Provides color of stack state. Red is an error state, yellow
|
113
|
-
# is a warning state and green is a success state
|
114
|
-
#
|
115
|
-
# @return [Symbol] color of state (:red, :yellow, :green)
|
116
|
-
def color_state
|
117
|
-
red? ? :red : green? ? :green : :yellow
|
118
|
-
end
|
119
|
-
|
120
|
-
# Provides text of stack state. Danger is an error state, warning
|
121
|
-
# is a warning state and success is a success state
|
122
|
-
#
|
123
|
-
# @return [Symbol] color of state (:danger, :warning, :success)
|
124
|
-
def text_state
|
125
|
-
red? ? :danger : green? ? :success : :warning
|
126
|
-
end
|
127
|
-
|
128
|
-
# @return [String] URL safe encoded stack id
|
129
|
-
def encoded_id
|
130
|
-
Base64.urlsafe_encode64(id)
|
131
|
-
end
|
132
|
-
|
133
|
-
# Whole number representation of current completion
|
134
|
-
#
|
135
|
-
# @param min [Integer] lowest allowed return value (defaults 5)
|
136
|
-
# @return [Integer] percent complete (0..100)
|
137
|
-
def percent_complete(min = 5)
|
138
|
-
if(in_progress?)
|
139
|
-
total_resources = load_template.fetch('Resources', []).size
|
140
|
-
total_complete = resources.all.find_all do |resource|
|
141
|
-
resource.resource_status.downcase.end_with?('complete')
|
142
|
-
end.size
|
143
|
-
result = ((total_complete.to_f / total_resources) * 100).to_i
|
144
|
-
result > min.to_i ? result : min
|
145
|
-
else
|
146
|
-
100
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
# Apply stack outputs to current stack parameters
|
151
|
-
#
|
152
|
-
# @param remote_stack [Miasma::Orchestration::Stack]
|
153
|
-
# @return [self]
|
154
|
-
# @note setting `DisableApply` within parameter hash will
|
155
|
-
# prevent parameters being overridden
|
156
|
-
def apply_stack(remote_stack)
|
157
|
-
default_key = 'Default'
|
158
|
-
stack_parameters = template['Parameters']
|
159
|
-
valid_parameters = Hash[
|
160
|
-
stack_parameters.map do |key, val|
|
161
|
-
unless(val['DisableApply'])
|
162
|
-
[snake(key), key]
|
163
|
-
end
|
164
|
-
end.compact
|
165
|
-
]
|
166
|
-
if(defined?(Chef::Config) && Chef::Config[:knife][:cloudformation][:ignore_parameters])
|
167
|
-
valid_parameters = Hash[
|
168
|
-
valid_parameters.map do |snake_param, camel_param|
|
169
|
-
unless(Chef::Config[:knife][:cloudformation][:ignore_parameters].include?(camel_param))
|
170
|
-
[snake_param, camel_param]
|
171
|
-
end
|
172
|
-
end.compact
|
173
|
-
]
|
174
|
-
end
|
175
|
-
if(persisted?)
|
176
|
-
remote_stack.outputs.each do |output|
|
177
|
-
if(param_key = valid_parameters[snake(output.key)])
|
178
|
-
parameters.merge!(param_key => output.value)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
else
|
182
|
-
remote_stack.outputs.each do |output|
|
183
|
-
if(param_key = valid_parameters[snake(output.key)])
|
184
|
-
stack_parameters[param_key][default_key] = output.value
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
end
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
# Infect miasma
|
195
|
-
Miasma::Models::Orchestration::Stack.send(:include, KnifeCloudformation::MonkeyPatch::Stack)
|