mux_tf 0.2.0 → 0.3.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: '081eb21a5fe4e2b6af78aec28e0136cf68ef0301314e4b42c220feee51b12eb0'
4
- data.tar.gz: b20cb57dc3c2cff965ba65dea8384ff91181c1716919cbf0330f91906c601fd1
3
+ metadata.gz: 4d3511e5badfa499bd43efb92048717c8d597633229c4e135a51c0d57ea56d84
4
+ data.tar.gz: 3a2feb35ce3d7a9c4f2781b2ace26eb08ed41da0ba047b33a8b4882363878914
5
5
  SHA512:
6
- metadata.gz: 87ff57efa5e61617cbe4a65c57b09d2c3ee9741ff4ee93955bf015a3e76dc9dcb6cbb8f6d0ef2f419879e727bd3584827e98d88c68bd6af58af3808c8d53bf07
7
- data.tar.gz: c8807d29c6839eac9496f4f8b4906e73b6b8f7504d1c888a9a003ff6b60eae3e77e65cf1f3932c62be8034551da3e8544f2ba30de90515e21578dbc87c529054
6
+ metadata.gz: 7559eca291ace43436b5f38ea72823187573c85e7b51029861bf98a4e3b88b9144f0997a915a9ab1e9cb581ddc04807b9a9da569dd233a47207007fae5939b57
7
+ data.tar.gz: 15d909df002d4ff344e2966eb2a54d3943407f6d9e910daebc84781de233f215bfa282067f7cf3eaf702811553785e785be9c5d8a437908e8b0f30d1efa911b8
@@ -1,30 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'English'
3
+ require "English"
4
4
 
5
- require 'shellwords'
6
- require 'optparse'
7
- require 'json'
8
- require 'open3'
5
+ require "shellwords"
6
+ require "optparse"
7
+ require "json"
8
+ require "open3"
9
9
 
10
- require 'piotrb_cli_utils'
11
- require 'stateful_parser'
10
+ require "piotrb_cli_utils"
11
+ require "stateful_parser"
12
12
 
13
- require 'active_support/core_ext'
13
+ require "active_support/core_ext"
14
14
 
15
- require 'paint'
16
- require 'pastel'
17
- require 'tty-prompt'
18
- require 'tty-table'
19
- require 'dotenv'
15
+ require "paint"
16
+ require "pastel"
17
+ require "tty-prompt"
18
+ require "tty-table"
19
+ require "dotenv"
20
20
 
21
- require_relative './mux_tf/version'
22
- require_relative './mux_tf/cli'
23
- require_relative './mux_tf/tmux'
24
- require_relative './mux_tf/terraform_helpers'
25
- require_relative './mux_tf/plan_formatter'
26
- require_relative './mux_tf/version_check'
27
- require_relative './mux_tf/yaml_cache'
21
+ require_relative "./mux_tf/version"
22
+ require_relative "./mux_tf/cli"
23
+ require_relative "./mux_tf/tmux"
24
+ require_relative "./mux_tf/terraform_helpers"
25
+ require_relative "./mux_tf/plan_formatter"
26
+ require_relative "./mux_tf/version_check"
27
+ require_relative "./mux_tf/yaml_cache"
28
+ require_relative "./mux_tf/plan_summary_handler"
28
29
 
29
30
  module MuxTf
30
31
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bundler"
4
+
3
5
  module MuxTf
4
6
  module Cli
5
7
  module Current
@@ -8,13 +10,13 @@ module MuxTf
8
10
  extend PiotrbCliUtils::CriCommandSupport
9
11
  extend PiotrbCliUtils::CmdLoop
10
12
 
11
- PLAN_FILENAME = 'foo.tfplan'
13
+ PLAN_FILENAME = "foo.tfplan"
12
14
 
13
15
  class << self
14
16
  def run(args)
15
17
  version_check
16
18
 
17
- if args[0] == 'cli'
19
+ if args[0] == "cli"
18
20
  cmd_loop
19
21
  return
20
22
  end
@@ -22,12 +24,12 @@ module MuxTf
22
24
  folder_name = File.basename(Dir.getwd)
23
25
  log "Processing #{Paint[folder_name, :cyan]} ..."
24
26
 
