mux_tf 0.16.0 → 0.17.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/lib/mux_tf/cli/current/plan_command.rb +18 -10
- data/lib/mux_tf/cli/current.rb +94 -49
- data/lib/mux_tf/formatter_common.rb +257 -0
- data/lib/mux_tf/init_formatter.rb +306 -0
- data/lib/mux_tf/plan_formatter.rb +174 -519
- data/lib/mux_tf/plan_summary_handler.rb +16 -2
- data/lib/mux_tf/plan_utils.rb +198 -55
- data/lib/mux_tf/stderr_line_handler.rb +1 -1
- data/lib/mux_tf/terraform_helpers.rb +2 -1
- data/lib/mux_tf/version.rb +1 -1
- data/lib/mux_tf/version_check.rb +1 -1
- data/lib/mux_tf/yaml_cache.rb +51 -34
- data/mux_tf.gemspec +6 -1
- metadata +49 -9
@@ -17,7 +17,7 @@ module MuxTf
|
|
17
17
|
if File.exist?("#{file}.json") && File.mtime("#{file}.json").to_f >= File.mtime(file).to_f
|
18
18
|
JSON.parse(File.read("#{file}.json"))
|
19
19
|
else
|
20
|
-
puts "Analyzing changes ..."
|
20
|
+
puts "Analyzing changes ... #{file}"
|
21
21
|
result = tf_show(file, json: true)
|
22
22
|
data = result.parsed_output
|
23
23
|
File.write("#{file}.json", JSON.dump(data))
|
@@ -43,7 +43,7 @@ module MuxTf
|
|
43
43
|
:red
|
44
44
|
when "read"
|
45
45
|
:cyan
|
46
|
-
when "import" # rubocop:disable Lint/DuplicateBranch
|
46
|
+
when "import", "forget" # rubocop:disable Lint/DuplicateBranch
|
47
47
|
:cyan
|
48
48
|
else
|
49
49
|
:reset
|
@@ -68,6 +68,8 @@ module MuxTf
|
|
68
68
|
"→"
|
69
69
|
when "import-update"
|
70
70
|
"↗︎"
|
71
|
+
when "forget"
|
72
|
+
"↺"
|
71
73
|
else
|
72
74
|
action
|
73
75
|
end
|
@@ -99,6 +101,7 @@ module MuxTf
|
|
99
101
|
end
|
100
102
|
|
101
103
|
def initialize(data)
|
104
|
+
@data = data
|
102
105
|
@parts = []
|
103
106
|
|
104
107
|
data["output_changes"]&.each do |output_name, v|
|
@@ -193,6 +196,13 @@ module MuxTf
|
|
193
196
|
address: v["address"],
|
194
197
|
deps: find_deps(data, v["address"])
|
195
198
|
}
|
199
|
+
when ["forget"]
|
200
|
+
parts << {
|
201
|
+
type: "resource",
|
202
|
+
action: "forget",
|
203
|
+
address: v["address"],
|
204
|
+
deps: find_deps(data, v["address"])
|
205
|
+
}
|
196
206
|
else
|
197
207
|
puts "[??] #{v['address']}"
|
198
208
|
puts "UNKNOWN RESOURCE ACTIONS: #{v['change']['actions'].inspect}"
|
@@ -333,6 +343,10 @@ module MuxTf
|
|
333
343
|
end
|
334
344
|
end
|
335
345
|
|
346
|
+
def plan_text_output
|
347
|
+
PlanUtils.text_version_of_plan_show_from_data(@data)
|
348
|
+
end
|
349
|
+
|
336
350
|
private
|
337
351
|
|
338
352
|
attr_reader :parts
|
data/lib/mux_tf/plan_utils.rb
CHANGED
@@ -12,12 +12,17 @@ module MuxTf
|
|
12
12
|
class << self
|
13
13
|
def warning(message, binding_arg: binding)
|
14
14
|
stack = binding_arg.send(:caller)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
stack_match = stack[0].match(/^(?<path>.+):(?<ln>\d+):in [`'](?<method>.+)'$/)
|
16
|
+
msg = []
|
17
|
+
if stack_match
|
18
|
+
stack_line = stack_match.named_captures
|
19
|
+
stack_line["path"].gsub!(MuxTf::ROOT, pastel.gray("{mux_tf}"))
|
20
|
+
msg << "#{pastel.orange('WARNING')}: #{message}"
|
21
|
+
msg << "at #{pastel.cyan(stack_line['path'])}:#{pastel.white(stack_line['ln'])}:in `#{pastel.cyan(stack_line['method'])}'"
|
22
|
+
else
|
23
|
+
p [stack_match, stack[0]]
|
24
|
+
msg << "#{pastel.orange('WARNING')}: #{message}"
|
25
|
+
end
|
21
26
|
puts msg.join(" - ")
|
22
27
|
end
|
23
28
|
|
@@ -104,11 +109,11 @@ module MuxTf
|
|
104
109
|
else
|
105
110
|
false
|
106
111
|
end
|
107
|
-
rescue Psych::DisallowedClass =>
|
108
|
-
ap e
|
112
|
+
rescue Psych::DisallowedClass => _e
|
113
|
+
# ap e
|
109
114
|
false
|
110
|
-
rescue Psych::SyntaxError =>
|
111
|
-
ap e
|
115
|
+
rescue Psych::SyntaxError => _e # rubocop:disable Lint/DuplicateBranch
|
116
|
+
# ap e
|
112
117
|
false
|
113
118
|
end
|
114
119
|
|
@@ -122,6 +127,12 @@ module MuxTf
|
|
122
127
|
pastel.red(symbol)
|
123
128
|
when "?"
|
124
129
|
pastel.orange(symbol)
|
130
|
+
when "±"
|
131
|
+
pastel.bright_red(symbol)
|
132
|
+
when ">"
|
133
|
+
pastel.blue(symbol)
|
134
|
+
when " "
|
135
|
+
symbol
|
125
136
|
else
|
126
137
|
warning "Unknown symbol: #{symbol.inspect}"
|
127
138
|
symbol
|
@@ -230,32 +241,6 @@ module MuxTf
|
|
230
241
|
format_value_diff(mode, value_arg)
|
231
242
|
end
|
232
243
|
|
233
|
-
# def format_value(value_arg, symbol)
|
234
|
-
# case value_arg
|
235
|
-
# when Array
|
236
|
-
# mode = :both
|
237
|
-
# case symbol
|
238
|
-
# when "+"
|
239
|
-
# mode = :right
|
240
|
-
# when "~"
|
241
|
-
# mode = :both
|
242
|
-
# else
|
243
|
-
# warning "Unknown symbol: #{symbol.inspect}"
|
244
|
-
# end
|
245
|
-
|
246
|
-
# format_value_diff(mode, value_arg)
|
247
|
-
# when Hash
|
248
|
-
# if value_arg.keys.all? { |k| k.is_a?(Integer) }
|
249
|
-
# # assuming its a hash notation of array keys changes
|
250
|
-
# value_arg.keys.sort.map { |k| "[#{k}] #{format_value(value_arg[k], symbol)[0]}" }
|
251
|
-
# else
|
252
|
-
# [value_arg.inspect]
|
253
|
-
# end
|
254
|
-
# else
|
255
|
-
# [value_arg.inspect]
|
256
|
-
# end
|
257
|
-
# end
|
258
|
-
|
259
244
|
def get_pretty_action_and_symbol(actions)
|
260
245
|
case actions
|
261
246
|
when ["delete"]
|
@@ -273,6 +258,9 @@ module MuxTf
|
|
273
258
|
when ["read"]
|
274
259
|
pretty_action = "read"
|
275
260
|
symbol = ">"
|
261
|
+
when ["no-op"]
|
262
|
+
pretty_action = "no-op"
|
263
|
+
symbol = " "
|
276
264
|
else
|
277
265
|
warning "Unknown action: #{actions.inspect}"
|
278
266
|
pretty_action = actions.inspect
|
@@ -311,44 +299,188 @@ module MuxTf
|
|
311
299
|
|
312
300
|
output << ""
|
313
301
|
output << "#{global_indent}#{pastel.bold("# #{resource['address']}")} will be #{pretty_action}"
|
302
|
+
output << "#{global_indent} >> #{action_reason_to_text(resource['action_reason'])}" if resource["action_reason"]
|
314
303
|
output << "#{global_indent}#{colorize_symbol(symbol)} resource \"#{resource['type']}\" \"#{resource['name']}\" {"
|
315
304
|
diff = tf_show_json_resource_diff(resource)
|
316
305
|
max_diff_key_length = diff.map { |change| change[1].length }.max
|
306
|
+
|
307
|
+
fields_which_caused_replacement = []
|
308
|
+
|
309
|
+
if resource["change"]["replace_paths"]
|
310
|
+
if resource["change"]["replace_paths"].length != 1
|
311
|
+
warning "Multiple replace paths found for resource #{resource['address']}: #{resource['change']['replace_paths'].inspect}"
|
312
|
+
elsif resource["change"]["replace_paths"][0].length != 1
|
313
|
+
warning "Multiple fields found to be replaced for resource #{resource['address']}: #{resource['change']['replace_paths'].inspect}"
|
314
|
+
else
|
315
|
+
fields_which_caused_replacement << resource["change"]["replace_paths"][0][0]
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
317
319
|
diff.each do |change|
|
318
320
|
change_symbol, key, *_values = change
|
319
321
|
prefix = format("#{global_indent} #{colorize_symbol(change_symbol)} %s = ", key.ljust(max_diff_key_length))
|
322
|
+
suffix = ""
|
323
|
+
suffix = " (forces replacement)" if fields_which_caused_replacement.include?(key)
|
320
324
|
blank_prefix = " " * pastel.strip(prefix).length
|
321
325
|
format_value(change).each_with_index do |line, index|
|
322
326
|
output << if index.zero?
|
323
|
-
"#{prefix}#{line}"
|
327
|
+
"#{prefix}#{line}#{suffix}"
|
324
328
|
else
|
325
|
-
"#{blank_prefix}#{line}"
|
329
|
+
"#{blank_prefix}#{line}#{suffix}"
|
326
330
|
end
|
327
331
|
end
|
328
332
|
end
|
329
|
-
# max_diff_key_length = diff.keys.map(&:length).max
|
330
|
-
# diff.each do |key, value|
|
331
|
-
# prefix = format("#{global_indent} #{colorize_symbol(symbol)} %s = ", key.ljust(max_diff_key_length))
|
332
|
-
# blank_prefix = " " * pastel.strip(prefix).length
|
333
|
-
# format_value(value, symbol).each_with_index do |line, index|
|
334
|
-
# output << if index.zero?
|
335
|
-
# "#{prefix}#{line}"
|
336
|
-
# else
|
337
|
-
# "#{blank_prefix}#{line}"
|
338
|
-
# end
|
339
|
-
# end
|
340
|
-
# end
|
341
333
|
output << "#{global_indent}}"
|
342
334
|
|
343
335
|
output.join("\n")
|
344
336
|
end
|
345
337
|
|
346
|
-
def
|
347
|
-
|
348
|
-
|
338
|
+
def format_output_value_diff(mode, value_arg)
|
339
|
+
case mode
|
340
|
+
when :both
|
341
|
+
vleft = in_display_representation(value_arg[0])
|
342
|
+
vright = in_display_representation(value_arg[1])
|
343
|
+
if [vleft, vright].any? { |v| v.is_a?(String) && v.include?("\n") }
|
344
|
+
if pastel.strip(vright) == KNOWN_AFTER_APPLY
|
345
|
+
"#{vleft} -> #{vright}".split("\n")
|
346
|
+
else
|
347
|
+
string_diff(pastel.strip(vleft), pastel.strip(vright))
|
348
|
+
end
|
349
|
+
else
|
350
|
+
"#{vleft} -> #{vright}".split("\n")
|
351
|
+
end
|
352
|
+
when :right
|
353
|
+
vright = in_display_representation(value_arg[1])
|
354
|
+
vright.split("\n")
|
355
|
+
when :left, :first
|
356
|
+
vleft = in_display_representation(value_arg[0])
|
357
|
+
vleft.split("\n")
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
def get_x_type(key, change)
|
362
|
+
return :hash if change[key].is_a?(Hash) || change["#{key}_sensitive"].is_a?(Hash) || change["#{key}_unknown"].is_a?(Hash)
|
363
|
+
return :array if change[key].is_a?(Array) || change["#{key}_sensitive"].is_a?(Array) || change["#{key}_unknown"].is_a?(Array)
|
364
|
+
|
365
|
+
:scalar
|
366
|
+
end
|
367
|
+
|
368
|
+
def get_value_type(change)
|
369
|
+
case change["actions"]
|
370
|
+
when ["create"]
|
371
|
+
get_x_type("after", change)
|
372
|
+
when ["delete"]
|
373
|
+
get_x_type("before", change)
|
374
|
+
when ["update"]
|
375
|
+
bt = get_x_type("before", change)
|
376
|
+
at = get_x_type("after", change)
|
377
|
+
raise "Type mismatch before vs after: #{bt} != #{at}" if bt != at
|
378
|
+
|
379
|
+
at
|
380
|
+
when ["no-op"]
|
381
|
+
:none
|
382
|
+
else
|
383
|
+
raise "Unknown action: #{change['actions'].inspect}"
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
def prep_before_after(change)
|
388
|
+
before = change["before"]
|
389
|
+
after = change["after"]
|
390
|
+
before = KNOWN_AFTER_APPLY if change["before_unknown"]
|
391
|
+
before = SENSITIVE if change["before_sensitive"]
|
392
|
+
after = KNOWN_AFTER_APPLY if change["after_unknown"]
|
393
|
+
after = SENSITIVE if change["after_sensitive"]
|
394
|
+
|
395
|
+
[before, after]
|
396
|
+
end
|
397
|
+
|
398
|
+
def tf_show_json_output(output_key, output_change, max_outer_key_length)
|
399
|
+
_pretty_action, symbol = get_pretty_action_and_symbol(output_change["actions"])
|
400
|
+
|
401
|
+
output = []
|
402
|
+
|
403
|
+
global_indent = " " * 2
|
404
|
+
|
405
|
+
value_type = get_value_type(output_change)
|
406
|
+
|
407
|
+
start_prefix = format("#{global_indent}#{colorize_symbol(symbol)} %s = ", output_key.ljust(max_outer_key_length))
|
408
|
+
blank_start_prefix = " " * pastel.strip(start_prefix).length
|
409
|
+
outer_mode = :both
|
410
|
+
outer_mode = :right if ["+"].include?(symbol)
|
411
|
+
outer_mode = :left if ["-"].include?(symbol)
|
412
|
+
outer_mode = :right if [" "].include?(symbol)
|
413
|
+
|
414
|
+
case value_type
|
415
|
+
when :hash
|
416
|
+
output << "#{start_prefix}{"
|
417
|
+
|
418
|
+
fake_resource = {
|
419
|
+
"change" => output_change
|
420
|
+
}
|
421
|
+
diff = tf_show_json_resource_diff(fake_resource)
|
422
|
+
max_diff_key_length = diff.map { |change| change[1].length }.max
|
423
|
+
|
424
|
+
diff.each do |change|
|
425
|
+
change_symbol, key, *_values = change
|
426
|
+
prefix = format("#{global_indent} #{colorize_symbol(change_symbol)} %s = ", key.ljust(max_diff_key_length))
|
427
|
+
suffix = ""
|
428
|
+
blank_prefix = " " * pastel.strip(prefix).length
|
429
|
+
format_value(change).each_with_index do |line, index|
|
430
|
+
output << if index.zero?
|
431
|
+
"#{prefix}#{line}#{suffix}"
|
432
|
+
else
|
433
|
+
"#{blank_prefix}#{line}#{suffix}"
|
434
|
+
end
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
438
|
+
output << "#{global_indent} }"
|
439
|
+
when :array, :scalar, :none
|
440
|
+
before, after = prep_before_after(output_change)
|
441
|
+
format_value_diff(outer_mode, [before, after]).each_with_index do |line, index|
|
442
|
+
output << if index.zero?
|
443
|
+
"#{start_prefix}#{line}"
|
444
|
+
else
|
445
|
+
"#{blank_start_prefix}#{line}"
|
446
|
+
end
|
447
|
+
end
|
448
|
+
else
|
449
|
+
raise "Unknown value type: #{value_type.inspect}"
|
450
|
+
end
|
451
|
+
|
452
|
+
output.join("\n")
|
453
|
+
end
|
349
454
|
|
350
|
-
|
455
|
+
# See https://developer.hashicorp.com/terraform/internals/json-format
|
456
|
+
def action_reason_to_text(action_reason)
|
457
|
+
case action_reason
|
458
|
+
when "replace_because_tainted"
|
459
|
+
"because the object is tainted in the prior state"
|
460
|
+
when "replace_because_cannot_update"
|
461
|
+
"because the provider does not support updating the object, or the changed attributes"
|
462
|
+
when "replace_by_request"
|
463
|
+
"because the user requested the object to be replaced"
|
464
|
+
when "delete_because_no_resource_config"
|
465
|
+
"because the object is no longer in the configuration"
|
466
|
+
when "delete_because_no_module"
|
467
|
+
"because the module this object belongs to is no longer in the configuration"
|
468
|
+
when "delete_because_wrong_repetition"
|
469
|
+
"because of the repetition mode has changed"
|
470
|
+
when "delete_because_count_index"
|
471
|
+
"because the repetition count has changed"
|
472
|
+
when "delete_because_each_key"
|
473
|
+
"because the repetition key has changed"
|
474
|
+
when "read_because_config_unknown"
|
475
|
+
"because reading this will only be possible during apply"
|
476
|
+
when "read_because_dependency_pending"
|
477
|
+
"because reading this will only be possible after a dependency is available"
|
478
|
+
else
|
479
|
+
"because #{action_reason}"
|
480
|
+
end
|
481
|
+
end
|
351
482
|
|
483
|
+
def text_version_of_plan_show_from_data(data)
|
352
484
|
output = []
|
353
485
|
|
354
486
|
output << "Terraform will perform the following actions:"
|
@@ -365,7 +497,18 @@ module MuxTf
|
|
365
497
|
output << ""
|
366
498
|
output << "Resource Changes:"
|
367
499
|
data["resource_changes"].each do |resource|
|
368
|
-
|
500
|
+
next if resource["change"]["actions"] == ["no-op"]
|
501
|
+
|
502
|
+
output << tf_show_json_resource(resource)
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
if data["output_changes"]
|
507
|
+
output << ""
|
508
|
+
output << "Changes to Outputs:"
|
509
|
+
max_outer_key_length = data["output_changes"].keys.map(&:length).max || 0
|
510
|
+
data["output_changes"].each do |key, output_change|
|
511
|
+
output << tf_show_json_output(key, output_change, max_outer_key_length)
|
369
512
|
end
|
370
513
|
end
|
371
514
|
|
@@ -60,7 +60,7 @@ module MuxTf
|
|
60
60
|
transform_paths!(parsed_line, "msg")
|
61
61
|
transform_paths!(parsed_line, "prefix")
|
62
62
|
parsed_line["msg"].gsub!("#{Dir.getwd}/", "")
|
63
|
-
parsed_line["prefix"]&.strip!&.gsub!(/^\[/, "")&.gsub!(/\]$/, "")
|
63
|
+
parsed_line["prefix"]&.strip!&.gsub!(/^\[/, "")&.gsub!(/\]$/, "") # rubocop:disable Style/SafeNavigationChainLength
|
64
64
|
parsed_line["prefix"]&.gsub!(Dir.getwd, "")
|
65
65
|
if @operation == :plan
|
66
66
|
handle_plan_json(parsed_line)
|
@@ -63,12 +63,13 @@ module MuxTf
|
|
63
63
|
JSON.parse(stdout)
|
64
64
|
end
|
65
65
|
|
66
|
-
def tf_init(input: nil, upgrade: nil, reconfigure: nil, color: true, &block)
|
66
|
+
def tf_init(input: nil, upgrade: nil, reconfigure: nil, color: true, json: false, &block)
|
67
67
|
args = []
|
68
68
|
args << "-input=#{input.inspect}" unless input.nil?
|
69
69
|
args << "-upgrade" unless upgrade.nil?
|
70
70
|
args << "-reconfigure" unless reconfigure.nil?
|
71
71
|
args << "-no-color" unless color
|
72
|
+
args << "-json" if json
|
72
73
|
|
73
74
|
cmd = tf_prepare_command(["init", *args], need_auth: true)
|
74
75
|
stream_terraform(cmd, split_streams: true, &block)
|
data/lib/mux_tf/version.rb
CHANGED
data/lib/mux_tf/version_check.rb
CHANGED
@@ -25,6 +25,6 @@ module MuxTf
|
|
25
25
|
@cache ||= YamlCache.new(File.expand_path("~/.mux_tf.yaml"), default_ttl: 1.hour)
|
26
26
|
end
|
27
27
|
|
28
|
-
module_function :has_updates?, :latest_gem_version, :current_gem_version, :cache
|
28
|
+
module_function :has_updates?, :latest_gem_version, :current_gem_version, :cache
|
29
29
|
end
|
30
30
|
end
|
data/lib/mux_tf/yaml_cache.rb
CHANGED
@@ -3,46 +3,63 @@
|
|
3
3
|
require "yaml/store"
|
4
4
|
|
5
5
|
# Ruby 2.7's YAML doesn't have a :unsafe_load method .. so we skip all that
|
6
|
-
if YAML.singleton_methods.include?(:unsafe_load)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
6
|
+
# if YAML.singleton_methods.include?(:unsafe_load)
|
7
|
+
# module YAML
|
8
|
+
# # Explaination from @h4xnoodle:
|
9
|
+
# #
|
10
|
+
# # Since ruby 3+ and psych 4+, the yaml loading became extra safe so the
|
11
|
+
# # expired_at timestamp in the yaml cache is no longer parsing for whatever reason.
|
12
|
+
# #
|
13
|
+
# # Attempts were made with
|
14
|
+
# #
|
15
|
+
# # `@store = YAML::Store.new path`
|
16
|
+
# # =>
|
17
|
+
# # `@store = YAML::Store.new(path, { aliases: true, permitted_classes: [Time] })`
|
18
|
+
# # to get it to work but that didn't help, so decided to just bypass the safe
|
19
|
+
# # loading, since the file is controlled by us for the version checking.
|
20
|
+
# #
|
21
|
+
# # This is to override the way that psych seems to be loading YAML.
|
22
|
+
# # Instead of using 'load' which needs work to permit the 'Time' class
|
23
|
+
# # (which from above I tried that and it wasn't working so I decided to just
|
24
|
+
# # bypass and use what it was doing before).
|
25
|
+
# # This brings us back to the equivalent that was working before in that unsafe
|
26
|
+
# # load was used before the psych upgrade.
|
27
|
+
# #
|
28
|
+
# # This change: https://my.diffend.io/gems/psych/3.3.2/4.0.0
|
29
|
+
# # is the changes that 'cause the problem' and so I'm 'fixing it' by using the old equivalent.
|
30
|
+
# #
|
31
|
+
# # Maybe the yaml cache needs more work to have
|
32
|
+
# # `YAML::Store.new(path, { aliases: true, permitted_classes: [Time] }) work.`
|
33
|
+
# #
|
34
|
+
# class << self
|
35
|
+
# undef load # avoid a warning about the next line redefining load
|
36
|
+
# alias load unsafe_load
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
|
41
|
+
module MuxTf
|
42
|
+
class UnsafeYamlStore < YAML::Store
|
43
|
+
def initialize(*args)
|
44
|
+
super
|
45
|
+
@opt[:permitted_classes] ||= [Symbol]
|
46
|
+
end
|
47
|
+
|
48
|
+
# basically have to override the whole load method, since it doesn't allow customization of the allowed classes ..
|
49
|
+
def load(content)
|
50
|
+
table = YAML.safe_load(content, **@opt)
|
51
|
+
if [false, nil].include?(table)
|
52
|
+
{}
|
53
|
+
else
|
54
|
+
table
|
55
|
+
end
|
37
56
|
end
|
38
57
|
end
|
39
|
-
end
|
40
58
|
|
41
|
-
module MuxTf
|
42
59
|
class YamlCache
|
43
60
|
def initialize(path, default_ttl:)
|
44
61
|
@default_ttl = default_ttl
|
45
|
-
@store =
|
62
|
+
@store = UnsafeYamlStore.new path, { aliases: true, permitted_classes: [Symbol, Time] }
|
46
63
|
end
|
47
64
|
|
48
65
|
def set(key, value, ttl: @default_ttl)
|
data/mux_tf.gemspec
CHANGED
@@ -40,9 +40,14 @@ Gem::Specification.new do |spec|
|
|
40
40
|
spec.add_dependency "dotenv"
|
41
41
|
spec.add_dependency "hashdiff"
|
42
42
|
spec.add_dependency "pastel"
|
43
|
-
spec.add_dependency "piotrb_cli_utils", "~> 0.
|
43
|
+
spec.add_dependency "piotrb_cli_utils", "~> 0.2.0"
|
44
44
|
spec.add_dependency "stateful_parser", "~> 0.1.1"
|
45
45
|
spec.add_dependency "tty-prompt"
|
46
46
|
spec.add_dependency "tty-table"
|
47
47
|
spec.add_dependency "zeitwerk", "~> 2.6"
|
48
|
+
|
49
|
+
# stdlib suff
|
50
|
+
spec.add_dependency "benchmark"
|
51
|
+
spec.add_dependency "ostruct"
|
52
|
+
spec.add_dependency "pstore"
|
48
53
|
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mux_tf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Banasik
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date: 2025-
|
10
|
+
date: 2025-05-12 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: activesupport
|
@@ -142,14 +141,14 @@ dependencies:
|
|
142
141
|
requirements:
|
143
142
|
- - "~>"
|
144
143
|
- !ruby/object:Gem::Version
|
145
|
-
version: 0.
|
144
|
+
version: 0.2.0
|
146
145
|
type: :runtime
|
147
146
|
prerelease: false
|
148
147
|
version_requirements: !ruby/object:Gem::Requirement
|
149
148
|
requirements:
|
150
149
|
- - "~>"
|
151
150
|
- !ruby/object:Gem::Version
|
152
|
-
version: 0.
|
151
|
+
version: 0.2.0
|
153
152
|
- !ruby/object:Gem::Dependency
|
154
153
|
name: stateful_parser
|
155
154
|
requirement: !ruby/object:Gem::Requirement
|
@@ -206,7 +205,48 @@ dependencies:
|
|
206
205
|
- - "~>"
|
207
206
|
- !ruby/object:Gem::Version
|
208
207
|
version: '2.6'
|
209
|
-
|
208
|
+
- !ruby/object:Gem::Dependency
|
209
|
+
name: benchmark
|
210
|
+
requirement: !ruby/object:Gem::Requirement
|
211
|
+
requirements:
|
212
|
+
- - ">="
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: '0'
|
215
|
+
type: :runtime
|
216
|
+
prerelease: false
|
217
|
+
version_requirements: !ruby/object:Gem::Requirement
|
218
|
+
requirements:
|
219
|
+
- - ">="
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: '0'
|
222
|
+
- !ruby/object:Gem::Dependency
|
223
|
+
name: ostruct
|
224
|
+
requirement: !ruby/object:Gem::Requirement
|
225
|
+
requirements:
|
226
|
+
- - ">="
|
227
|
+
- !ruby/object:Gem::Version
|
228
|
+
version: '0'
|
229
|
+
type: :runtime
|
230
|
+
prerelease: false
|
231
|
+
version_requirements: !ruby/object:Gem::Requirement
|
232
|
+
requirements:
|
233
|
+
- - ">="
|
234
|
+
- !ruby/object:Gem::Version
|
235
|
+
version: '0'
|
236
|
+
- !ruby/object:Gem::Dependency
|
237
|
+
name: pstore
|
238
|
+
requirement: !ruby/object:Gem::Requirement
|
239
|
+
requirements:
|
240
|
+
- - ">="
|
241
|
+
- !ruby/object:Gem::Version
|
242
|
+
version: '0'
|
243
|
+
type: :runtime
|
244
|
+
prerelease: false
|
245
|
+
version_requirements: !ruby/object:Gem::Requirement
|
246
|
+
requirements:
|
247
|
+
- - ">="
|
248
|
+
- !ruby/object:Gem::Version
|
249
|
+
version: '0'
|
210
250
|
email:
|
211
251
|
- piotr@jane.app
|
212
252
|
executables:
|
@@ -228,8 +268,10 @@ files:
|
|
228
268
|
- lib/mux_tf/cli/plan_summary.rb
|
229
269
|
- lib/mux_tf/coloring.rb
|
230
270
|
- lib/mux_tf/error_handling_methods.rb
|
271
|
+
- lib/mux_tf/formatter_common.rb
|
231
272
|
- lib/mux_tf/handlers.rb
|
232
273
|
- lib/mux_tf/handlers/plan_handler.rb
|
274
|
+
- lib/mux_tf/init_formatter.rb
|
233
275
|
- lib/mux_tf/plan_filename_generator.rb
|
234
276
|
- lib/mux_tf/plan_formatter.rb
|
235
277
|
- lib/mux_tf/plan_summary_handler.rb
|
@@ -249,7 +291,6 @@ metadata:
|
|
249
291
|
rubygems_mfa_required: 'true'
|
250
292
|
homepage_uri: https://github.com/piotrb/mux_tf
|
251
293
|
source_code_uri: https://github.com/piotrb/mux_tf
|
252
|
-
post_install_message:
|
253
294
|
rdoc_options: []
|
254
295
|
require_paths:
|
255
296
|
- lib
|
@@ -264,8 +305,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
264
305
|
- !ruby/object:Gem::Version
|
265
306
|
version: '0'
|
266
307
|
requirements: []
|
267
|
-
rubygems_version: 3.2
|
268
|
-
signing_key:
|
308
|
+
rubygems_version: 3.6.2
|
269
309
|
specification_version: 4
|
270
310
|
summary: Terraform Multiplexing Scripts
|
271
311
|
test_files: []
|