mux_tf 0.2.2 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a554f0039080c094e9fe4096cc2e93dc66c073de44d18581c10061b927e466c
4
- data.tar.gz: 8b6ec1f3746db1815c12f21dc62872843c20a59c811a5953e334bfb59fad6daf
3
+ metadata.gz: 5f2940b8702e57dae5ff71b8f777e99795dfc041984559de93cf81a920047ab2
4
+ data.tar.gz: d07b3c1e3d0f2545c5cf1a7813b693ff17c15fe896af3039b3aa5d220fcb64b1
5
5
  SHA512:
6
- metadata.gz: 9868c26137825f6fdb09372488563d46cf51370d13decf64f456b5a6fd9c70073059a382640cf95e570291d91bdfc3d558018914193e8e00496877ecf556a91f
7
- data.tar.gz: 615146492ddd7462510b431a2b54976dd16d8b3e5c594c46fe61fefa7f8ab51217c87825cee5317a78769dfe0b27d2c85363b5e1ebfe0b951441b3aad171cad3
6
+ metadata.gz: 1050a664da014f3efd5005eb98acb79931328b31782864644285ec3a3d6caedcfa2dc760e483fc0f1ea8a513834c2ad087e02c00a216ee4dc3a7a0ac02287515
7
+ data.tar.gz: 5d4f4380fb4769b080b4c3de572ae08805c4b9a3b9fadd0ee76c76a7f1514db66bf1c3559b672631c996cb343e9da775e159cdce556278ae002a484fce912ddf
@@ -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
@@ -0,0 +1,5 @@
1
+ require "bundler/inline"
2
+
3
+ gemfile do
4
+ gemspec(path: File.join(__dir__, ".."))
5
+ end
@@ -1,30 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'English'
4
-
5
- require 'shellwords'
6
- require 'optparse'
7
- require 'json'
8
- require 'open3'
9
-
10
- require 'piotrb_cli_utils'
11
- require 'stateful_parser'
12
-
13
- require 'active_support/core_ext'
14
-
15
- require 'paint'
16
- require 'pastel'
17
- require 'tty-prompt'
18
- require 'tty-table'
19
- require 'dotenv'
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'
3
+ require_relative "./deps"
4
+
5
+ require "English"
6
+
7
+ require "shellwords"
8
+ require "optparse"
9
+ require "json"
10
+ require "open3"
11
+
12
+ require "piotrb_cli_utils"
13
+ require "stateful_parser"
14
+
15
+ require "active_support/core_ext"
16
+
17
+ require "paint"
18
+ require "pastel"
19
+ require "tty-prompt"
20
+ require "tty-table"
21
+ require "dotenv"
22
+
23
+ require_relative "./mux_tf/version"
24
+ require_relative "./mux_tf/cli"
25
+ require_relative "./mux_tf/tmux"
26
+ require_relative "./mux_tf/terraform_helpers"
27
+ require_relative "./mux_tf/plan_formatter"
28
+ require_relative "./mux_tf/version_check"
29
+ require_relative "./mux_tf/yaml_cache"
30
+ require_relative "./mux_tf/plan_summary_handler"
28
31
 
29
32
  module MuxTf
30
33
  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
70
  log "Run `#{Paint["gem install mux_tf", :green]}` to update!"
69
- log Paint["="*80, :yellow]
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 1
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