mux_tf 0.2.1 → 0.3.1

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: 4c60cb54c7514e17f82865850165b25a3146086cc3906e024296d5d9e19b7a7f
4
- data.tar.gz: c2715accbc4a4c1d326db5be541f947a9228ddbd2c36b6c026cbf528baa60498
3
+ metadata.gz: 1a5386f0053732c1613b294b19bd94890a3dc5dbea9a6a443a35e6ca78ca0d36
4
+ data.tar.gz: 263c0bbe4fe2de06e2833f5640ad7bfb0e69814a37a8a199a9e360c99308cf28
5
5
  SHA512:
6
- metadata.gz: ab7c0591caa23fef662acb3a496a38bf8bbbd74fc2aeae8f1e83010f6412312ace34ac68ac2110d0c2ef5eaf01f34a0cdf69b784d3959bfa4a1b036d5dd96ba3
7
- data.tar.gz: c2569420e3dc71a1a2a88fb8ecb636b8be5ad7990ed73612f20459678cebb5731576a37c3ff0830990c423a333fd879494de00a227ed984696e7c63d21c030f0
6
+ metadata.gz: 56b45e534766f0efcdad2b008ecc3d0c7fe016ae4a0fed5009ca2df9094832d218aa3793b081cbf9e78d59b1cb847a3b9038bd5de41fa18e9f9ecaf2f914dcd9
7
+ data.tar.gz: b9d94d51350c22a7c1004194877cf2314f84208394711a3edd16cbd640d86332c1d12966089c656d242ea40977bd3dd9a9bb45b1439e606550366c53a138929a
@@ -1,8 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- $LOAD_PATH << File.expand_path(File.join(__dir__, '..', 'lib'))
4
+ begin
5
+ $LOAD_PATH << File.expand_path(File.join(__dir__, "..", "lib"))
5
6
 
6
- require 'mux_tf'
7
+ require "mux_tf"
7
8
 
8
- MuxTf::Cli.run(:current, ARGV)
9
+ MuxTf::Cli.run(:current, ARGV)
10
+ rescue Exception => e
11
+ warn e.full_message
12
+ warn "<press enter>"
13
+ gets
14
+ exit 1
15
+ end
data/exe/tf_mux CHANGED
@@ -1,8 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- $LOAD_PATH << File.expand_path(File.join(__dir__, '..', 'lib'))
4
+ begin
5
+ $LOAD_PATH << File.expand_path(File.join(__dir__, "..", "lib"))
5
6
 
6
- require 'mux_tf'
7
+ require "mux_tf"
7
8
 
8
- MuxTf::Cli.run(:mux, ARGV)
9
+ MuxTf::Cli.run(:mux, ARGV)
10
+ rescue Exception => e
11
+ warn e.full_message
12
+ warn "<press enter>"
13
+ gets
14
+ exit 1
15
+ end
@@ -1,8 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- $LOAD_PATH << File.expand_path(File.join(__dir__, '..', 'lib'))
4
+ begin
5
+ $LOAD_PATH << File.expand_path(File.join(__dir__, "..", "lib"))
5
6
 
6
- require 'mux_tf'
7
+ require "mux_tf"
7
8
 
8
- MuxTf::Cli.run(:plan_summary, ARGV)
9
+ MuxTf::Cli.run(:plan_summary, ARGV)
10
+ rescue Exception => e
11
+ warn e.full_message
12
+ warn "<press enter>"
13
+ gets
14
+ exit 1
15
+ end
@@ -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 mux_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
@@ -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 Mux
@@ -7,49 +9,70 @@ module MuxTf
7
9
  extend PiotrbCliUtils::ShellHelpers
8
10
 
9
11
  class << self
12
+ def with_clean_env
13
+ backup = {}
14
+ Bundler.with_original_env do
15
+ ENV.keys.grep(/^(RBENV_|RUBYLIB)/).each do |key|
16
+ backup[key] = ENV[key]
17
+ ENV.delete(key)
18
+ end
19
+ yield
20
+ end
21
+ ensure
22
+ backup.each do |k, v|
23
+ ENV[k] = v
24
+ end
25
+ end
26
+
10
27
  def run(_args)
11
- Dotenv.load('.env.mux')
28
+ Dotenv.load(".env.mux")
12
29
 
13
- log 'Enumerating folders ...'
30
+ log "Enumerating folders ..."
14
31
  dirs = enumerate_terraform_dirs
