class Krane::RenderTask

Render templates

Public Class Methods

new(logger: nil, current_sha:, template_dir: nil, template_paths: [], bindings:) click to toggle source

Initializes the render task

@param logger [Object] Logger object (defaults to an instance of Krane::FormattedLogger) @param current_sha [String] The SHA of the commit @param template_dir [String] Path to a directory with templates to render (deprecated) @param template_paths [Array<String>] An array of template paths to render @param bindings [Hash] Bindings parsed by Krane::BindingsParser

# File lib/krane/render_task.rb, line 18
def initialize(logger: nil, current_sha:, template_dir: nil, template_paths: [], bindings:)
  @logger = logger || Krane::FormattedLogger.build
  @template_dir = template_dir
  @template_paths = template_paths.map { |path| File.expand_path(path) }
  @bindings = bindings
  @current_sha = current_sha
end

Public Instance Methods

run(*args) click to toggle source

Runs the task, returning a boolean representing success or failure

@return [Boolean]

# File lib/krane/render_task.rb, line 29
def run(*args)
  run!(*args)
  true
rescue Krane::FatalDeploymentError
  false
end
run!(stream, only_filenames = []) click to toggle source

Runs the task, raising exceptions in case of issues

@param stream [IO] Place to stream the output to @param only_filenames [Array<String>] List of filenames to render

@return [nil]

# File lib/krane/render_task.rb, line 42
def run!(stream, only_filenames = [])
  @logger.reset
  @logger.phase_heading("Initializing render task")

  ts = TemplateSets.from_dirs_and_files(paths: template_sets_paths(only_filenames), logger: @logger)

  validate_configuration(ts, only_filenames)
  count = render_templates(stream, ts)

  @logger.summary.add_action("Successfully rendered #{count} template(s)")
  @logger.print_summary(:success)
rescue Krane::FatalDeploymentError
  @logger.print_summary(:failure)
  raise
end

Private Instance Methods

log_invalid_template(exception) click to toggle source
# File lib/krane/render_task.rb, line 138
def log_invalid_template(exception)
  @logger.error("Failed to render #{exception.filename}")

  debug_msg = ColorizedString.new("Invalid template: #{exception.filename}\n").red
  debug_msg += "> Error message:\n#{FormattedLogger.indent_four(exception.to_s)}"
  if exception.content
    debug_msg += "\n> Template content:\n#{FormattedLogger.indent_four(exception.content)}"
  end
  @logger.summary.add_paragraph(debug_msg)
end
render_templates(stream, template_sets) click to toggle source
# File lib/krane/render_task.rb, line 74
def render_templates(stream, template_sets)
  @logger.phase_heading("Rendering template(s)")
  count = 0
  template_sets.with_resource_definitions_and_filename(render_erb: true,
      current_sha: @current_sha, bindings: @bindings, raw: true) do |rendered_content, filename|
    write_to_stream(rendered_content, filename, stream)
    count += 1
  end

  count
rescue Krane::InvalidTemplateError => exception
  log_invalid_template(exception)
  raise
end
template_sets_paths(only_filenames) click to toggle source
# File lib/krane/render_task.rb, line 60
def template_sets_paths(only_filenames)
  if @template_paths.present?
    # Validation will catch @template_paths & @template_dir being present
    @template_paths
  elsif only_filenames.blank?
    [File.expand_path(@template_dir || '')]
  else
    absolute_template_dir = File.expand_path(@template_dir || '')
    only_filenames.map do |name|
      File.join(absolute_template_dir, name)
    end
  end
end
validate_configuration(template_sets, filenames) click to toggle source
# File lib/krane/render_task.rb, line 105
def validate_configuration(template_sets, filenames)
  @logger.info("Validating configuration")
  errors = []
  if @template_dir.present? && @template_paths.present?
    errors << "template_dir and template_paths can not be combined"
  elsif @template_dir.blank? && @template_paths.blank?
    errors << "template_dir or template_paths must be set"
  end

  if filenames.present?
    if @template_dir.nil?
      errors << "template_dir must be set to use filenames"
    else
      absolute_template_dir = File.expand_path(@template_dir)
      filenames.each do |filename|
        absolute_file = File.expand_path(File.join(@template_dir, filename))
        unless absolute_file.start_with?(absolute_template_dir)
          errors << "Filename \"#{absolute_file}\" is outside the template directory," \
          " which was resolved as #{absolute_template_dir}"
        end
      end
    end
  end

  errors += template_sets.validate

  unless errors.empty?
    @logger.summary.add_action("Configuration invalid")
    @logger.summary.add_paragraph(errors.map { |err| "- #{err}" }.join("\n"))
    raise Krane::TaskConfigurationError, "Configuration invalid: #{errors.join(', ')}"
  end
end
write_to_stream(rendered_content, filename, stream) click to toggle source
# File lib/krane/render_task.rb, line 89
def write_to_stream(rendered_content, filename, stream)
  file_basename = File.basename(filename)
  @logger.info("Rendering #{file_basename}...")
  implicit = []
  YAML.parse_stream(rendered_content, "<rendered> #{filename}") { |d| implicit << d.implicit }
  if rendered_content.present?
    stream.puts "---\n" if implicit.first
    stream.puts rendered_content
    @logger.info("Rendered #{file_basename}")
  else
    @logger.warn("Rendered #{file_basename} successfully, but the result was blank")
  end
rescue Psych::SyntaxError => exception
  raise InvalidTemplateError.new("Template is not valid YAML. #{exception.message}", filename: filename)
end