mux_tf 0.13.0 → 0.14.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ab68c9969748e0246a48cb2bf53876b0b2f47993b021017e1e9bb31782a7e4b4
4
- data.tar.gz: 63fb2194ba923f3c30c9480f50946c550e85ea9e7e1988fdcc1764cbe7666f6a
3
+ metadata.gz: f9a03af7a131fd34e58d5fb27d3c578154f49246634a684980e6ebc16aa28d08
4
+ data.tar.gz: d093d1604dabbeb1aed8ef5b1ebc3e33a0b5e3575602f7b3802796b2b51f7a7a
5
5
  SHA512:
6
- metadata.gz: e8d1442c6cff1c7c0828347176b1cc0a49fa28fb5a27e0212e730e3bf176fc4a072ba247e9cbf6d248c488fb1c62ffc6a71181dbde47e0b35a759b798ded6886
7
- data.tar.gz: 3d85fc7be2b58bd815060145c33bccf7dc5814a5ee3a052f5adc6a4c7512792e290f0b1bb26faa07d4f950aab81036bcf9c09b91c2a3a20878fcd70601bd2044
6
+ metadata.gz: 7809b83e63a8aa17671ef6fbaac79a09cd7aa8216fdd1ccd390f2e32ee0b4ec0a85e4f6653d4c4bbbafcb99d47076413a9135f970f4d4c0f7f8608b2e8858f5f
7
+ data.tar.gz: c9dd73ed72236b568c7bbdc34ede9701e1d1db94403ccd2e84ee611cd58500e73810f50c9c0bdd6817c2ef7f8bd5d504fd945d86d340db95d9246e797376efb4
data/exe/tf_current CHANGED
@@ -11,6 +11,8 @@ begin
11
11
  rescue Interrupt
12
12
  warn "\nInterrupted"
13
13
  exit 1
14
+ rescue SystemExit => e
15
+ exit e.status
14
16
  rescue Exception => e # rubocop:disable Lint/RescueException
15
17
  warn e.full_message
16
18
  warn "<press enter>"
data/exe/tf_mux CHANGED
@@ -11,6 +11,8 @@ begin
11
11
  rescue Interrupt
12
12
  warn "\nInterrupted"
13
13
  exit 1
14
+ rescue SystemExit => e
15
+ exit e.status
14
16
  rescue Exception => e # rubocop:disable Lint/RescueException
15
17
  warn e.full_message
16
18
  warn "<press enter>"
data/exe/tf_plan_summary CHANGED
@@ -11,6 +11,8 @@ begin
11
11
  rescue Interrupt
12
12
  warn "\nInterrupted"
13
13
  exit 1
14
+ rescue SystemExit => e
15
+ exit e.status
14
16
  rescue Exception => e # rubocop:disable Lint/RescueException
15
17
  warn e.full_message
16
18
  warn "<press enter>"
data/lib/deps.rb CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  require "bundler/inline"
4
4
 
5
- gemfile do
5
+ dep_def = proc do
6
6
  gemspec(path: File.join(__dir__, ".."))
7
7
  end
8
+
9
+ begin
10
+ gemfile(&dep_def)
11
+ rescue Bundler::GemNotFound
12
+ gemfile(true) do
13
+ source "https://rubygems.org"
14
+ instance_exec(&dep_def)
15
+ end
16
+ end
@@ -9,8 +9,9 @@ module MuxTf
9
9
  extend PiotrbCliUtils::Util
10
10
  extend PiotrbCliUtils::CriCommandSupport
11
11
  extend PiotrbCliUtils::CmdLoop
12
+ include Coloring
12
13
 
13
- class << self
14
+ class << self # rubocop:disable Metrics/ClassLength
14
15
  def run(args)
15
16
  version_check
16
17
 
@@ -19,8 +20,21 @@ module MuxTf
19
20
  return
20
21
  end
21
22
 
23
+ unless args.empty?
24
+ root_cmd = build_root_cmd
25
+ valid_commands = root_cmd.subcommands.map(&:name)
26
+
27
+ if args[0] && valid_commands.include?(args[0])
28
+ stop_reason = catch(:stop) {
29
+ root_cmd.run(args, {}, hard_exit: true)
30
+ }
31
+ log pastel.red("Stopped: #{stop_reason}") if stop_reason
32
+ return
33
+ end
34
+ end
35
+
22
36
  folder_name = File.basename(Dir.getwd)