25
- ENV['TF_IN_AUTOMATION'] = '1'
26
- ENV['TF_INPUT'] = '0'
27
+ ENV["TF_IN_AUTOMATION"] = "1"
28
+ ENV["TF_INPUT"] = "0"
27
29
 
28
30
  return launch_cmd_loop(:error) unless run_validate
29
31
 
30
- if ENV['TF_UPGRADE']
32
+ if ENV["TF_UPGRADE"]
31
33
  upgrade_status, upgrade_meta = run_upgrade
32
34
  return launch_cmd_loop(:error) unless upgrade_status == :ok
33
35
  end
@@ -36,37 +38,37 @@ module MuxTf
36
38
 
37
39
  case plan_status
38
40
  when :ok
39
- log 'no changes, exiting', depth: 1
41
+ log "no changes, exiting", depth: 1
40
42
  when :error
41
- log 'something went wrong', depth: 1
43
+ log "something went wrong", depth: 1
42
44
  launch_cmd_loop(plan_status)
43
45
  when :changes
44
- log 'Printing Plan Summary ...', depth: 1
46
+ log "Printing Plan Summary ...", depth: 1
45
47
  pretty_plan_summary(PLAN_FILENAME)
46
48
  launch_cmd_loop(plan_status)
47
49
  when :unknown
48
50
  launch_cmd_loop(plan_status)
49
51
  end
50
52
  rescue Exception => e # rubocop:disable Lint/RescueException
51
- puts Paint['Unhandled Exception!', :red]
52
- puts '=' * 20
53
+ puts Paint["Unhandled Exception!", :red]
54
+ puts "=" * 20
53
55
  puts e.full_message
54
56
  puts
55
- puts '< press enter to continue >'
57
+ puts "< press enter to continue >"
56
58
  gets
57
59
  exit 1
58
60
  end
59
61
 
60
- private
62
+ private
61
63
 
62
64
  def version_check
63
65
  if VersionCheck.has_updates?
64
- log Paint["="*80, :yellow]
66
+ log Paint["=" * 80, :yellow]
65
67
  log "New version of #{Paint["mux_tf", :cyan]} is available!"
66
68
  log "You are currently on version: #{Paint[VersionCheck.current_gem_version, :yellow]}"
67
69
  log "Latest version found is: #{Paint[VersionCheck.latest_gem_version, :green]}"
68
- log "Run `#{Paint["gem update muf_tf", :green]}` to update!"
69
- log Paint["="*80, :yellow]
70
+ log "Run `#{Paint["gem install mux_tf", :green]}` to update!"
71
+ log Paint["=" * 80, :yellow]
70
72
  end
71
73
  end
72
74
 
@@ -77,7 +79,7 @@ module MuxTf
77
79
 
78
80
  def process_remedies(remedies)
79
81
  if remedies.delete? :init
80
- log 'Running terraform init ...', depth: 2
82
+ log "Running terraform init ...", depth: 2
81
83
  tf_init
82
84
  remedies = PlanFormatter.process_validation(validate)
83
85
  process_remedies(remedies)
@@ -90,12 +92,12 @@ module MuxTf
90
92
  end
91
93
 
92
94
  def validate
93
- log 'Validating module ...', depth: 1
95
+ log "Validating module ...", depth: 1
94
96
  tf_validate.parsed_output
95
97
  end
96
98
 
97
99
  def create_plan(filename)
98
- log 'Preparing Plan ...', depth: 1
100
+ log "Preparing Plan ...", depth: 1
99
101
  exit_code, meta = PlanFormatter.pretty_plan(filename)
100
102
  case exit_code
101
103
  when 0
@@ -111,13 +113,13 @@ module MuxTf
111
113
  end
112
114
 
113
115
  def launch_cmd_loop(status)
114
- return if ENV['NO_CMD']
116
+ return if ENV["NO_CMD"]
115
117
 
116
118
  case status
117
119
  when :error, :unknown
118
- log Paint['Dropping to command line so you can fix the issue!', :red]
120
+ log Paint["Dropping to command line so you can fix the issue!", :red]
119
121
  when :changes
120
- log Paint['Dropping to command line so you can review the changes.', :yellow]
122
+ log Paint["Dropping to command line so you can review the changes.", :yellow]
121
123
  end