15
32
 
16
- fail_with 'Error: - no subfolders detected! Aborting.' if dirs.empty?
33
+ fail_with "Error: - no subfolders detected! Aborting." if dirs.empty?
17
34
 
18
- tasks = dirs.map do |dir|
35
+ tasks = dirs.map { |dir|
19
36
  {
20
37
  name: dir,
21
38
  cwd: dir,
22
- cmd: File.expand_path(File.join(__dir__, '..', '..', '..', 'exe', 'tf_current'))
39
+ cmd: File.expand_path(File.join(__dir__, "..", "..", "..", "exe", "tf_current"))
23
40
  }
24
- end
41
+ }
25
42
 
26
43
  project = File.basename(Dir.getwd)
27
44
 
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)
45
+ if ENV["MUX_TF_AUTH_WRAPPER"]
46
+ log "Warming up AWS connection ..."
47
+ words = Shellwords.shellsplit(ENV["MUX_TF_AUTH_WRAPPER"])
48
+ result = capture_shell([*words, "aws", "sts", "get-caller-identity"], raise_on_error: true)
32
49
  p JSON.parse(result)
33
50
  end
34
51
 
35
52
  if Tmux.session_running?(project)
36
- log 'Killing existing session ...'
53
+ log "Killing existing session ..."
37
54
  Tmux.kill_session(project)
38
55
  end
39
56
 
40
- log 'Starting new session ...'
41
- Tmux.new_session project
42
- Tmux.select_pane 'initial'
57
+ log "Starting new session ..."
58
+ with_clean_env do
59
+ Tmux.new_session project
60
+ end
61
+ Tmux.select_pane "initial"
62
+
63
+ # Tmux.set "remain-on-exit", "on"
43
64
 
44
- Tmux.set_hook 'pane-exited', 'select-layout tiled'
45
- Tmux.set_hook 'window-pane-changed', 'select-layout tiled'
65
+ Tmux.set_hook "pane-exited", "select-layout tiled"
66
+ Tmux.set_hook "window-pane-changed", "select-layout tiled"
46
67
 
47
- Tmux.set 'mouse', 'on'
68
+ Tmux.set "mouse", "on"
69
+
70
+ window_id = Tmux.list_windows.first[:id]
48
71
 
49
72
  unless tasks.empty?
50
73
  tasks.each do |task|
51
74
  log "launching task: #{task[:name]} ...", depth: 2
52
- Tmux.split_window :horizontal, "#{project}:1", cmd: task[:cmd], cwd: task[:cwd]
75
+ Tmux.split_window :horizontal, "#{project}:#{window_id}", cmd: task[:cmd], cwd: task[:cwd]
53
76
  Tmux.select_pane task[:name]
54
77
  Tmux.tile!
55
78
  task[:commands]&.each do |cmd|
@@ -58,17 +81,19 @@ module MuxTf
58
81
  end
59
82
  end
60
83
 
61
- log 'Almost done ...'
84
+ log "Almost done ..."
62
85
 
63
- initial_pane = Tmux.find_pane('initial')
86
+ initial_pane = Tmux.find_pane("initial")
64
87
  Tmux.kill_pane initial_pane[:id]
65
88
  Tmux.tile!
66
89
 
67
90
  puts "\e]0;tmux: #{project}\007"
68
91
 
69
- log 'Attaching ...'
70
- Tmux.attach(project, cc: !!ENV['MUXP_CC_MODE'])
71
- log 'Done!'
92
+ sleep 5
93
+
94
+ log "Attaching ..."
95
+ Tmux.attach(project, cc: !!ENV["MUXP_CC_MODE"])
96
+ log "Done!"
72
97
  end
73
98
 
74
99
  private
@@ -76,9 +101,9 @@ module MuxTf
76
101
  def enumerate_terraform_dirs
77
102
  ignored = []
78
103
 
79
- ignored += ENV['MUX_IGNORE'].split(',') if ENV['MUX_IGNORE']
104
+ ignored += ENV["MUX_IGNORE"].split(",") if ENV["MUX_IGNORE"]
80
105
 
81
- dirs = Dir['**/*/.terraform'].map { |n| n.gsub(%r{/\.terraform}, '') }
106
+ dirs = Dir["**/*/.terraform"].map { |n| n.gsub(%r{/\.terraform}, "") }
82
107
  dirs.reject! { |d| d.in?(ignored) }
83
108
 
84
109
  dirs