Project

General

Profile

Download (20 KB) Statistics
| Branch: | Tag: | Revision:
module RenderersSharedTests
extend ActiveSupport::Concern

included do
setup do
@template = OpenStruct.new(
name: 'abc',
template: 'Test'
)
source = Foreman::Renderer::Source::Database.new(
@template
)
@host = FactoryBot.create(:host, architecture: FactoryBot.create(:architecture, :name => 'SPARC-T2'),
operatingsystem: operatingsystems(:redhat))
@scope = Class.new(Foreman::Renderer::Scope::Base) do
include Foreman::Renderer::Scope::Macros::Base
include Foreman::Renderer::Scope::Macros::SnippetRendering
end.send(:new, host: @host, source: source, variables: { x: 'test' })
Setting['foreman_url'] = 'http://foreman.example.net'
end

test "should evaluate template variables" do
source = OpenStruct.new(content: '<%= @host.name %>')
assert_equal @host.name, renderer.render(source, @scope)
end

test "should evaluate renderer methods" do
@scope.expects(:foreman_url).returns('bar')
source = OpenStruct.new(content: '<%= foreman_url %>')
assert_equal 'bar', renderer.render(source, @scope)
end

test "foreman_server_fqdn helper method" do
source = OpenStruct.new(content: '<%= foreman_server_fqdn %>')
assert_equal 'foreman.example.net', renderer.render(source, @scope)
end

test "foreman_server_url helper method" do
source = OpenStruct.new(content: '<%= foreman_server_url %>')
assert_equal 'http://foreman.example.net', renderer.render(source, @scope)
end

test "plugin_present? finds existing plugin" do
Foreman::Plugin.register(:existing_plugin) {}
source = OpenStruct.new(content: '<%= plugin_present?("existing_plugin") %>')
assert_equal 'true', renderer.render(source, @scope)
end

test "plugin_present? does not find nonexistant plugin" do
Foreman::Plugin.register(:existing_plugin) {}
source = OpenStruct.new(content: '<%= plugin_present?("nonexisting_plugin") %>')
assert_equal 'false', renderer.render(source, @scope)
end

test "rand_hex helper method" do
source = OpenStruct.new(content: '<%= rand_hex(5) %>')
assert_not_nil renderer.render(source, @scope)
end

test "rand_name helper method" do
source = OpenStruct.new(content: '<%= rand_name %>')
assert_not_nil renderer.render(source, @scope)
end

test "mac_name helper method" do
source = OpenStruct.new(content: '<%= mac_name("52:54:00:3d:f3:53") %>')
assert_equal 'jimmy-alton-danko-deckard', renderer.render(source, @scope)
end

test "indent helper method" do
source = OpenStruct.new(content: '<%= indent(3) { "test" } %>')
assert_equal ' test', renderer.render(source, @scope)
end

test "global_setting helper method" do
source = OpenStruct.new(content: '<%= global_setting("default_pxe_item_global") %>')
Setting[:default_pxe_item_global] = "PASS"
assert_equal 'PASS', renderer.render(source, @scope)
end

test "global_setting helper method with special case 'false'" do
source = OpenStruct.new(content: '<%= global_setting("default_pxe_item_global") %>')
Setting[:default_pxe_item_global] = false
assert_equal '', renderer.render(source, @scope)
end

test "global_setting helper method with symbol" do
source = OpenStruct.new(content: '<%= global_setting("default_pxe_item_global") %>')
Setting[:default_pxe_item_global] = "PASS"
assert_equal 'PASS', renderer.render(source, @scope)
end

test "global_setting helper method with own default" do
source = OpenStruct.new(content: '<%= global_setting("default_pxe_item_global", "PASS") %>')
Setting[:default_pxe_item_global] = ""
assert_equal 'PASS', renderer.render(source, @scope)
end

test "global_setting helper default does not work with boolean" do
source = OpenStruct.new(content: '<%= global_setting("update_ip_from_built_request", "FAIL").to_s %>')
Setting[:update_ip_from_built_request] = false
assert_equal "boolean", Setting.find_by_name("update_ip_from_built_request").settings_type
assert_equal 'false', renderer.render(source, @scope)
end

test "dns_lookup helper method - address" do
source = OpenStruct.new(content: '<%= dns_lookup("test.domain.com") %>')
Resolv::DNS.any_instance.expects(:getaddress).with("test.domain.com").returns("1.2.3.4")
assert_equal "1.2.3.4", renderer.render(source, @scope)
end

test "dns_lookup helper method - hostname" do
source = OpenStruct.new(content: '<%= dns_lookup("1.2.3.4") %>')
Resolv::DNS.any_instance.expects(:getname).with("1.2.3.4").returns("test.domain.com")
assert_equal "test.domain.com", renderer.render(source, @scope)
end