122
124
  cmd_loop(status)
123
125
  end
@@ -138,7 +140,7 @@ module MuxTf
138
140
  end
139
141
 
140
142
  run_cmd_loop(prompt) do |cmd|
141
- throw(:stop, :no_input) if cmd == ''
143
+ throw(:stop, :no_input) if cmd == ""
142
144
  args = Shellwords.split(cmd)
143
145
  root_cmd.run(args, {}, hard_exit: false)
144
146
  end
@@ -159,90 +161,98 @@ module MuxTf
159
161
  end
160
162
 
161
163
  def plan_cmd
162
- define_cmd('plan', summary: 'Re-run plan') do |_opts, _args, _cmd|
164
+ define_cmd("plan", summary: "Re-run plan") do |_opts, _args, _cmd|
163
165
  run_validate && run_plan
164
166
  end
165
167
  end
166
168
 
167
169
  def apply_cmd
168
- define_cmd('apply', summary: 'Apply the current plan') do |_opts, _args, _cmd|
170
+ define_cmd("apply", summary: "Apply the current plan") do |_opts, _args, _cmd|
169
171
  status = tf_apply(filename: PLAN_FILENAME)
170
172
  if status.success?
171
173
  throw :stop, :done
172
174
  else
173
- log 'Apply Failed!'
175
+ log "Apply Failed!"
174
176
  end
175
177
  end
176
178
  end
177
179
 
178
180
  def shell_cmd
179
- define_cmd('shell', summary: 'Open your default terminal in the current folder') do |_opts, _args, _cmd|
180
- log Paint['Launching shell ...', :yellow]
181
- log Paint['When it exits you will be back at this prompt.', :yellow]
182
- system ENV['SHELL']
181
+ define_cmd("shell", summary: "Open your default terminal in the current folder") do |_opts, _args, _cmd|
182
+ log Paint["Launching shell ...", :yellow]
183
+ log Paint["When it exits you will be back at this prompt.", :yellow]
184
+ system ENV["SHELL"]
183
185
  end
184
186
  end
185
187
 
186
188
  def force_unlock_cmd
187
- define_cmd('force-unlock', summary: 'Force unlock state after encountering a lock error!') do
189
+ define_cmd("force-unlock", summary: "Force unlock state after encountering a lock error!") do
188
190
  prompt = TTY::Prompt.new(interrupt: :noop)
189
191
 
190
192
  table = TTY::Table.new(header: %w[Field Value])
191
- table << ['Lock ID', @plan_meta['ID']]
192
- table << ['Operation', @plan_meta['Operation']]
193
- table << ['Who', @plan_meta['Who']]
194
- table << ['Created', @plan_meta['Created']]
193
+ table << ["Lock ID", @plan_meta["ID"]]
194
+ table << ["Operation", @plan_meta["Operation"]]
195
+ table << ["Who", @plan_meta["Who"]]
196
+ table << ["Created", @plan_meta["Created"]]
195
197
 
196
198
  puts table.render(:unicode, padding: [0, 1])
197
199
 
198
- if @plan_meta && @plan_meta['error'] == 'lock'
199
- done = catch(:abort) do
200
- if @plan_meta['Operation'] != 'OperationTypePlan'
200
+ if @plan_meta && @plan_meta["error"] == "lock"
201
+ done = catch(:abort) {
202
+ if @plan_meta["Operation"] != "OperationTypePlan"
201
203
  throw :abort unless prompt.yes?(
202
- "Are you sure you want to force unlock a lock for operation: #{@plan_meta['Operation']}",
204
+ "Are you sure you want to force unlock a lock for operation: #{@plan_meta["Operation"]}",
203
205
  default: false
204
206
  )
205
207
  end
206
208
 
207
209
  throw :abort unless prompt.yes?(
208
- 'Are you sure you want to force unlock this lock?',
210
+ "Are you sure you want to force unlock this lock?",
209
211
  default: false
210
212
  )
211
213
 
212
- status = tf_force_unlock(id: @plan_meta['ID'])
214
+ status = tf_force_unlock(id: @plan_meta["ID"])
213
215
  if status.success?
214
- log 'Done!'
216
+ log "Done!"
215
217
  else
216
218
  log Paint["Failed with status: #{status}", :red]
217
219
  end
218
220
 
219
221
  true
220
- end
222
+ }
221
223
 
