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 +4 -4
- data/exe/tf_current +2 -0
- data/exe/tf_mux +2 -0
- data/exe/tf_plan_summary +2 -0
- data/lib/deps.rb +10 -1
- data/lib/mux_tf/cli/current.rb +192 -76
- data/lib/mux_tf/cli/plan_summary.rb +2 -1
- data/lib/mux_tf/cli.rb +3 -3
- data/lib/mux_tf/coloring.rb +23 -0
- data/lib/mux_tf/plan_formatter.rb +503 -80
- data/lib/mux_tf/plan_summary_handler.rb +99 -94
- data/lib/mux_tf/plan_utils.rb +360 -0
- data/lib/mux_tf/terraform_helpers.rb +51 -9
- data/lib/mux_tf/version.rb +1 -1
- data/lib/mux_tf.rb +18 -10
- data/mux_tf.gemspec +3 -1
- metadata +33 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9a03af7a131fd34e58d5fb27d3c578154f49246634a684980e6ebc16aa28d08
|
4
|
+
data.tar.gz: d093d1604dabbeb1aed8ef5b1ebc3e33a0b5e3575602f7b3802796b2b51f7a7a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7809b83e63a8aa17671ef6fbaac79a09cd7aa8216fdd1ccd390f2e32ee0b4ec0a85e4f6653d4c4bbbafcb99d47076413a9135f970f4d4c0f7f8608b2e8858f5f
|
7
|
+
data.tar.gz: c9dd73ed72236b568c7bbdc34ede9701e1d1db94403ccd2e84ee611cd58500e73810f50c9c0bdd6817c2ef7f8bd5d504fd945d86d340db95d9246e797376efb4
|
data/exe/tf_current
CHANGED
data/exe/tf_mux
CHANGED
data/exe/tf_plan_summary
CHANGED
data/lib/deps.rb
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
require "bundler/inline"
|
4
4
|
|
5
|
-
|
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
|
data/lib/mux_tf/cli/current.rb
CHANGED
@@ -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 #{
|
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
|
59
|
-
log "New version of #{
|
60
|
-
log "You are currently on version: #{
|
61
|
-
log "Latest version found is: #{
|
62
|
-
log "Run `#{
|
63
|
-
log
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
81
|
-
|
82
|
-
|
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
|
-
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
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
|
-
|
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
|
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
|
199
|
+
log pastel.red("Dropping to command line so you can fix the issue!")
|
136
200
|
when :changes
|
137
|
-
log
|
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 = "[#{
|
216
|
+
prompt = "[#{pastel.red(status.to_s)}] #{prompt}"
|
153
217
|
when :changes
|
154
|
-
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
|
200
|
-
log
|
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
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
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
|
-
|
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
|
220
|
-
"Are you sure you want to force unlock a lock for 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:
|
317
|
+
status = tf_force_unlock(id: lock_info[:lock_id])
|
232
318
|
if status.success?
|
233
319
|
log "Done!"
|
234
320
|
else
|
235
|
-
log
|
321
|
+
log pastel.red("Failed with status: #{status}")
|
236
322
|
end
|
237
323
|
|
238
324
|
true
|
239
325
|
}
|
240
326
|
|
241
|
-
log
|
327
|
+
log pastel.yellow("Aborted") unless done
|
242
328
|
else
|
243
|
-
log
|
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
|
-
|
261
|
-
|
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
|
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 <<
|
288
|
-
message <<
|
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
|
-
|
382
|
+
meta[:warnings]&.each do |warning|
|
296
383
|
log "-" * 20
|
297
|
-
log
|
384
|
+
log pastel.yellow("Warning: #{warning[:message]}")
|
298
385
|
warning[:body]&.each do |line|
|
299
|
-
log
|
386
|
+
log pastel.yellow(line), depth: 1
|
300
387
|
end
|
301
388
|
log ""
|
302
389
|
end
|
303
390
|
|
304
|
-
|
391
|
+
meta[:errors]&.each do |error|
|
305
392
|
log "-" * 20
|
306
|
-
log
|
393
|
+
log pastel.red("Error: #{error[:message]}")
|
307
394
|
error[:body]&.each do |line|
|
308
|
-
log
|
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
|
-
|
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
|
327
|
-
|
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
|
-
|
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
|
-
|
340
|
-
|
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
|
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
|
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 "
|
10
|
+
require_relative "cli/mux"
|
11
11
|
MuxTf::Cli::Mux.run(args)
|
12
12
|
when :current
|
13
|
-
require_relative "
|
13
|
+
require_relative "cli/current"
|
14
14
|
MuxTf::Cli::Current.run(args)
|
15
15
|
when :plan_summary
|
16
|
-
require_relative "
|
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
|