23
- log "Processing #{Paint[folder_name, :cyan]} ..."
37
+ log "Processing #{pastel.cyan(folder_name)} ..."
24
38
 
25
39
  ENV["TF_IN_AUTOMATION"] = "1"
26
40
  ENV["TF_INPUT"] = "0"
@@ -55,52 +69,102 @@ module MuxTf
55
69
  def version_check
56
70
  return unless VersionCheck.has_updates?
57
71
 
58
- log Paint["=" * 80, :yellow]
59
- log "New version of #{Paint['mux_tf', :cyan]} is available!"
60
- log "You are currently on version: #{Paint[VersionCheck.current_gem_version, :yellow]}"
61
- log "Latest version found is: #{Paint[VersionCheck.latest_gem_version, :green]}"
62
- log "Run `#{Paint['gem install mux_tf', :green]}` to update!"
63
- log Paint["=" * 80, :yellow]
72
+ log pastel.yellow("=" * 80)
73
+ log "New version of #{pastel.cyan('mux_tf')} is available!"
74
+ log "You are currently on version: #{pastel.yellow(VersionCheck.current_gem_version)}"
75
+ log "Latest version found is: #{pastel.green(VersionCheck.latest_gem_version)}"
76
+ log "Run `#{pastel.green('gem install mux_tf')}` to update!"
77
+ log pastel.yellow("=" * 80)
64
78
  end
65
79
 
66
- def run_validate
67
- remedies = PlanFormatter.process_validation(validate)
68
- status, _results = process_remedies(remedies)
69
- status
80
+ # block is expected to return a touple, the first element is a list of remedies
81
+ # the rest are any additional results
82
+ def remedy_retry_helper(from:, level: 1, attempt: 0, &block)
83
+ catch(:abort) do
84
+ until attempt > 1
85
+ attempt += 1
86
+ remedies, *results = block.call
87
+ return results if remedies.empty?
88
+
89
+ remedy_status, _remedy_results = process_remedies(remedies, from: from, level: level)
90
+ return unless remedy_status
91
+ end
92
+ log "!! giving up because attempt: #{attempt}"
93
+ end
94
+ end
95
+
96
+ # returns boolean true if succeeded
97
+ def run_validate(level: 1)
98
+ remedy_retry_helper(from: :validate, level: level) do
99
+ validation_info = validate
100
+ PlanFormatter.print_validation_errors(validation_info)
101
+ remedies = PlanFormatter.process_validation(validation_info)
102
+ [remedies, validation_info]
103
+ end
70
104
  end
71
105
 
72
- def process_remedies(remedies, retry_count: 0) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
106
+ def process_remedies(remedies, from: nil, level: 1, retry_count: 0) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
107
+ remedies = remedies.dup
108
+ remedy = nil
109
+ wrap_log = lambda do |msg, color: nil|
110
+ [
111
+ from ? pastel.cyan("#{from} -> ") : nil,
112
+ pastel.cyan(remedy ? "[remedy: #{remedy}]" : "[process remedies]"),
113
+ " ",
114
+ color ? pastel.decorate(msg, color) : msg,
115
+ " ",
116
+ level > 1 ? pastel.cyan("[lv #{level}]") : nil,
117
+ retry_count.positive? ? pastel.cyan("[try #{retry_count}]") : nil
118
+ ].compact.join
119
+ end
73
120
  results = {}
74
121
  if retry_count > 5
75
- log "giving up because retry_count: #{retry_count}", depth: 1
76
- log "unprocessed remedies: #{remedies.to_a}", depth: 1
122
+ log wrap_log["giving up because retry_count: #{retry_count}", color: :yellow], depth: 1
123
+ log wrap_log["unprocessed remedies: #{remedies.to_a}", color: :red], depth: 1
77
124
  return [false, results]
78
125
  end
79
126
  if remedies.delete? :init
80
- log "[remedy] Running terraform init ...", depth: 2
81
- remedies = PlanFormatter.init_status_to_remedies(*PlanFormatter.run_tf_init)
82
- status, r_results = process_remedies(remedies)
127
+ remedy = :init
128
+ log wrap_log["Running terraform init ..."], depth: 2
129
+ exit_code, meta = PlanFormatter.run_tf_init
130
+ print_errors_and_warnings(meta)
131
+ remedies = PlanFormatter.init_status_to_remedies(exit_code, meta)
132
+ status, r_results = process_remedies(remedies, from: from, level: level + 1)
83
133
  results.merge!(r_results)
