Class: Terraspace::All::Runner

Inherits:
Base
  • Object
show all
Includes:
Util
Defined in:
lib/terraspace/all/runner.rb

Instance Method Summary collapse

Methods included from Util::Pretty

#pretty_path, #pretty_time

Methods included from Util::Sure

#sure?

Methods included from Util::Logging

#logger

Constructor Details

#initialize(command, options = {}) ⇒ Runner

Returns a new instance of Runner.



5
6
7
8
# File 'lib/terraspace/all/runner.rb', line 5

def initialize(command, options={})
  @command, @options = command, options
  super(options)
end

Instance Method Details

#are_you_sure?Boolean

Returns:

  • (Boolean)


154
155
156
157
# File 'lib/terraspace/all/runner.rb', line 154

def are_you_sure?
  return true unless sure_command?
  sure? # from Util
end

#build_batchesObject



23
24
25
26
27
# File 'lib/terraspace/all/runner.rb', line 23

def build_batches
  @batches = run_builder(quiet: false)
  @batches.reverse! if @command == "down"
  @batches
end

#command_map(name) ⇒ Object



146
147
148
149
150
151
152
# File 'lib/terraspace/all/runner.rb', line 146

def command_map(name)
  map = {
    up:   "apply",
    down: "destroy",
  }.stringify_keys
  map[name] || name
end

#deploy_batch(batch) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/terraspace/all/runner.rb', line 44

def deploy_batch(batch)
  @pids = {} # stores child processes pids. map of pid to mod_name, reset this list on each batch run
  concurrency = Terraspace.config.all.concurrency
  batch.sort_by(&:name).each_slice(concurrency) do |slice|
    slice.each do |node|
      pid = fork do
        run_terraspace(node.name)
      end
      @pids[pid] = node.name # store mod_name mapping
    end
  end
  wait_for_child_proccess
  summarize     # also reports lower-level error info
  report_errors # reports finall errors and possibly exit
end

#deploy_batchesObject



29
30
31
32
33
34
35
36
# File 'lib/terraspace/all/runner.rb', line 29

def deploy_batches
  truncate_logs if ENV['TS_TRUNCATE_LOGS']
  @batches.each_with_index do |batch,i|
    logger.info "Batch Run #{i+1}:"
    run_builder unless i == 0 # already handled by build_batches the first time
    deploy_batch(batch)
  end
end

#exit_on_fail?Boolean

Precendence:

  1. env var

  2. cli

  3. config/app.rb setting

Returns:

  • (Boolean)


84
85
86
87
88
89
90
91
# File 'lib/terraspace/all/runner.rb', line 84

def exit_on_fail?
  return false if ENV['TS_EXIT_ON_FAIL'] == '0'
  if @options[:exit_on_fail].nil?
    Terraspace.config.all.exit_on_fail[@command]
  else
    @options[:exit_on_fail]
  end
end

#log_path(mod_name) ⇒ Object



133
134
135
# File 'lib/terraspace/all/runner.rb', line 133

def log_path(mod_name)
  "#{Terraspace.config.log.root}/#{@command}/#{mod_name}.log"
end

#previewObject



19
20
21
# File 'lib/terraspace/all/runner.rb', line 19

def preview
  Preview.new(@command, @batches, @options).show
end

#report_errorsObject



69
70
71
72
73
74
75
76
77
78
# File 'lib/terraspace/all/runner.rb', line 69

def report_errors
  @errors.each do |pid|
    mod_name = @pids[pid]
    terraspace_command = terraspace_command(mod_name)
    logger.error "Error running: #{terraspace_command}. Check logs and fix the error.".color(:red)
  end
  unless @errors.empty?
    exit 2 if exit_on_fail?
  end
end

#runObject



10
11
12
13
14
15
16
17
# File 'lib/terraspace/all/runner.rb', line 10

def run
  time_took do
    @batches = build_batches
    preview
    are_you_sure?
    deploy_batches
  end
end

#run_builder(quiet: true) ⇒ Object

Should run after each batch run. run_builder also calls replace_outputs. Important: rebuild from source so placeholders are in place.



40
41
42
# File 'lib/terraspace/all/runner.rb', line 40

def run_builder(quiet: true)
  Terraspace::Builder.new(@options.merge(mod: "placeholder", quiet: quiet)).run
end

#run_terraspace(mod_name) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/terraspace/all/runner.rb', line 104

def run_terraspace(mod_name)
  set_log_path!(mod_name)
  name = command_map(@command)
  o = @options.merge(mod: mod_name, yes: true, build: false, input: false)
  o.merge!(quiet: false) if @command == "init" # noisy so can filter and summarize output
  case @command
  when "up"
    Terraspace::CLI::Up.new(o).run
  when "down"
    Terraspace::CLI::Down.new(o).run
  else
    Terraspace::CLI::Commander.new(name, o).run
  end
end

#set_log_path!(mod_name) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/terraspace/all/runner.rb', line 119

def set_log_path!(mod_name)
  command = terraspace_command(mod_name)
  path = log_path(mod_name)
  pretty_path = Terraspace::Util.pretty_path(path)
  logger.info "Running: #{command.bright} Logs: #{pretty_path}"

  FileUtils.mkdir_p(File.dirname(path))
  logger = Terraspace::Logger.new(path)
  logger.level = Terraspace.config.logger.level # match the level that user configured
  logger.formatter = Terraspace.config.logger.formatter # match the level that user configured
  logger.progname = command
  Terraspace.logger = logger
end

#summarizeObject



93
94
95
96
97
98
99
100
101
102
# File 'lib/terraspace/all/runner.rb', line 93

def summarize
  @pids.each do |_, mod_name|
    data = {
      command: @command,
      log_path: log_path(mod_name),
      terraspace_command: terraspace_command(mod_name),
    }
    Summary.new(data).run
  end
end

#sure_command?Boolean

Returns:

  • (Boolean)


159
160
161
# File 'lib/terraspace/all/runner.rb', line 159

def sure_command?
  %w[up down].include?(@command)
end

#terraspace_command(name) ⇒ Object



142
143
144
# File 'lib/terraspace/all/runner.rb', line 142

def terraspace_command(name)
  "terraspace #{@command} #{name}"
end

#time_tookObject



163
164
165
166
167
168
# File 'lib/terraspace/all/runner.rb', line 163

def time_took
  t1 = Time.now
  yield
  t2 = Time.now
  logger.info "Time took: #{pretty_time(t2-t1)}"
end

#truncate_logsObject



137
138
139
140
# File 'lib/terraspace/all/runner.rb', line 137

def truncate_logs
  logs = Terraspace::CLI::Log::Tasks.new(mute: true)
  logs.truncate
end

#wait_for_child_proccessObject



60
61
62
63
64
65
66
67
# File 'lib/terraspace/all/runner.rb', line 60

def wait_for_child_proccess
  @errors = [] # stores child processes pids that errored
  @pids.each do |pid, _|
    pid, status = Process.wait2(pid)
    success = status.exitstatus == 0
    @errors << pid unless success
  end
end