test "dns_lookup helper method - invalid IPv4" do
source = OpenStruct.new(content: '<%= dns_lookup("1.2.3.999") %>')
Resolv::DNS.any_instance.expects(:getaddress).with("1.2.3.999").returns("xxx")
assert_equal "xxx", renderer.render(source, @scope)
end

test "should define passed variables only in snippet scope" do
level2_snippet = FactoryBot.create(:provisioning_template, :snippet, :template => "<%= @level2 -%>")
level1_snippet = FactoryBot.create(:provisioning_template, :snippet, :template => "<%= @level1 -%><%= snippet('#{level2_snippet.name}', :variables => {:level2 => 2}) %><%= @level2 %>")
source = OpenStruct.new(content: "<%= snippet('#{level1_snippet.name}', :variables => {:level1 => 1}) -%><%= @level1 %>")
assert_equal '12', renderer.render(source, @scope)
end

test "should pass variables from template to snippet" do
snippet = FactoryBot.create(:provisioning_template, :snippet, :template => "<%= @x -%>")
template = OpenStruct.new(content: "<%= snippet('#{snippet.name}') %>")

assert_equal renderer.render(template, @scope), 'test'
end

test "should render a save_to_file macro" do
source = OpenStruct.new(content: '<%= save_to_file("/etc/puppet/puppet.conf", "[main]\nserver=example.com\n") %>')
assert_nothing_raised do
assert_equal("cat << EOF-728d4ec4 > /etc/puppet/puppet.conf\n[main]\nserver=example.com\nEOF-728d4ec4", renderer.render(source, @scope))
end
end