84
- if status
85
- remedies = PlanFormatter.process_validation(validate)
86
- return [false, results] unless process_remedies(remedies)
87
- end
134
+ return [true, r_results] if status
88
135
  end
89
136
  if remedies.delete?(:plan)
90
- log "[remedy] Running terraform plan ...", depth: 2
137
+ remedy = :plan
138
+ log wrap_log["Running terraform plan ..."], depth: 2
91
139
  plan_status = run_plan(retry_count: retry_count)
92
140
  results[:plan_status] = plan_status
93
141
  return [false, results] unless [:ok, :changes].include?(plan_status)
94
142
  end
95
143
  if remedies.delete? :reconfigure
96
- log "[remedy] Running terraform init ...", depth: 2
97
- remedies = PlanFormatter.init_status_to_remedies(*PlanFormatter.run_tf_init(reconfigure: true))
98
- status, r_results = process_remedies(remedies)
99
- results.merge!(r_results)
100
- return [false, results] unless status
144
+ remedy = :reconfigure
145
+ log wrap_log["Running terraform init ..."], depth: 2
146
+ result = remedy_retry_helper(from: :reconfigure, level: level + 1, attempt: retry_count) {
147
+ exit_code, meta = PlanFormatter.run_tf_init(reconfigure: true)
148
+ print_errors_and_warnings(meta)
149
+ remedies = PlanFormatter.init_status_to_remedies(exit_code, meta)
150
+ [remedies, exit_code, meta]
151
+ }
152
+ unless result
153
+ log wrap_log["Failed", color: :red], depth: 2
154
+ return [false, result]
155
+ end
156
+ end
157
+ if remedies.delete? :user_error
158
+ remedy = :user_error
159
+ log wrap_log["user error encountered!", color: :red]
160
+ log wrap_log["-" * 40, color: :red]
161
+ log wrap_log["!! User Error, Please fix the issue and try again", color: :red]
162
+ log wrap_log["-" * 40, color: :red]
163
+ return [false, results]
101
164
  end
102
165
  unless remedies.empty?
103
- log "unprocessed remedies: #{remedies.to_a}", depth: 1
166
+ remedy = nil
167
+ log wrap_log["Unprocessed remedies: #{remedies.to_a}", color: :red], depth: 1 if level == 1
104
168
  return [false, results]
105
169
  end
106
170
  [true, results]
@@ -122,7 +186,7 @@ module MuxTf
122
186
  when 2
123
187
  [:changes, meta]
124
188
  else
125
- log Paint["terraform plan exited with an unknown exit code: #{exit_code}", :yellow]
189
+ log pastel.yellow("terraform plan exited with an unknown exit code: #{exit_code}")
126
190
  [:unknown, meta]
127
191
  end
128
192
  end
@@ -132,9 +196,9 @@ module MuxTf
132
196
 
133
197
  case status
134
198
  when :error, :unknown
135
- log Paint["Dropping to command line so you can fix the issue!", :red]
199
+ log pastel.red("Dropping to command line so you can fix the issue!")
136
200
  when :changes
137
- log Paint["Dropping to command line so you can review the changes.", :yellow]
201
+ log pastel.yellow("Dropping to command line so you can review the changes.")
138
202
  end
139
203
  cmd_loop(status)
140
204
  end
@@ -149,9 +213,9 @@ module MuxTf
149
213
  prompt = "#{folder_name} => "
150
214
  case status
151
215
  when :error, :unknown
152
- prompt = "[#{Paint[status.to_s, :red]}] #{prompt}"
216
+ prompt = "[#{pastel.red(status.to_s)}] #{prompt}"
153
217
  when :changes
154
- prompt = "[#{Paint[status.to_s, :yellow]}] #{prompt}"
218
+ prompt = "[#{pastel.yellow(status.to_s)}] #{prompt}"
155
219
  end
156
220
 
157
221
  run_cmd_loop(prompt) do |cmd|
@@ -171,11 +235,31 @@ module MuxTf
171
235
  root_cmd.add_command(upgrade_cmd)
