mux_tf 0.12.0 → 0.13.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.rb +81 -21
- data/lib/mux_tf/cli.rb +2 -0
- data/lib/mux_tf/plan_formatter.rb +54 -11
- data/lib/mux_tf/plan_summary_handler.rb +1 -31
- data/lib/mux_tf/terraform_helpers.rb +1 -0
- data/lib/mux_tf/tmux.rb +2 -0
- data/lib/mux_tf/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab68c9969748e0246a48cb2bf53876b0b2f47993b021017e1e9bb31782a7e4b4
|
4
|
+
data.tar.gz: 63fb2194ba923f3c30c9480f50946c550e85ea9e7e1988fdcc1764cbe7666f6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8d1442c6cff1c7c0828347176b1cc0a49fa28fb5a27e0212e730e3bf176fc4a072ba247e9cbf6d248c488fb1c62ffc6a71181dbde47e0b35a759b798ded6886
|
7
|
+
data.tar.gz: 3d85fc7be2b58bd815060145c33bccf7dc5814a5ee3a052f5adc6a4c7512792e290f0b1bb26faa07d4f950aab81036bcf9c09b91c2a3a20878fcd70601bd2044
|
data/lib/mux_tf/cli/current.rb
CHANGED
@@ -4,7 +4,7 @@ require "bundler"
|
|
4
4
|
|
5
5
|
module MuxTf
|
6
6
|
module Cli
|
7
|
-
module Current
|
7
|
+
module Current # rubocop:disable Metrics/ModuleLength
|
8
8
|
extend TerraformHelpers
|
9
9
|
extend PiotrbCliUtils::Util
|
10
10
|
extend PiotrbCliUtils::CriCommandSupport
|
@@ -32,19 +32,16 @@ module MuxTf
|
|
32
32
|
return launch_cmd_loop(:error) unless upgrade_status == :ok
|
33
33
|
end
|
34
34
|
|
35
|
-
plan_status
|
35
|
+
plan_status = run_plan
|
36
36
|
|
37
37
|
case plan_status
|
38
38
|
when :ok
|
39
|
-
log "
|
39
|
+
log "exiting", depth: 1
|
40
40
|
when :error
|
41
|
-
log "something went wrong", depth: 1
|
42
41
|
launch_cmd_loop(plan_status)
|
43
|
-
when :changes
|
44
|
-
log "Printing Plan Summary ...", depth: 1
|
45
|
-
pretty_plan_summary(plan_filename)
|
42
|
+
when :changes # rubocop:disable Lint/DuplicateBranch
|
46
43
|
launch_cmd_loop(plan_status)
|
47
|
-
when :unknown
|
44
|
+
when :unknown # rubocop:disable Lint/DuplicateBranch
|
48
45
|
launch_cmd_loop(plan_status)
|
49
46
|
end
|
50
47
|
end
|
@@ -68,28 +65,45 @@ module MuxTf
|
|
68
65
|
|
69
66
|
def run_validate
|
70
67
|
remedies = PlanFormatter.process_validation(validate)
|
71
|
-
process_remedies(remedies)
|
68
|
+
status, _results = process_remedies(remedies)
|
69
|
+
status
|
72
70
|
end
|
73
71
|
|
74
|
-
def process_remedies(remedies)
|
72
|
+
def process_remedies(remedies, retry_count: 0) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
|
73
|
+
results = {}
|
74
|
+
if retry_count > 5
|
75
|
+
log "giving up because retry_count: #{retry_count}", depth: 1
|
76
|
+
log "unprocessed remedies: #{remedies.to_a}", depth: 1
|
77
|
+
return [false, results]
|
78
|
+
end
|
75
79
|
if remedies.delete? :init
|
76
|
-
log "Running terraform init ...", depth: 2
|
80
|
+
log "[remedy] Running terraform init ...", depth: 2
|
77
81
|
remedies = PlanFormatter.init_status_to_remedies(*PlanFormatter.run_tf_init)
|
78
|
-
|
82
|
+
status, r_results = process_remedies(remedies)
|
83
|
+
results.merge!(r_results)
|
84
|
+
if status
|
79
85
|
remedies = PlanFormatter.process_validation(validate)
|
80
|
-
return false unless process_remedies(remedies)
|
86
|
+
return [false, results] unless process_remedies(remedies)
|
81
87
|
end
|
82
88
|
end
|
89
|
+
if remedies.delete?(:plan)
|
90
|
+
log "[remedy] Running terraform plan ...", depth: 2
|
91
|
+
plan_status = run_plan(retry_count: retry_count)
|
92
|
+
results[:plan_status] = plan_status
|
93
|
+
return [false, results] unless [:ok, :changes].include?(plan_status)
|
94
|
+
end
|
83
95
|
if remedies.delete? :reconfigure
|
84
|
-
log "Running terraform init ...", depth: 2
|
96
|
+
log "[remedy] Running terraform init ...", depth: 2
|
85
97
|
remedies = PlanFormatter.init_status_to_remedies(*PlanFormatter.run_tf_init(reconfigure: true))
|
86
|
-
|
98
|
+
status, r_results = process_remedies(remedies)
|
99
|
+
results.merge!(r_results)
|
100
|
+
return [false, results] unless status
|
87
101
|
end
|
88
102
|
unless remedies.empty?
|
89
103
|
log "unprocessed remedies: #{remedies.to_a}", depth: 1
|
90
|
-
return false
|
104
|
+
return [false, results]
|
91
105
|
end
|
92
|
-
true
|
106
|
+
[true, results]
|
93
107
|
end
|
94
108
|
|
95
109
|
def validate
|
@@ -268,20 +282,68 @@ module MuxTf
|
|
268
282
|
end
|
269
283
|
end
|
270
284
|
|
271
|
-
def
|
285
|
+
def print_errors_and_warnings # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize
|
286
|
+
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]
|
289
|
+
if message.length.positive?
|
290
|
+
log ""
|
291
|
+
log "Encountered: #{message.join(' and ')}"
|
292
|
+
log ""
|
293
|
+
end
|
294
|
+
|
295
|
+
@plan_meta[:warnings]&.each do |warning|
|
296
|
+
log "-" * 20
|
297
|
+
log Paint["Warning: #{warning[:message]}", :yellow]
|
298
|
+
warning[:body]&.each do |line|
|
299
|
+
log Paint[line, :yellow], depth: 1
|
300
|
+
end
|
301
|
+
log ""
|
302
|
+
end
|
303
|
+
|
304
|
+
@plan_meta[:errors]&.each do |error|
|
305
|
+
log "-" * 20
|
306
|
+
log Paint["Error: #{error[:message]}", :red]
|
307
|
+
error[:body]&.each do |line|
|
308
|
+
log Paint[line, :red], depth: 1
|
309
|
+
end
|
310
|
+
log ""
|
311
|
+
end
|
312
|
+
|
313
|
+
return unless message.length.positive?
|
314
|
+
|
315
|
+
log ""
|
316
|
+
end
|
317
|
+
|
318
|
+
def detect_remedies_from_plan
|
319
|
+
remedies = Set.new
|
320
|
+
@plan_meta[:errors]&.each do |error|
|
321
|
+
remedies << :plan if error[:message].include?("timeout while waiting for plugin to start")
|
322
|
+
end
|
323
|
+
remedies
|
324
|
+
end
|
325
|
+
|
326
|
+
def run_plan(targets: [], retry_count: 0)
|
272
327
|
plan_status, @plan_meta = create_plan(plan_filename, targets: targets)
|
273
328
|
|
274
329
|
case plan_status
|
275
330
|
when :ok
|
276
331
|
log "no changes", depth: 1
|
277
332
|
when :error
|
278
|
-
log "something went wrong", depth: 1
|
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
|
279
338
|
when :changes
|
280
339
|
log "Printing Plan Summary ...", depth: 1
|
281
340
|
pretty_plan_summary(plan_filename)
|
282
341
|
when :unknown
|
283
342
|
# nothing
|
284
343
|
end
|
344
|
+
|
345
|
+
print_errors_and_warnings
|
346
|
+
|
285
347
|
plan_status
|
286
348
|
end
|
287
349
|
|
@@ -292,8 +354,6 @@ module MuxTf
|
|
292
354
|
[:ok, meta]
|
293
355
|
when 1
|
294
356
|
[:error, meta]
|
295
|
-
# when 2
|
296
|
-
# [:changes, meta]
|
297
357
|
else
|
298
358
|
log Paint["terraform init upgrade exited with an unknown exit code: #{exit_code}", :yellow]
|
299
359
|
[:unknown, meta]
|
data/lib/mux_tf/cli.rb
CHANGED
@@ -13,7 +13,7 @@ module MuxTf
|
|
13
13
|
|
14
14
|
parser = StatefulParser.new(normalizer: pastel.method(:strip))
|
15
15
|
parser.state(:info, /^Acquiring state lock/)
|
16
|
-
parser.state(:error, /(
|
16
|
+
parser.state(:error, /(Error locking state|Error:)/, [:none, :blank, :info, :reading])
|
17
17
|
parser.state(:reading, /: (Reading...|Read complete after)/, [:none, :info, :reading])
|
18
18
|
parser.state(:none, /^$/, [:reading])
|
19
19
|
parser.state(:refreshing, /^.+: Refreshing state... \[id=/, [:none, :info, :reading])
|
@@ -31,10 +31,13 @@ module MuxTf
|
|
31
31
|
parser.state(:plan_legend, /^Terraform used the selected providers to generate the following execution$/)
|
32
32
|
parser.state(:none, /^$/, [:plan_legend])
|
33
33
|
|
34
|
-
parser.state(:error_lock_info, /Lock Info/, [:
|
35
|
-
parser.state(:error, /^$/, [:error_lock_info])
|
34
|
+
parser.state(:error_lock_info, /Lock Info/, [:plan_error_error])
|
36
35
|
|
37
|
-
parser.state(:plan_error,
|
36
|
+
parser.state(:plan_error, /Planning failed. Terraform encountered an error while generating this plan./, [:refreshing, :refresh_done])
|
37
|
+
parser.state(:plan_error_block, /^╷/, [:plan_error, :none, :blank, :info, :reading])
|
38
|
+
parser.state(:plan_error_warning, /^│ Warning: /, [:plan_error_block])
|
39
|
+
parser.state(:plan_error_error, /^│ Error: /, [:plan_error_block])
|
40
|
+
parser.state(:plan_error, /^╵/, [:plan_error_warning, :plan_error_error, :plan_error_block, :error_lock_info])
|
38
41
|
|
39
42
|
last_state = nil
|
40
43
|
|
@@ -68,16 +71,54 @@ module MuxTf
|
|
68
71
|
else
|
69
72
|
p [state, line]
|
70
73
|
end
|
71
|
-
when :
|
72
|
-
meta[
|
73
|
-
|
74
|
+
when :plan_error_block
|
75
|
+
meta[:current_error] = {
|
76
|
+
type: :unknown,
|
77
|
+
body: []
|
78
|
+
}
|
79
|
+
when :plan_error_warning, :plan_error_error
|
80
|
+
clean_line = pastel.strip(line).gsub(/^│ /, "")
|
81
|
+
if clean_line =~ /^(Warning|Error): (.+)$/
|
82
|
+
meta[:current_error][:type] = $LAST_MATCH_INFO[1].downcase.to_sym
|
83
|
+
meta[:current_error][:message] = $LAST_MATCH_INFO[2]
|
84
|
+
elsif clean_line == ""
|
85
|
+
# skip double empty lines
|
86
|
+
meta[:current_error][:body] << clean_line if meta[:current_error][:body].last != ""
|
87
|
+
else
|
88
|
+
meta[:current_error][:body] ||= []
|
89
|
+
meta[:current_error][:body] << clean_line
|
90
|
+
end
|
74
91
|
when :plan_error
|
75
|
-
|
76
|
-
|
77
|
-
|
92
|
+
case pastel.strip(line)
|
93
|
+
when "╵" # closing of an error block
|
94
|
+
if meta[:current_error][:type] == :error
|
95
|
+
meta[:errors] ||= []
|
96
|
+
meta[:errors] << meta[:current_error]
|
97
|
+
end
|
98
|
+
if meta[:current_error][:type] == :warning
|
99
|
+
meta[:warnings] ||= []
|
100
|
+
meta[:warnings] << meta[:current_error]
|
101
|
+
end
|
102
|
+
meta.delete(:current_error)
|
103
|
+
when ""
|
104
|
+
# skip empty line
|
105
|
+
when /Releasing state lock. This may take a few moments"/
|
106
|
+
log line, depth: 2
|
107
|
+
when /Planning failed./ # rubocop:disable Lint/DuplicateBranch
|
108
|
+
log line, depth: 2
|
109
|
+
else
|
110
|
+
p [state, line]
|
111
|
+
end
|
78
112
|
when :error_lock_info
|
113
|
+
meta["error"] = "lock"
|
79
114
|
meta[$LAST_MATCH_INFO[1]] = $LAST_MATCH_INFO[2] if line =~ /([A-Z]+\S+)+:\s+(.+)$/
|
80
|
-
|
115
|
+
clean_line = pastel.strip(line).gsub(/^│ /, "")
|
116
|
+
if clean_line == ""
|
117
|
+
meta[:current_error][:body] << clean_line if meta[:current_error][:body].last != ""
|
118
|
+
else
|
119
|
+
meta[:current_error][:body] << clean_line
|
120
|
+
end
|
121
|
+
# log Paint[line, :red], depth: 2
|
81
122
|
when :refreshing
|
82
123
|
if first_in_state
|
83
124
|
log "Refreshing state ", depth: 2, newline: false
|
@@ -270,6 +311,8 @@ module MuxTf
|
|
270
311
|
remedies << :init
|
271
312
|
elsif /there is no package for .+ cached in/.match?(dinfo["summary"]) # rubocop:disable Lint/DuplicateBranch
|
272
313
|
remedies << :init
|
314
|
+
elsif dinfo["detail"]&.include?("timeout while waiting for plugin to start") # rubocop:disable Lint/DuplicateBranch
|
315
|
+
remedies << :init
|
273
316
|
else
|
274
317
|
log dinfo["detail"], depth: 4 if dinfo["detail"]
|
275
318
|
log format_validation_range(dinfo["range"], color), depth: 4 if dinfo["range"]
|
@@ -239,7 +239,7 @@ module MuxTf
|
|
239
239
|
throw :abort, "nothing selected"
|
240
240
|
else
|
241
241
|
log "Re-running apply with the selected resources ..."
|
242
|
-
run_plan(targets: result)
|
242
|
+
MuxTf::Cli::Current.run_plan(targets: result)
|
243
243
|
end
|
244
244
|
end
|
245
245
|
|
@@ -263,36 +263,6 @@ module MuxTf
|
|
263
263
|
end
|
264
264
|
end
|
265
265
|
|
266
|
-
def run_plan(targets: [])
|
267
|
-
plan_filename = MuxTf::Cli::Current.plan_filename
|
268
|
-
plan_status, @plan_meta = create_plan(plan_filename, targets: targets)
|
269
|
-
|
270
|
-
case plan_status
|
271
|
-
when :ok
|
272
|
-
log "no changes", depth: 1
|
273
|
-
when :error
|
274
|
-
log "something went wrong", depth: 1
|
275
|
-
when :changes
|
276
|
-
log "Printing Plan Summary ...", depth: 1
|
277
|
-
pretty_plan_summary(plan_filename)
|
278
|
-
when :unknown
|
279
|
-
# nothing
|
280
|
-
end
|
281
|
-
plan_status
|
282
|
-
end
|
283
|
-
|
284
|
-
def pretty_plan_summary(filename)
|
285
|
-
plan = PlanSummaryHandler.from_file(filename)
|
286
|
-
plan.flat_summary.each do |line|
|
287
|
-
log line, depth: 2
|
288
|
-
end
|
289
|
-
plan.output_summary.each do |line|
|
290
|
-
log line, depth: 2
|
291
|
-
end
|
292
|
-
log "", depth: 2
|
293
|
-
log plan.summary, depth: 2
|
294
|
-
end
|
295
|
-
|
296
266
|
def prune_unchanged_deps(_parts)
|
297
267
|
valid_addresses = resource_parts.map { |part| part[:address] }
|
298
268
|
|
data/lib/mux_tf/tmux.rb
CHANGED
data/lib/mux_tf/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mux_tf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Banasik
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-07-
|
11
|
+
date: 2023-07-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|