test "should render a templates_used" do
source = OpenStruct.new(content: '<%= @host.templates_used %>')
assert_nothing_raised do
content = renderer.render(source, @scope)
assert_match(/#{@host.provisioning_template(:kind => 'provision')}/, content)
assert_match(/#{@host.provisioning_template(:kind => 'script')}/, content)
end
end

test "should render template name" do
source = OpenStruct.new(name: @template.name, content: 'x <%= @template_name %> <%= template_name %>')
assert_equal 'x abc abc', renderer.render(source, @scope)
end

test "should render with AR relation method calls" do
source = OpenStruct.new(content: "<% @host.managed_interfaces.each do |int| -%><%= int.to_s -%><% end -%>")
assert_equal @host.name, renderer.render(source, @scope)
end

test "should render with AR collection proxy method calls" do
source = OpenStruct.new(content: "<% @host.interfaces.each do |int| -%><%= int.to_s -%><% end -%>")
assert_equal @host.name, renderer.render(source, @scope)
end

test "global_setting unsafe attempt" do
source = OpenStruct.new(content: '<%= global_setting("not_allowed_setting") %>')
assert_raises(Foreman::Renderer::Errors::FilteredGlobalSettingAccessed) do
renderer.render(source, @scope)
end
end

test "should raise SyntaxError" do
source = OpenStruct.new(content: '<%- begin %>')
assert_raises(Foreman::Renderer::Errors::SyntaxError) do
renderer.render(source, @scope)
end
end

test "should load hosts" do
source = OpenStruct.new(content: '<%= load_hosts.map { |b| b.size }.inject(0) { |m,c| m += c } %>')
assert_equal(renderer.render(source, @scope), Host.count.to_s)
end

test "should find all registered host statuses" do
source = OpenStruct.new(content: '<%= all_host_statuses.map { |s| s.status_name }.join(",") %>')
statuses = renderer.render(source, @scope).split(',')

assert_includes statuses, 'Build'
assert_includes statuses, 'Configuration'
assert(statuses.index('Build') < statuses.index('Configuration'))
end

test "should respect preview setting" do
source = OpenStruct.new(content: 'id <%= preview? %>')

assert_equal("id false", renderer.render(source, @scope))
@scope.instance_variable_set '@mode', Foreman::Renderer::PREVIEW_MODE
assert_equal("id true", renderer.render(source, @scope))
end

test "should compare versions correctly" do
source = OpenStruct.new(content: '<%= gem_version_compare("10.2.3", "2.0.1") %>')
assert_equal(renderer.render(source, @scope), '1')

source = OpenStruct.new(content: '<%= gem_version_compare("1.2.3", "1.2.3") %>')
assert_equal(renderer.render(source, @scope), '0')

source = OpenStruct.new(content: '<%= gem_version_compare("1.2.3", "1.2.4") %>')
assert_equal(renderer.render(source, @scope), '-1')
end

describe '#foreman_server_ca_cert' do
subject { renderer.render(source, @scope) }

let(:source) { OpenStruct.new(content: '<%= foreman_server_ca_cert %>') }
let(:cert_path) { Rails.root.join('test/static_fixtures/certificates/example.com.crt') }
let(:cert_2_path) { Rails.root.join('test/static_fixtures/certificates/example2.com.crt') }
let(:cert_file_content) { File.read(cert_path) }
let(:cert_2_file_content) { File.read(cert_2_path) }

test "load server_ca_file" do
Setting[:server_ca_file] = cert_path
Setting[:ssl_ca_file] = 'not-existing-file'

assert_equal subject, cert_file_content
end

test "load ssl_ca_file" do
Setting[:server_ca_file] = 'not-existing-file'
Setting[:ssl_ca_file] = cert_path

assert_equal subject, cert_file_content
end

test "load server_ca_file and ssl_ca_file" do
Setting[:server_ca_file] = cert_path
Setting[:ssl_ca_file] = cert_2_path

expected = "#{cert_file_content}\n#{cert_2_file_content}"
assert_equal subject, expected
end

test "do not load any files and raise exception" do
Setting[:server_ca_file] = 'not-existing-file'
Setting[:ssl_ca_file] = 'not-existing-file'

error = assert_raise Foreman::Exception do
subject
end

assert_includes error.message, "SSL CA file not found, check the 'Server CA file' and 'SSL CA file' in Settings > Authentication"
end

context 'when server_ca_file is disabled' do
let(:source) { OpenStruct.new(content: '<%= foreman_server_ca_cert(server_ca_file_enabled: false) %>') }

test "do not load server_ca_file and raise exception" do
Setting[:server_ca_file] = cert_path
Setting[:ssl_ca_file] = 'not-existing-file'

error = assert_raise Foreman::Exception do
subject
end

assert_includes error.message, "SSL CA file not found, check the 'Server CA file' and 'SSL CA file' in Settings > Authentication"
end
end

context 'when ssl_ca_file is disabled' do
let(:source) { OpenStruct.new(content: '<%= foreman_server_ca_cert(ssl_ca_file_enabled: false) %>') }

test "do not load ssl_ca_file and raise exception" do
Setting[:server_ca_file] = 'not-existing-file'
Setting[:ssl_ca_file] = cert_path

error = assert_raise Foreman::Exception do
subject
end

assert_includes error.message, "SSL CA file not found, check the 'Server CA file' and 'SSL CA file' in Settings > Authentication"
end
end

context "when server_ca_file and ssl_ca_file settings are blank" do
let(:source) { OpenStruct.new(content: '<%= foreman_server_ca_cert %>') }

test "do not load any files and raise exception" do
Setting[:server_ca_file] = ''
Setting[:ssl_ca_file] = ''

error = assert_raise Foreman::Renderer::Errors::UndefinedSetting do
renderer.render(source, @scope)
end

assert_includes error.message, 'Undefined setting \'"Server CA file" or "SSL CA file"\''
end
end
end

context 'renderer for template with user input used' do
let(:template) { FactoryBot.build(:provisioning_template, :template => 'service restart <%= input("service_name") -%>') }
let(:source) { Foreman::Renderer::Source::Database.new(template) }
let(:real_scope) { Foreman::Renderer::Scope::Provisioning.new(host: @host, source: source) }
let(:preview_scope) { Foreman::Renderer::Scope::Provisioning.new(host: @host, source: source, mode: Foreman::Renderer::PREVIEW_MODE) }

context 'but without input defined' do
describe 'rendering' do
let(:result) { renderer.render(source, real_scope) }
test "rendering fails and raises an error" do
e = assert_raises Foreman::Renderer::Errors::UndefinedInput do
result
end
assert_includes e.message, 'service_name'
end
end

describe 'preview' do
let(:result) { renderer.render(source, preview_scope) }
test "rendering fails and raises an error" do
e = assert_raises Foreman::Renderer::Errors::UndefinedInput do
result
end
assert_includes e.message, 'service_name'
end
end
end

context 'with input defined but not ready' do
describe 'render' do
let(:result) { renderer.render(source, real_scope) }
test "rendering fails and registers an error" do
template.template_inputs = [FactoryBot.build(:template_input, :name => 'service_name')]
template.save
e = assert_raises TemplateInput::ValueNotReady do
result
end
assert_includes e.message, 'service_name'
end
end

describe 'preview' do
let(:result) { renderer.render(source, preview_scope) }
test "rendering works using placeholder" do
template.template_inputs = [FactoryBot.build(:template_input, :name => 'service_name')]
template.save
assert_nothing_raised do
assert_equal "service restart $USER_INPUT[service_name]", result
end
end
end
end

context 'with input defined and value provided' do
let(:real_scope) { Foreman::Renderer::Scope::Provisioning.new(host: @host, source: source, template_input_values: { 'service_name' => 'httpd' }) }
let(:preview_scope) { Foreman::Renderer::Scope::Provisioning.new(host: @host, source: source, mode: Foreman::Renderer::PREVIEW_MODE, template_input_values: { 'service_name' => 'httpd' }) }

describe 'render' do
let(:result) { renderer.render(source, real_scope) }
test "rendering fails and registers an error" do
template.template_inputs = [FactoryBot.build(:template_input, :name => 'service_name')]
template.save
assert_nothing_raised do
assert_equal "service restart httpd", result
end
end
end

describe 'preview' do
let(:result) { renderer.render(source, preview_scope) }
test "rendering works using placeholder" do
template.template_inputs = [FactoryBot.build(:template_input, :name => 'service_name')]
template.save
assert_nothing_raised do
assert_equal "service restart httpd", result
end
end
end
end
end

describe 'input_resource macro' do
let(:template) { FactoryBot.build(:provisioning_template, template: "resource_id: '<%= input_resource('ress').id -%>'") }
let(:template_inputs) { [FactoryBot.build(:template_input, name: 'ress', value_type: 'resource', resource_type: 'Hostgroup')] }
let(:source) { Foreman::Renderer::Source::Database.new(template) }

let(:real_scope) { Foreman::Renderer::Scope::Provisioning.new(**scope_args) }
let(:preview_scope) { Foreman::Renderer::Scope::Provisioning.new(**scope_args, mode: Foreman::Renderer::PREVIEW_MODE) }

setup { template.update(template_inputs: template_inputs) }

context "when resource found" do
let(:scope_args) { { host: @host, source: source, template_input_values: { 'ress' => hostgroups(:common).id } } }

test "preview" do
assert_nothing_raised do
result = renderer.render(source, preview_scope)
assert_equal "resource_id: ''", result
end
end

test "render" do
assert_nothing_raised do
result = renderer.render(source, real_scope)
assert_equal "resource_id: '#{hostgroups(:common).id}'", result
end
end
end

context "when resource not found" do
let(:scope_args) { { host: @host, source: source, template_input_values: { 'ress' => 0 } } }

test "preview" do
assert_nothing_raised do
result = renderer.render(source, preview_scope)
assert_equal "resource_id: ''", result
end
end

test "render" do
assert_raises ActiveRecord::RecordNotFound do
renderer.render(source, real_scope)
end
end
end

context "when resource class is not found" do
let(:template_inputs) { [FactoryBot.build(:template_input, name: 'ress', value_type: 'resource', resource_type: 'NotExistingResource')] }
let(:scope_args) { { host: @host, source: source, template_input_values: { 'ress' => 0 } } }

test "preview" do
e = assert_raises Foreman::Renderer::Errors::UnknownResource do
renderer.render(source, preview_scope)
end
assert_includes e.message, "Unkown 'NotExistingResource' resource class"
end

test "render" do
e = assert_raises Foreman::Renderer::Errors::UnknownResource do
renderer.render(source, real_scope)
end
assert_includes e.message, "Unkown 'NotExistingResource' resource class"
end
end

context "when not authorized" do
let(:template_inputs) { [FactoryBot.build(:template_input, name: 'ress', value_type: 'resource', resource_type: 'Image')] }
let(:scope_args) { { host: @host, source: source, template_input_values: { 'ress' => images(:one).id } } }

test "preview" do
as_user(users(:one)) do
assert_nothing_raised do
result = renderer.render(source, preview_scope)
assert_equal "resource_id: ''", result
end
end
end

test "render" do
as_user(users(:one)) do
assert_raises ActiveRecord::RecordNotFound do
renderer.render(source, real_scope)
end
end
end
end

context "when value is empty" do
let(:scope_args) { { host: @host, source: source } }

test "preview" do
assert_nothing_raised do
result = renderer.render(source, preview_scope)
assert_equal "resource_id: ''", result
end
end

test "render" do
e = assert_raises TemplateInput::ValueNotReady do
renderer.render(source, real_scope)
end
assert_includes e.message, "Input 'ress' is not ready for rendering"
end
end

context "when value type != 'resource'" do
let(:template_inputs) { [FactoryBot.build(:template_input, name: 'ress')] }
let(:scope_args) { { host: @host, source: source } }

test "preview" do
assert_raises Foreman::Renderer::Errors::WrongInputValueType do
renderer.render(source, real_scope)
end
end

test "render" do
assert_raises Foreman::Renderer::Errors::WrongInputValueType do
renderer.render(source, real_scope)
end
end
end
end
end
end
(1-1/4)