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.
@@ -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
@@ -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
- stack_line = stack[0].match(/^(?<path>.+):(?<ln>\d+):in `(?<method>.+)'$/).named_captures
16
- stack_line["path"].gsub!(MuxTf::ROOT, pastel.gray("{mux_tf}"))
17
- msg = [
18
- "#{pastel.orange('WARNING')}: #{message}",
19
- "at #{pastel.cyan(stack_line['path'])}:#{pastel.white(stack_line['ln'])}:in `#{pastel.cyan(stack_line['method'])}'"
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 => e
108
- ap e
112
+ rescue Psych::DisallowedClass => _e
113
+ # ap e
109
114
  false
110
- rescue Psych::SyntaxError => e # rubocop:disable Lint/DuplicateBranch
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 text_version_of_plan_show(plan_filename)
347
- result = tf_show(plan_filename, capture: true, json: true)
348
- data = result.parsed_output
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
- # Plan: 0 to add, 1 to change, 0 to destroy.
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
- output << tf_show_json_resource(resource) if resource["change"]["actions"] != ["no-op"]
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)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MuxTf
4
- VERSION = "0.16.0"
4
+ VERSION = "0.17.0"
5
5
  end
@@ -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 # rubocop:disable Style/AccessModifierDeclarations
28
+ module_function :has_updates?, :latest_gem_version, :current_gem_version, :cache
29
29
  end
30
30
  end
@@ -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
- 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
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 = YAML::Store.new path
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.1.1"
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.16.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-02-26 00:00:00.000000000 Z
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.1.1
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.1.1
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
- description:
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.22
268
- signing_key:
308
+ rubygems_version: 3.6.2
269
309
  specification_version: 4
270
310
  summary: Terraform Multiplexing Scripts
271
311
  test_files: []