knife-cloudformation 0.2.24 → 0.5.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 +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,36 +0,0 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
require 'sparkle_formation'
|
3
|
-
require 'knife-cloudformation'
|
4
|
-
|
5
|
-
class Chef
|
6
|
-
class Knife
|
7
|
-
# Cloudformation validate command
|
8
|
-
class CloudformationValidate < Knife
|
9
|
-
|
10
|
-
include KnifeCloudformation::Knife::Base
|
11
|
-
include KnifeCloudformation::Knife::Template
|
12
|
-
|
13
|
-
banner 'knife cloudformation validate'
|
14
|
-
|
15
|
-
def _run
|
16
|
-
file = load_template_file
|
17
|
-
file.delete('sfn_nested_stack')
|
18
|
-
ui.info "#{ui.color('Cloud Formation Validation: ', :bold)} #{Chef::Config[:knife][:cloudformation][:file].sub(Dir.pwd, '').sub(%r{^/}, '')}"
|
19
|
-
file = KnifeCloudformation::Utils::StackParameterScrubber.scrub!(file)
|
20
|
-
file = translate_template(file)
|
21
|
-
begin
|
22
|
-
result = provider.connection.stacks.build(
|
23
|
-
:name => 'validation-stack',
|
24
|
-
:template => file
|
25
|
-
).validate
|
26
|
-
ui.info ui.color(' -> VALID', :bold, :green)
|
27
|
-
rescue => e
|
28
|
-
ui.info ui.color(' -> INVALID', :bold, :red)
|
29
|
-
ui.fatal e.message
|
30
|
-
failed = true
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,385 +0,0 @@
|
|
1
|
-
require 'digest/sha2'
|
2
|
-
require 'thread'
|
3
|
-
require 'knife-cloudformation'
|
4
|
-
|
5
|
-
module KnifeCloudformation
|
6
|
-
# Data caching helper
|
7
|
-
class Cache
|
8
|
-
|
9
|
-
class << self
|
10
|
-
|
11
|
-
# Configure the caching approach to use
|
12
|
-
#
|
13
|
-
# @param type [Symbol] :redis or :local
|
14
|
-
# @param args [Hash] redis connection arguments if used
|
15
|
-
def configure(type, args={})
|
16
|
-
type = type.to_sym
|
17
|
-
case type
|
18
|
-
when :redis
|
19
|
-
begin
|
20
|
-
require 'redis-objects'
|
21
|
-
rescue LoadError
|
22
|
-
$stderr.puts 'The `redis-objects` gem is required for Cache support!'
|
23
|
-
raise
|
24
|
-
end
|
25
|
-
@_pid = Process.pid
|
26
|
-
Redis::Objects.redis = Redis.new(args)
|
27
|
-
when :local
|
28
|
-
else
|
29
|
-
raise TypeError.new("Unsupported caching type: #{type}")
|
30
|
-
end
|
31
|
-
enable(type)
|
32
|
-
end
|
33
|
-
|
34
|
-
# Set enabled caching type
|
35
|
-
#
|
36
|
-
# @param type [Symbol]
|
37
|
-
# @return [Symbol]
|
38
|
-
def enable(type)
|
39
|
-
@type = type.to_sym
|
40
|
-
end
|
41
|
-
|
42
|
-
# @return [Symbol] type of caching enabled
|
43
|
-
def type
|
44
|
-
@type || :local
|
45
|
-
end
|
46
|
-
|
47
|
-
# Set/get time limit on data type
|
48
|
-
#
|
49
|
-
# @param kind [String, Symbol] data type
|
50
|
-
# @param seconds [Integer]
|
51
|
-
# return [Integer] seconds
|
52
|
-
def apply_limit(kind, seconds=nil)
|
53
|
-
@apply_limit ||= {}
|
54
|
-
if(seconds)
|
55
|
-
@apply_limit[kind.to_sym] = seconds.to_i
|
56
|
-
end
|
57
|
-
@apply_limit[kind.to_sym].to_i
|
58
|
-
end
|
59
|
-
|
60
|
-
# @return [Hash] default limits
|
61
|
-
def default_limits
|
62
|
-
(@apply_limit || {}).dup
|
63
|
-
end
|
64
|
-
|
65
|
-
# Ping the redis connection and reconnect if dead
|
66
|
-
def redis_ping!
|
67
|
-
if((@_pid && @_pid != Process.pid) || !Redis::Objects.redis.connected?)
|
68
|
-
Redis::Objects.redis.client.reconnect
|
69
|
-
@_pid = Process.pid
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
# @return [String] custom key for this cache
|
76
|
-
attr_reader :key
|
77
|
-
|
78
|
-
# Create new instance
|
79
|
-
#
|
80
|
-
# @param key [String, Array]
|
81
|
-
def initialize(key)
|
82
|
-
if(key.respond_to?(:sort))
|
83
|
-
key = key.flatten if key.respond_to?(:flatten)
|
84
|
-
key = key.map(&:to_s).sort
|
85
|
-
end
|
86
|
-
@key = Digest::SHA256.hexdigest(key.to_s)
|
87
|
-
@apply_limit = self.class.default_limits
|
88
|
-
end
|
89
|
-
|
90
|
-
# Initialize a new data type
|
91
|
-
#
|
92
|
-
# @param name [Symbol] name of data
|
93
|
-
# @param kind [Symbol] data type
|
94
|
-
# @param args [Hash] options for data type
|
95
|
-
def init(name, kind, args={})
|
96
|
-
get_storage(self.class.type, kind, name, args)
|
97
|
-
true
|
98
|
-
end
|
99
|
-
|
100
|
-
# @return [Hash] data registry
|
101
|
-
def registry
|
102
|
-
get_storage(self.class.type, :hash, "registry_#{key}")
|
103
|
-
end
|
104
|
-
|
105
|
-
# Clear data
|
106
|
-
#
|
107
|
-
# @param args [Symbol] list of names to delete
|
108
|
-
# @return [TrueClass]
|
109
|
-
# @note clears all data if no names provided
|
110
|
-
def clear!(*args)
|
111
|
-
internal_lock do
|
112
|
-
args = registry.keys if args.empty?
|
113
|
-
args.each do |key|
|
114
|
-
value = self[key]
|
115
|
-
if(value.respond_to?(:clear))
|
116
|
-
value.clear
|
117
|
-
elsif(value.respond_to?(:value))
|
118
|
-
value.value = nil
|
119
|
-
end
|
120
|
-
registry.delete(key)
|
121
|
-
end
|
122
|
-
yield if block_given?
|
123
|
-
end
|
124
|
-
true
|
125
|
-
end
|
126
|
-
|
127
|
-
# Fetch item from storage
|
128
|
-
#
|
129
|
-
# @param store_type [Symbol]
|
130
|
-
# @param data_type [Symbol]
|
131
|
-
# @param name [Symbol] name of data
|
132
|
-
# @param args [Hash] options for underlying storage
|
133
|
-
# @return [Object]
|
134
|
-
def get_storage(store_type, data_type, name, args={})
|
135
|
-
full_name = "#{key}_#{name}"
|
136
|
-
result = nil
|
137
|
-
case store_type.to_sym
|
138
|
-
when :redis
|
139
|
-
result = get_redis_storage(data_type, full_name.to_s, args)
|
140
|
-
when :local
|
141
|
-
@_local_cache ||= {}
|
142
|
-
unless(@_local_cache[full_name.to_s])
|
143
|
-
@_local_cache[full_name.to_s] = get_local_storage(data_type, full_name.to_s, args)
|
144
|
-
end
|
145
|
-
result = @_local_cache[full_name.to_s]
|
146
|
-
else
|
147
|
-
raise TypeError.new("Unsupported caching storage type encountered: #{store_type}")
|
148
|
-
end
|
149
|
-
unless(full_name == "#{key}_registry_#{key}")
|
150
|
-
registry[name.to_s] = data_type
|
151
|
-
end
|
152
|
-
result
|
153
|
-
end
|
154
|
-
|
155
|
-
# Fetch item from redis storage
|
156
|
-
#
|
157
|
-
# @param data_type [Symbol]
|
158
|
-
# @param full_name [Symbol]
|
159
|
-
# @param args [Hash]
|
160
|
-
# @return [Object]
|
161
|
-
def get_redis_storage(data_type, full_name, args={})
|
162
|
-
self.class.redis_ping!
|
163
|
-
case data_type.to_sym
|
164
|
-
when :array
|
165
|
-
Redis::List.new(full_name, {:marshal => true}.merge(args))
|
166
|
-
when :hash
|
167
|
-
Redis::HashKey.new(full_name)
|
168
|
-
when :value
|
169
|
-
Redis::Value.new(full_name, {:marshal => true}.merge(args))
|
170
|
-
when :lock
|
171
|
-
Redis::Lock.new(full_name, {:expiration => 60, :timeout => 0.1}.merge(args))
|
172
|
-
when :stamped
|
173
|
-
Stamped.new(full_name.sub("#{key}_", '').to_sym, get_redis_storage(:value, full_name), self)
|
174
|
-
else
|
175
|
-
raise TypeError.new("Unsupported caching data type encountered: #{data_type}")
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
# Fetch item from local storage
|
180
|
-
#
|
181
|
-
# @param data_type [Symbol]
|
182
|
-
# @param full_name [Symbol]
|
183
|
-
# @param args [Hash]
|
184
|
-
# @return [Object]
|
185
|
-
# @todo make proper singleton for local storage
|
186
|
-
def get_local_storage(data_type, full_name, args={})
|
187
|
-
@storage ||= {}
|
188
|
-
@storage[full_name] ||= case data_type.to_sym
|
189
|
-
when :array
|
190
|
-
[]
|
191
|
-
when :hash
|
192
|
-
{}
|
193
|
-
when :value
|
194
|
-
LocalValue.new
|
195
|
-
when :lock
|
196
|
-
LocalLock.new(full_name, {:expiration => 60, :timeout => 0.1}.merge(args))
|
197
|
-
when :stamped
|
198
|
-
Stamped.new(full_name.sub("#{key}_", '').to_sym, get_local_storage(:value, full_name), self)
|
199
|
-
else
|
200
|
-
raise TypeError.new("Unsupported caching data type encountered: #{data_type}")
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
# Execute block within internal lock
|
205
|
-
#
|
206
|
-
# @return [Object] result of yield
|
207
|
-
# @note for internal use
|
208
|
-
def internal_lock
|
209
|
-
get_storage(self.class.type, :lock, :internal_access, :timeout => 20, :expiration => 120).lock do
|
210
|
-
yield
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
# Fetch data
|
215
|
-
#
|
216
|
-
# @param name [String, Symbol]
|
217
|
-
# @return [Object, NilClass]
|
218
|
-
def [](name)
|
219
|
-
if(kind = registry[name.to_s])
|
220
|
-
get_storage(self.class.type, kind, name)
|
221
|
-
else
|
222
|
-
nil
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
# Set data
|
227
|
-
#
|
228
|
-
# @param key [Object]
|
229
|
-
# @param val [Object]
|
230
|
-
# @note this will never work, thus you should never use it
|
231
|
-
def []=(key, val)
|
232
|
-
raise 'Setting backend data is not allowed'
|
233
|
-
end
|
234
|
-
|
235
|
-
# Check if cache time has expired
|
236
|
-
#
|
237
|
-
# @param key [String, Symbol] value key
|
238
|
-
# @param stamp [Time, Integer]
|
239
|
-
# @return [TrueClass, FalseClass]
|
240
|
-
def time_check_allow?(key, stamp)
|
241
|
-
Time.now.to_i - stamp.to_i > apply_limit(key)
|
242
|
-
end
|
243
|
-
|
244
|
-
# Apply time limit for data type
|
245
|
-
#
|
246
|
-
# @param kind [String, Symbol] data type
|
247
|
-
# @param seconds [Integer]
|
248
|
-
# return [Integer]
|
249
|
-
def apply_limit(kind, seconds=nil)
|
250
|
-
@apply_limit ||= {}
|
251
|
-
if(seconds)
|
252
|
-
@apply_limit[kind.to_sym] = seconds.to_i
|
253
|
-
end
|
254
|
-
@apply_limit[kind.to_sym].to_i
|
255
|
-
end
|
256
|
-
|
257
|
-
# Perform action within lock
|
258
|
-
#
|
259
|
-
# @param lock_name [String, Symbol] name of lock
|
260
|
-
# @param raise_on_locked [TrueClass, FalseClass] raise execption if lock wait times out
|
261
|
-
# @return [Object] result of yield
|
262
|
-
def locked_action(lock_name, raise_on_locked=false)
|
263
|
-
begin
|
264
|
-
self[lock_name].lock do
|
265
|
-
yield
|
266
|
-
end
|
267
|
-
rescue => e
|
268
|
-
if(e.class.to_s == 'Redis::Lock::LockTimeout')
|
269
|
-
raise if raise_on_locked
|
270
|
-
else
|
271
|
-
raise
|
272
|
-
end
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
|
-
# Simple value for memory cache
|
277
|
-
class LocalValue
|
278
|
-
# @return [Object] value
|
279
|
-
attr_accessor :value
|
280
|
-
def initialize(*args)
|
281
|
-
@value = nil
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
# Simple lock for memory cache
|
286
|
-
class LocalLock
|
287
|
-
|
288
|
-
# @return [Symbol] key name
|
289
|
-
attr_reader :_key
|
290
|
-
# @return [Numeric] timeout
|
291
|
-
attr_reader :_timeout
|
292
|
-
# @return [Mutex] underlying lock
|
293
|
-
attr_reader :_lock
|
294
|
-
|
295
|
-
# Create new instance
|
296
|
-
#
|
297
|
-
# @param name [Symbol] name of lock
|
298
|
-
# @param args [Hash]
|
299
|
-
# @option args [Numeric] :timeout
|
300
|
-
def initialize(name, args={})
|
301
|
-
@_key = name
|
302
|
-
@_timeout = args.fetch(:timeout, -1).to_f
|
303
|
-
@_lock = Mutex.new
|
304
|
-
end
|
305
|
-
|
306
|
-
# Aquire lock and yield
|
307
|
-
#
|
308
|
-
# @yield block to execute within lock
|
309
|
-
# @return [Object] result of yield
|
310
|
-
def lock
|
311
|
-
locked = false
|
312
|
-
attempt_start = Time.now.to_f
|
313
|
-
while(!locked && (_timeout < 0 || Time.now.to_f - attempt_start < _timeout))
|
314
|
-
locked = _lock.try_lock
|
315
|
-
end
|
316
|
-
if(locked)
|
317
|
-
begin
|
318
|
-
yield
|
319
|
-
ensure
|
320
|
-
_lock.unlock if _lock.locked?
|
321
|
-
end
|
322
|
-
else
|
323
|
-
raise Redis::Lock::LockTimeout.new "Timeout on lock #{_key} exceeded #{_timeout} sec"
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
|
-
# Clear the lock
|
328
|
-
#
|
329
|
-
# @note this is a noop
|
330
|
-
def clear
|
331
|
-
# noop
|
332
|
-
end
|
333
|
-
end
|
334
|
-
|
335
|
-
# Wrapper to auto stamp values
|
336
|
-
class Stamped
|
337
|
-
|
338
|
-
# Create new instance
|
339
|
-
#
|
340
|
-
# @param name [String, Symbol]
|
341
|
-
# @param base [Redis::Value, LocalValue]
|
342
|
-
# @param cache [Cache]
|
343
|
-
def initialize(name, base, cache)
|
344
|
-
@name = name.to_sym
|
345
|
-
@base = base
|
346
|
-
@cache = cache
|
347
|
-
end
|
348
|
-
|
349
|
-
# @return [Object] value stored
|
350
|
-
def value
|
351
|
-
@base.value[:value] if set?
|
352
|
-
end
|
353
|
-
|
354
|
-
# Store value and update timestamp
|
355
|
-
#
|
356
|
-
# @param v [Object] value
|
357
|
-
# @return [Object]
|
358
|
-
def value=(v)
|
359
|
-
@base.value = {:stamp => Time.now.to_f, :value => v}
|
360
|
-
v
|
361
|
-
end
|
362
|
-
|
363
|
-
# @return [TrueClass, FalseClass] is value set
|
364
|
-
def set?
|
365
|
-
@base.value.is_a?(Hash)
|
366
|
-
end
|
367
|
-
|
368
|
-
# @return [Float] timestamp of last set (or 0.0 if unset)
|
369
|
-
def stamp
|
370
|
-
set? ? @base.value[:stamp] : 0.0
|
371
|
-
end
|
372
|
-
|
373
|
-
# Force a timestamp update
|
374
|
-
def restamp!
|
375
|
-
self.value = value
|
376
|
-
end
|
377
|
-
|
378
|
-
# @return [TrueClass, FalseClass] update is allowed based on stamp and limits
|
379
|
-
def update_allowed?
|
380
|
-
!set? || @cache.time_check_allow?(@name, @base.value[:stamp])
|
381
|
-
end
|
382
|
-
end
|
383
|
-
|
384
|
-
end
|
385
|
-
end
|
@@ -1,195 +0,0 @@
|
|
1
|
-
require 'chef/knife'
|
2
|
-
require 'knife-cloudformation'
|
3
|
-
|
4
|
-
module KnifeCloudformation
|
5
|
-
module Knife
|
6
|
-
# Base to build cloudformation related knife commands
|
7
|
-
module Base
|
8
|
-
|
9
|
-
# Instance methods for cloudformation command classes
|
10
|
-
module InstanceMethods
|
11
|
-
|
12
|
-
# @return [KnifeCloudformation::Provider]
|
13
|
-
def provider
|
14
|
-
self.class.provider
|
15
|
-
end
|
16
|
-
|
17
|
-
# Write exception information if debug is enabled
|
18
|
-
#
|
19
|
-
# @param e [Exception]
|
20
|
-
# @param args [String] extra strings to output
|
21
|
-
def _debug(e, *args)
|
22
|
-
if(ENV['DEBUG'])
|
23
|
-
ui.fatal "Exception information: #{e.class}: #{e.message}\n#{e.backtrace.join("\n")}\n"
|
24
|
-
if(e.is_a?(Miasma::Error::ApiError))
|
25
|
-
ui.fatal "Response body: #{e.response.body.to_s.inspect}"
|
26
|
-
end
|
27
|
-
args.each do |string|
|
28
|
-
ui.fatal string
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# Get stack
|
34
|
-
#
|
35
|
-
# @param name [String] name of stack
|
36
|
-
# @return [Miasma::Models::Orchestration::Stack]
|
37
|
-
def stack(name)
|
38
|
-
provider.stacks.get(name)
|
39
|
-
end
|
40
|
-
|
41
|
-
# @return [Array<String>] attributes to display
|
42
|
-
def allowed_attributes
|
43
|
-
Chef::Config[:knife][:cloudformation][:attributes] || default_attributes
|
44
|
-
end
|
45
|
-
|
46
|
-
# @return [Array<String>] default attributes to display
|
47
|
-
def default_attributes
|
48
|
-
%w(timestamp stack_name id)
|
49
|
-
end
|
50
|
-
|
51
|
-
# Check if attribute is allowed for display
|
52
|
-
#
|
53
|
-
# @param attr [String]
|
54
|
-
# @return [TrueClass, FalseClass]
|
55
|
-
def attribute_allowed?(attr)
|
56
|
-
config[:all_attributes] || allowed_attributes.include?(attr)
|
57
|
-
end
|
58
|
-
|
59
|
-
# Poll events on stack
|
60
|
-
#
|
61
|
-
# @param name [String] name of stack
|
62
|
-
def poll_stack(name)
|
63
|
-
retry_attempts = 0
|
64
|
-
begin
|
65
|
-
provider.connection.stacks.reload
|
66
|
-
knife_events = Chef::Knife::CloudformationEvents.new
|
67
|
-
knife_events.name_args.push(name)
|
68
|
-
Chef::Config[:knife][:cloudformation][:poll] = true
|
69
|
-
knife_events.run
|
70
|
-
rescue => e
|
71
|
-
if(retry_attempts < Chef::Config[:knife][:cloudformation].fetch(:max_poll_retries, 5))
|
72
|
-
retry_attempts += 1
|
73
|
-
warn "Unexpected error encountered (#{e.class}: #{e}) Retrying [retry count: #{retry_attempts}]"
|
74
|
-
sleep(1)
|
75
|
-
retry
|
76
|
-
else
|
77
|
-
raise
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Wrapper for information retrieval. Provides consistent error
|
83
|
-
# message for failures
|
84
|
-
#
|
85
|
-
# @param stack [String] stack name
|
86
|
-
# @param message [String] failure message
|
87
|
-
# @yield block to wrap error handling
|
88
|
-
# @return [Object] result of yield
|
89
|
-
def get_things(stack=nil, message=nil)
|
90
|
-
begin
|
91
|
-
yield
|
92
|
-
rescue => e
|
93
|
-
ui.fatal "#{message || 'Failed to retrieve information'}#{" for requested stack: #{stack}" if stack}"
|
94
|
-
ui.fatal "Reason: #{e}"
|
95
|
-
_debug(e)
|
96
|
-
exit 1
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
# Disable chef configuration. Let the dep loader do that for us
|
101
|
-
# so it doesn't squash config values set via options
|
102
|
-
def configure_chef
|
103
|
-
true
|
104
|
-
end
|
105
|
-
|
106
|
-
# Wrapper to allow consistent exception handling
|
107
|
-
def run
|
108
|
-
begin
|
109
|
-
_run
|
110
|
-
rescue => e
|
111
|
-
ui.fatal "Unexpected Error: #{e.message}"
|
112
|
-
_debug(e)
|
113
|
-
exit 1
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
end
|
118
|
-
|
119
|
-
module ClassMethods
|
120
|
-
|
121
|
-
# @return [KnifeCloudformation::Provider]
|
122
|
-
def provider
|
123
|
-
Thread.current[:_provider] ||= KnifeCloudformation::Provider.new(
|
124
|
-
:miasma => Chef::Config[:knife][:cloudformation][:credentials],
|
125
|
-
:async => false,
|
126
|
-
:fetch => false
|
127
|
-
)
|
128
|
-
end
|
129
|
-
|
130
|
-
# @return [FalseClass]
|
131
|
-
def use_separate_defaults?
|
132
|
-
false
|
133
|
-
end
|
134
|
-
|
135
|
-
end
|
136
|
-
|
137
|
-
class << self
|
138
|
-
def included(klass)
|
139
|
-
klass.instance_eval do
|
140
|
-
|
141
|
-
extend KnifeCloudformation::Knife::Base::ClassMethods
|
142
|
-
include KnifeCloudformation::Knife::Base::InstanceMethods
|
143
|
-
include KnifeCloudformation::Utils::JSON
|
144
|
-
include KnifeCloudformation::Utils::AnimalStrings
|
145
|
-
include KnifeCloudformation::Utils::Output
|
146
|
-
|
147
|
-
deps do
|
148
|
-
Chef::Knife.new.configure_chef
|
149
|
-
require 'miasma'
|
150
|
-
Chef::Config[:knife][:cloudformation] ||= Mash.new
|
151
|
-
Chef::Config[:knife][:cloudformation][:credentials] ||= Mash.new
|
152
|
-
Chef::Config[:knife][:cloudformation][:options] ||= Mash.new
|
153
|
-
Chef::Config[:knife][:cloudformation][:ignore_parameters] = []
|
154
|
-
%w(poll interactive_parameters apply_nesting).each do |key|
|
155
|
-
if(Chef::Config[:knife][:cloudformation][key].nil?)
|
156
|
-
Chef::Config[:knife][:cloudformation][key] = true
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
option(:credentials,
|
162
|
-
:short => '-S CREDENTIALS',
|
163
|
-
:long => '--credentials CREDENTIALS',
|
164
|
-
:description => 'Miasma API options. Comma delimited or used multiple times. (-S "aws_access_key_id=MYKEY")',
|
165
|
-
:proc => lambda {|val|
|
166
|
-
val.split(',').each do |pair|
|
167
|
-
key, value = pair.split('=')
|
168
|
-
Chef::Config[:knife][:cloudformation][:credentials][key] = value
|
169
|
-
end
|
170
|
-
}
|
171
|
-
)
|
172
|
-
|
173
|
-
option(:ignore_parameter,
|
174
|
-
:long => '--ignore-parameter PARAMETER_NAME',
|
175
|
-
:description => 'Parameter to ignore during modifications (can be used multiple times)',
|
176
|
-
:proc => lambda{|val| Chef::Config[:knife][:cloudformation][:ignore_parameters].push(val).uniq! }
|
177
|
-
)
|
178
|
-
|
179
|
-
# Populate up the hashes so they are available for knife config
|
180
|
-
# with issues of nils
|
181
|
-
['knife.cloudformation.credentials', 'knife.cloudformation.options'].each do |stack|
|
182
|
-
stack.split('.').inject(Chef::Config) do |memo, item|
|
183
|
-
memo[item.to_sym] = Mash.new unless memo[item.to_sym]
|
184
|
-
memo[item.to_sym]
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
end
|
189
|
-
|
190
|
-
end
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
end
|
195
|
-
end
|