172
236
  root_cmd.add_command(reconfigure_cmd)
173
237
  root_cmd.add_command(interactive_cmd)
238
+ root_cmd.add_command(plan_details_cmd)
174
239
 
175
240
  root_cmd.add_command(exit_cmd)
241
+ root_cmd.add_command(define_cmd("help", summary: "Show help for commands") { |_opts, _args, cmd| puts cmd.supercommand.help })
176
242
  root_cmd
177
243
  end
178
244
 
245
+ def plan_summary_text
246
+ plan_filename = PlanFilenameGenerator.for_path
247
+ if File.exist?("#{plan_filename}.txt") && File.mtime("#{plan_filename}.txt").to_f >= File.mtime(plan_filename).to_f
248
+ File.read("#{plan_filename}.txt")
249
+ else
250
+ puts "Inspecting Changes ... #{plan_filename}"
251
+ data = PlanUtils.text_version_of_plan_show(plan_filename)
252
+ File.write("#{plan_filename}.txt", data)
253
+ data
254
+ end
255
+ end
256
+
257
+ def plan_details_cmd
258
+ define_cmd("details", summary: "Show Plan Details") do |_opts, _args, _cmd|
259
+ puts plan_summary_text
260
+ end
261
+ end
262
+
179
263
  def plan_cmd
180
264
  define_cmd("plan", summary: "Re-run plan") do |_opts, _args, _cmd|
181
265
  run_validate && run_plan
@@ -196,28 +280,30 @@ module MuxTf
196
280
 
197
281
  def shell_cmd
198
282
  define_cmd("shell", summary: "Open your default terminal in the current folder") do |_opts, _args, _cmd|
199
- log Paint["Launching shell ...", :yellow]
200
- log Paint["When it exits you will be back at this prompt.", :yellow]
283
+ log pastel.yellow("Launching shell ...")
284
+ log pastel.yellow("When it exits you will be back at this prompt.")
201
285
  system ENV.fetch("SHELL")
202
286
  end
203
287
  end
204
288
 
205
289
  def force_unlock_cmd
206
- define_cmd("force-unlock", summary: "Force unlock state after encountering a lock error!") do
290
+ define_cmd("force-unlock", summary: "Force unlock state after encountering a lock error!") do # rubocop:disable Metrics/BlockLength
207
291
  prompt = TTY::Prompt.new(interrupt: :noop)
208
292
 
209
- table = TTY::Table.new(header: %w[Field Value])
210
- table << ["Lock ID", @plan_meta["ID"]]
211
- table << ["Operation", @plan_meta["Operation"]]
212
- table << ["Who", @plan_meta["Who"]]
213
- table << ["Created", @plan_meta["Created"]]
293
+ lock_info = @last_lock_info
294
+
295
+ if lock_info
296
+ table = TTY::Table.new(header: %w[Field Value])
297
+ table << ["Lock ID", lock_info[:lock_id]]
298
+ table << ["Operation", lock_info[:operation]]
299
+ table << ["Who", lock_info[:who]]
300
+ table << ["Created", lock_info[:created]]
214
301
 
215
- puts table.render(:unicode, padding: [0, 1])
302
+ puts table.render(:unicode, padding: [0, 1])
216
303
 
217
- if @plan_meta && @plan_meta["error"] == "lock"
218
304
  done = catch(:abort) {
219
- if @plan_meta["Operation"] != "OperationTypePlan" && !prompt.yes?(
220
- "Are you sure you want to force unlock a lock for operation: #{@plan_meta['Operation']}",
305
+ if lock_info[:operation] != "OperationTypePlan" && !prompt.yes?(
306
+ "Are you sure you want to force unlock a lock for operation: #{lock_info[:operation]}",
221
307
  default: false
222
308
  )
223
309
  throw :abort
@@ -228,19 +314,19 @@ module MuxTf
228
314
  default: false
229
315
  )
230
316
 
231
- status = tf_force_unlock(id: @plan_meta["ID"])
317
+ status = tf_force_unlock(id: lock_info[:lock_id])
232
318
  if status.success?
233
319
  log "Done!"
234
320
  else
235
- log Paint["Failed with status: #{status}", :red]
321
+ log pastel.red("Failed with status: #{status}")
236
322
  end
237
323
 
238
324
  true
239
325
  }
