mux_tf 0.2.0 → 0.3.0

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: '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