theforeman/foreman_remote_execution

View on GitHub
app/models/input_template_renderer.rb

Summary

Maintainability
A
1 hr
Test Coverage
class InputTemplateRenderer
  class UndefinedInput < ::Foreman::Exception
  end

  class RenderError < ::Foreman::Exception
  end

  delegate :logger, to: Rails

  attr_accessor :template, :host, :invocation, :template_input_values, :error_message, :templates_stack, :current_user

  # takes template object that should be rendered
  # host and template invocation arguments are optional
  # so we can render values based on parameters, facts or user inputs
  def initialize(template, host = nil, invocation = nil, input_values = nil, preview = false, templates_stack = [])
    raise Foreman::Exception, N_('Recursive rendering of templates detected') if templates_stack.include?(template)

    @host = host
    @template = template
    @invocation = invocation
    @template_input_values = input_values
    @preview = preview
    @templates_stack = templates_stack + [template]
  end

  def render
    @template_input_values ||= values_from_invocation
    @template.validate_unique_inputs!
    source = Foreman::Renderer.get_source(
      template: template,
      host: host
    )
    @scope = Foreman::Renderer.get_scope(
      source: source,
      host: host,
      klass: renderer_scope,
      template_input_values: @template_input_values,
      variables: {
        host: host,
        template: template,
        preview: @preview,
        invocation: invocation,
        input_values: @template_input_values,
        templates_stack: templates_stack,
        input_template_instance: self,
        current_user: User.current.try(:login),
      }
    )
    Foreman::Renderer.render(source, @scope)
  rescue => e
    self.error_message ||= _('error during rendering: %s') % e.message
    Foreman::Logging.exception('Error during rendering of a job template', e)
    false
  end

  def preview
    old_preview = @preview
    @preview = true
    render
  ensure
    @preview = old_preview
  end

  private

  def values_from_invocation
    input_values = @invocation ? Hash[@invocation.input_values.map { |iv| [iv.template_input.name, iv.value] }] : {}
    default_values = template.default_input_values(input_values.keys)
    result = @preview ? input_values : default_values.merge(input_values)
    result.with_indifferent_access
  end

  def renderer_scope
    ForemanRemoteExecution::Renderer::Scope::Input
  end

  def find_by_name(collection, name)
    collection.detect { |i| i.name == name.to_s }
  end
end