240
326
 
241
- log Paint["Aborted", :yellow] unless done
327
+ log pastel.yellow("Aborted") unless done
242
328
  else
243
- log Paint["No lock error or no plan ran!", :red]
329
+ log pastel.red("No lock error or no plan ran!")
244
330
  end
245
331
  end
246
332
  end
@@ -257,8 +343,9 @@ module MuxTf
257
343
 
258
344
  def reconfigure_cmd
259
345
  define_cmd("reconfigure", summary: "Reconfigure modules/plguins") do |_opts, _args, _cmd|
260
- status, meta = PlanFormatter.run_tf_init(reconfigure: true)
261
- if status != 0
346
+ exit_code, meta = PlanFormatter.run_tf_init(reconfigure: true)
347
+ print_errors_and_warnings(meta)
348
+ if exit_code != 0
262
349
  log meta.inspect unless meta.empty?
263
350
  log "Reconfigure Failed!"
264
351
  end
@@ -271,7 +358,7 @@ module MuxTf
271
358
  begin
272
359
  abort_message = catch(:abort) { plan.run_interactive }
273
360
  if abort_message
274
- log Paint["Aborted: #{abort_message}", :red]
361
+ log pastel.red("Aborted: #{abort_message}")
275
362
  else
276
363
  run_plan
277
364
  end
@@ -282,30 +369,30 @@ module MuxTf
282
369
  end
283
370
  end
284
371
 
285
- def print_errors_and_warnings # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
372
+ def print_errors_and_warnings(meta) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
286
373
  message = []
287
- message << Paint["#{@plan_meta[:warnings].length} Warnings", :yellow] if @plan_meta[:warnings]
288
- message << Paint["#{@plan_meta[:errors].length} Errors", :red] if @plan_meta[:errors]
374
+ message << pastel.yellow("#{meta[:warnings].length} Warnings") if meta[:warnings]
375
+ message << pastel.red("#{meta[:errors].length} Errors") if meta[:errors]
289
376
  if message.length.positive?
290
377
  log ""
291
378
  log "Encountered: #{message.join(' and ')}"
292
379
  log ""
293
380
  end
294
381
 
295
- @plan_meta[:warnings]&.each do |warning|
382
+ meta[:warnings]&.each do |warning|
296
383
  log "-" * 20
297
- log Paint["Warning: #{warning[:message]}", :yellow]
384
+ log pastel.yellow("Warning: #{warning[:message]}")
298
385
  warning[:body]&.each do |line|
299
- log Paint[line, :yellow], depth: 1
386
+ log pastel.yellow(line), depth: 1
300
387
  end
301
388
  log ""
302
389
  end
303
390
 
304
- @plan_meta[:errors]&.each do |error|
391
+ meta[:errors]&.each do |error|
305
392
  log "-" * 20
306
- log Paint["Error: #{error[:message]}", :red]
393
+ log pastel.red("Error: #{error[:message]}")
307
394
  error[:body]&.each do |line|
308
- log Paint[line, :red], depth: 1
395
+ log pastel.red(line), depth: 1
309
396
  end
310
397
  log ""
311
398
  end
@@ -315,47 +402,76 @@ module MuxTf
315
402
  log ""
316
403
  end
317
404
 
318
- def detect_remedies_from_plan
405
+ def detect_remedies_from_plan(meta)
319
406
  remedies = Set.new
320
- @plan_meta[:errors]&.each do |error|
407
+ meta[:errors]&.each do |error|
321
408
  remedies << :plan if error[:message].include?("timeout while waiting for plugin to start")
322
409
  end
410
+ remedies << :unlock if lock_error?(meta)
323
411
  remedies
324
412
  end
325
413
 
326
- def run_plan(targets: [], retry_count: 0)
327
- plan_status, @plan_meta = create_plan(plan_filename, targets: targets)
414
+ def lock_error?(meta)
415
+ meta && meta["error"] == "lock"
416
+ end
417
+
418
+ def extract_lock_info(meta)
419
+ {
420
+ lock_id: meta["ID"],
421
+ operation: meta["Operation"],
422
+ who: meta["Who"],
423
+ created: meta["Created"]
424
+ }
425
+ end
426
+
427
+ def run_plan(targets: [], level: 1, retry_count: 0)
428
+ plan_status, = remedy_retry_helper(from: :plan, level: level, attempt: retry_count) {
429
+ @last_lock_info = nil
430
+
431
+ plan_status, meta = create_plan(plan_filename, targets: targets)
432
+
433
+ print_errors_and_warnings(meta)
434
+
435
+ remedies = detect_remedies_from_plan(meta)
436
+
437
+ if remedies.include?(:unlock)
438
+ @last_lock_info = extract_lock_info(meta)
439
+ throw :abort, [plan_status, meta]
440
+ end
441
+
442
+ [remedies, plan_status, meta]
443
+ }
328
444
 
