mux_tf 0.13.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|