222
- log Paint['Aborted', :yellow] unless done
224
+ log Paint["Aborted", :yellow] unless done
223
225
  else
224
- log Paint['No lock error or no plan ran!', :red]
226
+ log Paint["No lock error or no plan ran!", :red]
225
227
  end
226
228
  end
227
229
  end
228
230
 
229
231
  def upgrade_cmd
230
- define_cmd('upgrade', summary: 'Upgrade modules/plguins') do |_opts, _args, _cmd|
232
+ define_cmd("upgrade", summary: "Upgrade modules/plguins") do |_opts, _args, _cmd|
231
233
  status, meta = run_upgrade
232
234
  if status != :ok
233
235
  log meta.inspect unless meta.empty?
234
- log 'Upgrade Failed!'
236
+ log "Upgrade Failed!"
235
237
  end
236
238
  end
237
239
  end
238
240
 
239
241
  def interactive_cmd
240
- define_cmd('interactive', summary: 'Apply interactively') do |_opts, _args, _cmd|
241
- status = run_shell([tf_plan_summrary_cmd, PLAN_FILENAME, '-i'], return_status: true)
242
- if status != 0
243
- log 'Interactive Apply Failed!'
244
- else
245
- run_plan
242
+ define_cmd("interactive", summary: "Apply interactively") do |_opts, _args, _cmd|
243
+ plan = PlanSummaryHandler.from_file(PLAN_FILENAME)
244
+ begin
245
+ abort_message = catch :abort do
246
+ plan.run_interactive
247
+ end
248
+ if abort_message
249
+ log Paint["Aborted: #{abort_message}", :red]
250
+ else
251
+ run_plan
252
+ end
253
+ rescue Exception => e
254
+ log e.full_message
255
+ log "Interactive Apply Failed!"
246
256
  end
247
257
  end
248
258
  end
@@ -252,11 +262,11 @@ module MuxTf
252
262
 
253
263
  case plan_status
254
264
  when :ok
255
- log 'no changes', depth: 1
265
+ log "no changes", depth: 1
256
266
  when :error
257
- log 'something went wrong', depth: 1
267
+ log "something went wrong", depth: 1
258
268
  when :changes
259
- log 'Printing Plan Summary ...', depth: 1
269
+ log "Printing Plan Summary ...", depth: 1
260
270
  pretty_plan_summary(PLAN_FILENAME)
261
271
  when :unknown
262
272
  # nothing
@@ -278,16 +288,15 @@ module MuxTf
278
288
  end
279
289
  end
280
290
 
281
- def tf_plan_summrary_cmd
282
- @tf_plan_summrary_cmd ||= File.expand_path(File.join(__dir__, '..', '..', '..', 'exe', 'tf_plan_summary'))
283
- end
284
-
285
291
  def pretty_plan_summary(filename)
286
- run_with_each_line([tf_plan_summrary_cmd, filename]) do |raw_line|
287
- log raw_line.rstrip, depth: 2
292
+ plan = PlanSummaryHandler.from_file(filename)
293
+ plan.flat_summary.each do |line|
294
+ log line, depth: 2
288
295
  end
296
+ log "", depth: 2
297
+ log plan.summary, depth: 2
289
298
  end
299
+ end
290
300
  end
291
301
  end
292
- end
293
302
  end
@@ -8,48 +8,50 @@ module MuxTf
8
8
 
9
9
  class << self
10
10
  def run(_args)
11
- Dotenv.load('.env.mux')
11
+ Dotenv.load(".env.mux")
12
12
 
13
- log 'Enumerating folders ...'
13
+ log "Enumerating folders ..."
14
14
  dirs = enumerate_terraform_dirs
15
15
 
16
- fail_with 'Error: - no subfolders detected! Aborting.' if dirs.empty?
16
+ fail_with "Error: - no subfolders detected! Aborting." if dirs.empty?
17
17
 
