Module: MuxTf::Cli::Current

Extended by:
TerraformHelpers, PiotrbCliUtils::CmdLoop, PiotrbCliUtils::CriCommandSupport, PiotrbCliUtils::Util
Includes:
MuxTf::Coloring
Defined in:
lib/mux_tf/cli/current.rb,
lib/mux_tf/cli/current/plan_command.rb

Overview

rubocop:disable Metrics/ModuleLength

Defined Under Namespace

Classes: PlanCommand

Class Attribute Summary collapse

Class Method Summary collapse

Methods included from TerraformHelpers

tf_apply, tf_force_unlock, tf_init, tf_plan, tf_show, tf_stream_helper, tf_validate

Methods included from MuxTf::Coloring

included, #pastel

Class Attribute Details

.plan_commandObject

Returns the value of attribute plan_command.



15
16
17
# File 'lib/mux_tf/cli/current.rb', line 15

def plan_command
  @plan_command
end

Class Method Details

.detect_tool_type(tool_cmd: nil) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/mux_tf/cli/current.rb', line 17

def detect_tool_type(tool_cmd: nil)
  tool_cmd ||= ENV.fetch("MUX_TF_BASE_CMD", "terraform")
  output = `#{tool_cmd} --version`
  case output
  when /^Terraform v(.+)$/
    {
      tool_name: "terraform",
      tool_version: ::Regexp.last_match(1)
    }
  when /^OpenTofu v(.+)$/
    {
      tool_name: "opentofu",
      tool_version: ::Regexp.last_match(1)
    }
  when /^terragrunt version v(.+)$/
    result = {
      tool_wrapper: "terragrunt",
      tool_wrapper_version: ::Regexp.last_match(1)
    }
    tg_tool = ENV.fetch("TG_TF_PATH", "tofu")
    result.merge! detect_tool_type(tool_cmd: tg_tool)
    result
  else
    raise "can't parse tool version from: #{output.inspect}"
  end
end

.init_tool_envObject



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/mux_tf/cli/current.rb', line 44

def init_tool_env
  info = detect_tool_type

  if %w[terraform opentofu].include?(info[:tool_name])
    ENV["TF_IN_AUTOMATION"] = "1"
    ENV["TF_INPUT"] = "0"
  end

  return unless info[:tool_wrapper] == "terragrunt"

  if Gem::Version.new(info[:tool_wrapper_version]) >= Gem::Version.new("0.70.0")
    # new syntax
    ENV["TG_LOG_FORMAT"] = "json"
    ENV["TG_TF_FORWARD_STDOUT"] = "true"
  else
    # old syntax
    ENV["TERRAGRUNT_JSON_LOG"] = "1"
    ENV["TERRAGRUNT_FORWARD_TF_STDOUT"] = "1"
  end
end


132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/mux_tf/cli/current.rb', line 132

def print_errors_and_warnings(meta)
  message = []
  message << pastel.yellow("#{meta[:warnings].length} Warnings") if meta[:warnings]
  message << pastel.red("#{meta[:errors].length} Errors") if meta[:errors]
  if message.length.positive?
    log ""
    log "Encountered: #{message.join(' and ')}"
    log ""
  end

  meta[:warnings]&.each do |warning|
    next if warning[:printed]

    log "-" * 20
    log pastel.yellow("Warning: #{warning[:message]}")
    warning[:body]&.each do |line|
      log pastel.yellow(line), depth: 1
    end
    log ""
  end

  meta[:errors]&.each do |error|
    next if error[:printed]

    log "-" * 20
    log pastel.red("Error: #{error[:message]}")
    error[:body]&.each do |line|
      log pastel.red(line), depth: 1
    end
    log ""
  end

  return unless message.length.positive?

  log ""
end

.remedy_retry_helper(from:, level: 1, attempt: 0, &block) ⇒ Object

block is expected to return a touple, the first element is a list of remedies the rest are any additional results



117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/mux_tf/cli/current.rb', line 117

def remedy_retry_helper(from:, level: 1, attempt: 0, &block)
  catch(:abort) do
    until attempt > 1
      attempt += 1
      remedies, *results = block.call
      return results if remedies.empty?

      remedy_status, remedy_results = process_remedies(remedies, from: from, level: level)
      throw :abort, false if remedy_results[:user_error]
      return remedy_status if remedy_status
    end
    log "!! giving up because attempt: #{attempt}"
  end
end

.run(args) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/mux_tf/cli/current.rb', line 65

def run(args)
  version_check

  self.plan_command = PlanCommand.new

  init_tool_env

  if args[0] == "cli"
    cmd_loop
    return
  end

  unless args.empty?
    root_cmd = build_root_cmd
    valid_commands = root_cmd.subcommands.map(&:name)

    if args[0] && valid_commands.include?(args[0])
      stop_reason = catch(:stop) {
        root_cmd.run(args, {}, hard_exit: true)
        nil
      }
      log pastel.red("Stopped: #{stop_reason}") if stop_reason
      return
    end
  end

  folder_name = File.basename(Dir.getwd)
  log "Processing #{pastel.cyan(folder_name)} ..."

  return launch_cmd_loop(:error) unless @plan_command.run_validate

  if ENV["TF_UPGRADE"]
    upgrade_status, _upgrade_meta = run_upgrade
    return launch_cmd_loop(:error) unless upgrade_status == :ok
  end

  plan_status = @plan_command.run_plan

  case plan_status
  when :ok
    log "exiting", depth: 1
  when :error
    launch_cmd_loop(plan_status)
  when :changes # rubocop:disable Lint/DuplicateBranch
    launch_cmd_loop(plan_status)
  when :unknown # rubocop:disable Lint/DuplicateBranch
    launch_cmd_loop(plan_status)
  end
end