require 'test_plugin_helper'
class JobTemplateTest < ActiveSupport::TestCase
context 'when creating a template' do
let(:job_template) { FactoryBot.build(:job_template, :job_category => '') }
let(:template_with_inputs) do
FactoryBot.build(:job_template, :template => 'test').tap do |template|
template.template_inputs << FactoryBot.build(:template_input, :name => 'command', :input_type => 'user')
template.save!
end
end
it 'has a unique name' do
template1 = FactoryBot.create(:job_template)
template2 = FactoryBot.build(:job_template, :name => template1.name)
assert_not template2.valid?
end
it 'needs a job_category' do
assert_not job_template.valid?
end
it 'does not need a job_category if it is a snippet' do
job_template.snippet = true
assert job_template.valid?
end
it 'validates the inputs are uniq in the template' do
job_template.job_category = 'Miscellaneous'
job_template.foreign_input_sets << FactoryBot.build(:foreign_input_set, :target_template => template_with_inputs)
job_template.foreign_input_sets << FactoryBot.build(:foreign_input_set, :target_template => template_with_inputs)
assert_not job_template.valid?
_(job_template.errors.full_messages.first).must_include 'Duplicated inputs detected: ["command"]'
end
end
context 'description format' do
let(:template_with_description) { FactoryBot.build(:job_template, :with_description_format, :job_category => 'test job') }
let(:template) { FactoryBot.build(:job_template, :with_input, :job_category => 'test job') }
let(:minimal_template) { FactoryBot.build(:job_template) }
it 'uses the description_format attribute if set' do
_(template_with_description.generate_description_format).must_equal template_with_description.description_format
end
it 'uses the job name as description_format if not set or blank and has no inputs' do
_(minimal_template.generate_description_format).must_equal '%{template_name}'
minimal_template.description_format = ''
_(minimal_template.generate_description_format).must_equal '%{template_name}'
end
it 'generates the description_format if not set or blank and has inputs' do
input_name = template.template_inputs.first.name
expected_result = %(%{template_name} with inputs #{input_name}="%{#{input_name}}")
_(template.generate_description_format).must_equal expected_result
template.description_format = ''
_(template.generate_description_format).must_equal expected_result
end
end
context 'cloning' do
let(:job_template) { FactoryBot.build(:job_template, :with_input) }
describe '#dup' do
it 'duplicates also template inputs' do
duplicate = job_template.dup
_(duplicate).wont_equal job_template
_(duplicate.template_inputs).wont_be_empty
_(duplicate.template_inputs.first).wont_equal job_template.template_inputs.first
_(duplicate.template_inputs.first.name).must_equal job_template.template_inputs.first.name
end
end
end
context 'importing a new template' do
let(:remote_execution_feature) do
FactoryBot.create(:remote_execution_feature)
end
let(:template) do
template = <<-END_TEMPLATE
<%#
kind: job_template
name: Service Restart
job_category: Service Restart
provider_type: SSH
feature: #{remote_execution_feature.label}
template_inputs:
- name: service_name
input_type: user
required: true
- name: verbose
input_type: user
%>
service <%= input("service_name") %> restart
<%# test comment %>
END_TEMPLATE
JobTemplate.import_raw!(template, :default => true)
end
let(:template_with_input_sets) do
template_with_input_sets = <<-END_TEMPLATE
<%#
kind: job_template
name: Service Restart - Custom
job_category: Service Restart
provider_type: SSH
foreign_input_sets:
- template: #{template.name}
exclude: verbose
%>
service <%= input("service_name") %> restart
END_TEMPLATE
JobTemplate.import_raw!(template_with_input_sets, :default => true)
end
it 'sets the name' do
_(template.name).must_equal 'Service Restart'
end
it 'has a template' do
_(template.template.squish).must_equal 'service <%= input("service_name") %> restart <%# test comment %>'
end
it 'imports inputs' do
_(template.template_inputs.first.name).must_equal 'service_name'
end
it 'imports input sets' do
_(template_with_input_sets.foreign_input_sets.first.target_template).must_equal template
_(template_with_input_sets.template_inputs_with_foreign.map(&:name)).must_equal ['service_name']
end
it 'imports feature' do
template # let is lazy
remote_execution_feature.reload
_(remote_execution_feature.job_template).must_equal template
end
it 'sets additional options' do
_(template.default).must_equal true
end
end
context 'importing an existing template' do
let(:included) do
template = <<-END_TEMPLATE
<%#
kind: job_template
name: Banner
job_category: Commands
provider_type: SSH
template_inputs:
- name: banner_message
input_type: user
required: true
%>
echo input(:banner_message)
END_TEMPLATE
JobTemplate.import_raw!(template, :default => true)
end
let(:existing) do
template = <<-END_TEMPLATE
<%#
kind: job_template
name: Ping a Thing
job_category: Commands
provider_type: SSH
template_inputs:
- name: hostname
input_type: user
options: "www.google.com"
required: true
foreign_input_sets:
- template: #{included.name}
%>
ping -c 5 <%= input("hostname") %>
END_TEMPLATE
JobTemplate.import_raw!(template, :default => true)
end
let(:updated) do
<<-END_TEMPLATE
<%#
kind: job_template
name: Ping a Thing
job_category: Commands
provider_type: SSH
template_inputs:
- name: hostname
input_type: user
options: 'www.redhat.com'
required: true
- name: count
input_type: user
required: true
foreign_input_sets:
- template: #{included.name}
exclude: banner_message
%>
ping -c <%= input('count') %> <%= input('hostname') %>
END_TEMPLATE
end
it 'will not overwrite by default' do
existing
assert_not JobTemplate.import_raw!(updated)
end
let(:synced_template) do
existing
JobTemplate.import_raw!(updated, :update => true)
existing.reload
end
it 'syncs inputs' do
hostname = synced_template.template_inputs.find { |input| input.name == 'hostname' }
_(hostname.options).must_equal 'www.redhat.com'
end
it 'syncs content' do
_(synced_template.template).must_match(/ping -c <%= input\('count'\) %> <%= input\('hostname'\) %>/m)
end
it 'syncs input sets' do
_(synced_template.foreign_input_sets.first.target_template).must_equal included
_(synced_template.template_inputs_with_foreign.map(&:name)).must_equal ['hostname', 'count']
end
end
context 'template export' do
let(:exportable_template) do
FactoryBot.create(:job_template, :with_input)
end
let(:erb) do
exportable_template.to_erb
end
it 'exports name' do
_(erb).must_match(/^name: #{exportable_template.name}$/)
end
it 'includes template inputs' do
_(erb).must_match(/^template_inputs:$/)
end
it 'includes template contents' do
_(erb).must_include exportable_template.template
end
it 'is importable' do
erb
old_name = exportable_template.name
exportable_template.update(:name => "#{old_name}_renamed")
imported = JobTemplate.import_raw!(erb)
_(imported.name).must_equal old_name
_(imported.template_inputs.first.to_export).must_equal exportable_template.template_inputs.first.to_export
end
it 'has taxonomies in metadata' do
assert_equal 'Organization 1', exportable_template.to_export["organizations"].first
assert_equal 'Location 1', exportable_template.to_export["locations"].first
end
end
context 'there is existing template invocation of a job template' do
let(:job_invocation) { FactoryBot.create(:job_invocation, :with_template) }
let(:job_template) { job_invocation.pattern_template_invocations.first.template }
describe 'job template deletion' do
it 'succeeds' do
_(job_template.pattern_template_invocations).wont_be_empty
assert job_template.destroy
end
end
end
context 'template locked' do
it 'inputs cannot be changed' do
job_template = FactoryBot.create(:job_template, :with_input, :locked => true)
Foreman.expects(:in_rake?).returns(false).at_least_once
assert_valid job_template
job_template.template_inputs.first.name = 'something else'
refute_valid job_template
end
end
context 'rendering' do
it 'renders nested template as a non-admin user' do
inner = FactoryBot.create(:job_template)
template_invocation = FactoryBot.create(:template_invocation)
template_invocation.template.template = "<%= render_template('#{inner.name}') %>"
template_invocation.template.save!
setup_user('view', 'job_templates')
renderer = InputTemplateRenderer.new template_invocation.template,
template_invocation.host,
template_invocation
result = renderer.render
_(result).must_equal "#{inner.template}"
end
end
end