18
- tasks = dirs.map do |dir|
18
+ tasks = dirs.map { |dir|
19
19
  {
20
20
  name: dir,
21
21
  cwd: dir,
22
- cmd: File.expand_path(File.join(__dir__, '..', '..', '..', 'exe', 'tf_current'))
22
+ cmd: File.expand_path(File.join(__dir__, "..", "..", "..", "exe", "tf_current"))
23
23
  }
24
- end
24
+ }
25
25
 
26
26
  project = File.basename(Dir.getwd)
27
27
 
28
- if ENV['MUX_TF_AUTH_WRAPPER']
29
- log 'Warming up AWS connection ...'
30
- words = Shellwords.shellsplit(ENV['MUX_TF_AUTH_WRAPPER'])
31
- result = capture_shell([*words, 'aws', 'sts', 'get-caller-identity'], raise_on_error: true)
28
+ if ENV["MUX_TF_AUTH_WRAPPER"]
29
+ log "Warming up AWS connection ..."
30
+ words = Shellwords.shellsplit(ENV["MUX_TF_AUTH_WRAPPER"])
31
+ result = capture_shell([*words, "aws", "sts", "get-caller-identity"], raise_on_error: true)
32
32
  p JSON.parse(result)
33
33
  end
34
34
 
35
35
  if Tmux.session_running?(project)
36
- log 'Killing existing session ...'
36
+ log "Killing existing session ..."
37
37
  Tmux.kill_session(project)
38
38
  end
39
39
 
40
- log 'Starting new session ...'
40
+ log "Starting new session ..."
41
41
  Tmux.new_session project
42
- Tmux.select_pane 'initial'
42
+ Tmux.select_pane "initial"
43
+
44
+ Tmux.set_hook "pane-exited", "select-layout tiled"
45
+ Tmux.set_hook "window-pane-changed", "select-layout tiled"
43
46
 
44
- Tmux.set_hook 'pane-exited', 'select-layout tiled'
45
- Tmux.set_hook 'window-pane-changed', 'select-layout tiled'
47
+ Tmux.set "mouse", "on"
46
48
 
47
- Tmux.set 'mouse', 'on'
49
+ window_id = Tmux.list_windows.first[:id]
48
50
 
49
51
  unless tasks.empty?
50
52
  tasks.each do |task|
51
53
  log "launching task: #{task[:name]} ...", depth: 2
52
- Tmux.split_window :horizontal, "#{project}:1", cmd: task[:cmd], cwd: task[:cwd]
54
+ Tmux.split_window :horizontal, "#{project}:#{window_id}", cmd: task[:cmd], cwd: task[:cwd]
53
55
  Tmux.select_pane task[:name]
54
56
  Tmux.tile!
55
57
  task[:commands]&.each do |cmd|
@@ -58,17 +60,17 @@ module MuxTf
58
60
  end
59
61
  end
60
62
 
61
- log 'Almost done ...'
63
+ log "Almost done ..."
62
64
 
63
- initial_pane = Tmux.find_pane('initial')
65
+ initial_pane = Tmux.find_pane("initial")
64
66
  Tmux.kill_pane initial_pane[:id]
65
67
  Tmux.tile!
66
68
 
67
69
  puts "\e]0;tmux: #{project}\007"
68
70
 
69
- log 'Attaching ...'
70
- Tmux.attach(project, cc: !!ENV['MUXP_CC_MODE'])
71
- log 'Done!'
71
+ log "Attaching ..."
72
+ Tmux.attach(project, cc: !!ENV["MUXP_CC_MODE"])
73
+ log "Done!"
72
74
  end
73
75
 
74
76
  private
@@ -76,9 +78,9 @@ module MuxTf
76
78
  def enumerate_terraform_dirs
77
79
  ignored = []
78
80
 
79
- ignored += ENV['MUX_IGNORE'].split(',') if ENV['MUX_IGNORE']
81
+ ignored += ENV["MUX_IGNORE"].split(",") if ENV["MUX_IGNORE"]
80
82
 
81
- dirs = Dir['**/*/.terraform'].map { |n| n.gsub(%r{/\.terraform}, '') }
83
+ dirs = Dir["**/*/.terraform"].map { |n| n.gsub(%r{/\.terraform}, "") }
82
84
  dirs.reject! { |d| d.in?(ignored) }
83
85
 
84
86
  dirs