329
445
  case plan_status
330
446
  when :ok
331
447
  log "no changes", depth: 1
332
448
  when :error
333
- # log "something went wrong", depth: 1
334
- print_errors_and_warnings
335
- remedies = detect_remedies_from_plan
336
- status, results = process_remedies(remedies, retry_count: retry_count)
337
- plan_status = results[:plan_status] if status
449
+ log "something went wrong", depth: 1
338
450
  when :changes
339
- log "Printing Plan Summary ...", depth: 1
340
- pretty_plan_summary(plan_filename)
451
+ unless ENV["JSON_PLAN"]
452
+ log "Printing Plan Summary ...", depth: 1
453
+ pretty_plan_summary(plan_filename)
454
+ end
455
+ puts plan_summary_text if ENV["JSON_PLAN"]
341
456
  when :unknown
342
457
  # nothing
343
458
  end
344
459
 
345
- print_errors_and_warnings
346
-
347
460
  plan_status
348
461
  end
349
462
 
463
+ public :run_plan
464
+
350
465
  def run_upgrade
351
466
  exit_code, meta = PlanFormatter.run_tf_init(upgrade: true)
467
+ print_errors_and_warnings(meta)
352
468
  case exit_code
353
469
  when 0
354
470
  [:ok, meta]
355
471
  when 1
356
472
  [:error, meta]
357
473
  else
358
- log Paint["terraform init upgrade exited with an unknown exit code: #{exit_code}", :yellow]
474
+ log pastel.yellow("terraform init upgrade exited with an unknown exit code: #{exit_code}")
359
475
  [:unknown, meta]
360
476
  end
361
477
  end
@@ -6,6 +6,7 @@ module MuxTf
6
6
  extend PiotrbCliUtils::Util
7
7
  extend PiotrbCliUtils::ShellHelpers
8
8
  extend TerraformHelpers
9
+ import Coloring
9
10
 
10
11
  class << self
11
12
  def run(args)
@@ -33,7 +34,7 @@ module MuxTf
33
34
 
34
35
  if options[:interactive]
35
36
  abort_message = catch(:abort) { plan.run_interactive }
36
- log Paint["Aborted: #{abort_message}", :red] if abort_message
37
+ log pastel.red("Aborted: #{abort_message}") if abort_message
37
38
  else
38
39
  if options[:hierarchy]
39
40
  plan.nested_summary.each do |line|
data/lib/mux_tf/cli.rb CHANGED
@@ -7,13 +7,13 @@ module MuxTf
7
7
  def self.run(mode, args)
8
8
  case mode
9
9
  when :mux
10
- require_relative "./cli/mux"
10
+ require_relative "cli/mux"
11
11
  MuxTf::Cli::Mux.run(args)
12
12
  when :current
13
- require_relative "./cli/current"
13
+ require_relative "cli/current"
14
14
  MuxTf::Cli::Current.run(args)
15
15
  when :plan_summary
16
- require_relative "./cli/plan_summary"
16
+ require_relative "cli/plan_summary"
17
17
  MuxTf::Cli::PlanSummary.run(args)
18
18
  else
19
19
  fail_with "unhandled mode: #{mode.inspect}"
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MuxTf
4
+ module Coloring
5
+ def pastel
6
+ self.class.pastel
7
+ end
8
+
9
+ def self.included(other)
10
+ other.extend(ClassMethods)
11
+ end
12
+
13
+ module ClassMethods
14
+ def pastel
15
+ instance = Pastel.new
16
+ instance.alias_color(:orange, :yellow)
17
+ instance.alias_color(:gray, :bright_black)
18
+ instance.alias_color(:grey, :bright_black)
19
+ instance
20
+ end
21
+ end
22
+ end
23
+ end