diff --git a/app/models/concerns/host_params.rb b/app/models/concerns/host_params.rb index 3df2d5c7391..dfb6ee35b59 100644 --- a/app/models/concerns/host_params.rb +++ b/app/models/concerns/host_params.rb @@ -21,7 +21,11 @@ def inherited_params_hash end def non_inherited_params_hash - params_to_hash(host_parameters.authorized(:view_params)) + items = host_parameters.authorized(:view_params).to_a + # Add transient host parameters to the array + # :authorized removes records that are not saved in the db + items += host_parameters.reject(&:persisted?) if User.current.can?(:view_params) + params_to_hash(items.uniq(&:name)) end def params_to_hash(params) diff --git a/app/models/concerns/hostext/operating_system.rb b/app/models/concerns/hostext/operating_system.rb index b50b60b0d88..af3b6ca7253 100644 --- a/app/models/concerns/hostext/operating_system.rb +++ b/app/models/concerns/hostext/operating_system.rb @@ -37,10 +37,14 @@ def template_kinds(provisioning = nil) images = cr.try(:images) return [TemplateKind.friendly.find('finish')] if images.blank? - return [] if compute_attributes_empty? - uuid = compute_attributes[cr.image_param_name] - image_kind = images.find_by_uuid(uuid).try(:user_data) ? 'user_data' : 'finish' + if compute_attributes_empty? + return [] unless image + image_kind = image.try(:user_data) ? 'user_data' : 'finish' + else + uuid = compute_attributes[cr.image_param_name] + image_kind = images.find_by_uuid(uuid).try(:user_data) ? 'user_data' : 'finish' + end [TemplateKind.friendly.find(image_kind)] end diff --git a/test/controllers/hosts_controller_test.rb b/test/controllers/hosts_controller_test.rb index 139e4c01c69..2c5b91c0dd6 100644 --- a/test/controllers/hosts_controller_test.rb +++ b/test/controllers/hosts_controller_test.rb @@ -1128,13 +1128,14 @@ class Host::Valid < Host::Managed; end describe '#template_used' do setup do @host.setBuild - ActiveRecord::Base.any_instance.expects(:destroy).never - ActiveRecord::Base.any_instance.expects(:save).never @attrs = host_attributes(@host) @attrs['hostgroup_id'] = hostgroups(:common).id end test 'returns templates with interfaces' do + ActiveRecord::Base.any_instance.expects(:destroy).never + ActiveRecord::Base.any_instance.expects(:save).never + nic = FactoryBot.build(:nic_managed, :host => @host) @attrs[:interfaces_attributes] = nic.attributes.except 'updated_at', 'created_at', 'attrs' put :template_used, params: {:provisioning => 'build', :host => @attrs, :id => @host.id }, session: set_session_user, xhr: true @@ -1142,14 +1143,37 @@ class Host::Valid < Host::Managed; end assert_template :partial => '_provisioning' end - test 'returns templates with host parameters' do - @attrs[:host_parameters_attributes] = {'0' => {:name => 'foo', :value => 'bar'}} - put :template_used, params: {:provisioning => 'build', :host => @attrs }, session: set_session_user + test 'render templates with host parameters' do + template_kind = TemplateKind.find_by_name('provision') + template_with_error = FactoryBot.create :provisioning_template, + name: 'fail_without_hp_parameter', + template: "<% raise 'BOOOM' if host_param('transient-hp', '').empty? -%>", + template_kind: template_kind + os = FactoryBot.create(:operatingsystem, :with_archs, :with_os_defaults, provisioning_templates: [template_with_error]) + host = FactoryBot.create(:host, :managed, operatingsystem: os) + attrs = host_attributes(host) + + ActiveRecord::Base.any_instance.expects(:destroy).never + ActiveRecord::Base.any_instance.expects(:save).never + + put :template_used, params: {:provisioning => 'build', :host => attrs }, session: set_session_user + assert_response :success + assert_template :partial => '_provisioning' + assert response.body.include? 'Templates rendered with errors' + assert response.body.include? 'BOOOM' + + attrs[:host_parameters_attributes] = {'0' => {:name => 'transient-hp', :value => 'i-am-not-saved-in-db'}} + put :template_used, params: {:provisioning => 'build', :host => attrs }, session: set_session_user assert_response :success assert_template :partial => '_provisioning' + refute response.body.include? 'Templates rendered with errors' + refute response.body.include? 'BOOOM' end test 'shows templates for image provisioning' do + ActiveRecord::Base.any_instance.expects(:destroy).never + ActiveRecord::Base.any_instance.expects(:save).never + image = compute_resources(:one).images.first @attrs[:compute_resource_id] = compute_resources(:one).id @attrs[:operatingsystem_id] = image.operatingsystem.id diff --git a/test/controllers/userdata_controller_test.rb b/test/controllers/userdata_controller_test.rb index 8fd6c950912..a544ff61a51 100644 --- a/test/controllers/userdata_controller_test.rb +++ b/test/controllers/userdata_controller_test.rb @@ -6,7 +6,9 @@ class UserdataControllerTest < ActionController::TestCase let(:tax_location) { FactoryBot.create(:location) } let(:user_data_content) { 'template content user_data' } let(:cloud_init_content) { 'template content cloud-init' } - let(:user_data_template_kind) { FactoryBot.create(:template_kind, name: 'user_data') } + let(:user_data_template_kind) do + TemplateKind.where(name: 'user_data').first || FactoryBot.create(:template_kind, name: 'user_data') + end let(:cloud_init_template_kind) { FactoryBot.create(:template_kind, name: 'cloud-init') } let(:user_data_template) do FactoryBot.create( diff --git a/test/fixtures/template_kinds.yml b/test/fixtures/template_kinds.yml index 82da1981aa9..5f3bdc7e36e 100644 --- a/test/fixtures/template_kinds.yml +++ b/test/fixtures/template_kinds.yml @@ -38,3 +38,7 @@ registration: public: name: public description: description for public template + +user_data: + name: user_data + description: description for user_data template diff --git a/test/models/concerns/host_params_test.rb b/test/models/concerns/host_params_test.rb new file mode 100644 index 00000000000..4d1e452b34d --- /dev/null +++ b/test/models/concerns/host_params_test.rb @@ -0,0 +1,48 @@ +require 'test_helper' + +class HostParamsTest < ActiveSupport::TestCase + test 'shows global params' do + host = FactoryBot.build_stubbed(:host) + + FactoryBot.create(:common_parameter, :name => 'test_param1', :value => 'test_value1') + + assert_equal 'test_value1', host.host_params['test_param1'] + end + + test 'renders global params if template specified' do + host = FactoryBot.build_stubbed(:host) + # rubocop:disable Lint/InterpolationCheck + FactoryBot.create(:common_parameter, :name => 'test_param1', :value => '<%= "test_value1-#{@host.name}" %>') + # rubocop:enable Lint/InterpolationCheck + + assert_equal "test_value1-#{host.name}", host.host_params['test_param1'] + end + + test 'transient host parameters in host_params' do + host = FactoryBot.build(:host) + hp = FactoryBot.build(:host_parameter, name: 'transient-hp', value: 'i-am-not-saved-in-db') + host.host_parameters << hp + + assert host.host_params.key? hp.name + assert_equal hp.value, host.host_params[hp.name] + + assert host.host_params_hash.key? hp.name + assert_equal hp.value, host.host_params_hash.dig(hp.name, :value) + end + + test 'transient host params without :view_params permission' do + user_role = FactoryBot.create(:user_user_role) + + as_user user_role.owner do + host = FactoryBot.build(:host) + hp = FactoryBot.build(:host_parameter, name: 'transient-hp', value: 'i-am-not-saved-in-db') + host.host_parameters << hp + + refute host.host_params.key? hp.name + assert host.host_params.key? parameters(:common).name + + refute host.host_params_hash.key? hp.name + assert host.host_params_hash.key? parameters(:common).name + end + end +end diff --git a/test/models/concerns/hostext/operating_system_test.rb b/test/models/concerns/hostext/operating_system_test.rb index f1bfe0029e4..94da6b47b3b 100644 --- a/test/models/concerns/hostext/operating_system_test.rb +++ b/test/models/concerns/hostext/operating_system_test.rb @@ -47,6 +47,37 @@ class OperatingSystemTest < ActiveSupport::TestCase assert_equal [os_dt.provisioning_template], host.available_template_kinds('image') end + test "template_kinds returns user data kind for host without compute attributes" do + Foreman::Model::EC2.any_instance.stubs(:image_exists?).returns(true) + os_dt = FactoryBot.create(:os_default_template, + :template_kind => TemplateKind.friendly.find('finish')) + host = FactoryBot.create(:host, :on_compute_resource, + :operatingsystem => os_dt.operatingsystem) + host.image = FactoryBot.create( + :image, + :uuid => 'abcde', + :compute_resource => host.compute_resource, + :user_data => true) + actual = host.template_kinds('image') + assert_equal [TemplateKind.friendly.find('user_data')], actual + end + + test "template_kinds returns user data kind for host with compute attributes" do + Foreman::Model::EC2.any_instance.stubs(:image_exists?).returns(true) + os_dt = FactoryBot.create(:os_default_template, + :template_kind => TemplateKind.friendly.find('finish')) + host = FactoryBot.create(:host, :on_compute_resource, + :operatingsystem => os_dt.operatingsystem) + host.image = FactoryBot.create( + :image, + :uuid => 'abcde', + :compute_resource => host.compute_resource, + :user_data => true) + host.compute_attributes = {:image_id => 'abcde'} + actual = host.template_kinds('image') + assert_equal [TemplateKind.friendly.find('user_data')], actual + end + test "#render_template" do provision_template = @host.provisioning_template({:kind => "provision"}) rendered_template = @host.render_template(template: provision_template) diff --git a/test/models/host_test.rb b/test/models/host_test.rb index c72230cd12b..0773034c803 100644 --- a/test/models/host_test.rb +++ b/test/models/host_test.rb @@ -3355,24 +3355,6 @@ def to_managed! end end - describe 'HostParams module' do - test 'shows global params' do - host = FactoryBot.build_stubbed(:host) - FactoryBot.create(:common_parameter, :name => 'test_param1', :value => 'test_value1') - - assert_equal 'test_value1', host.host_params['test_param1'] - end - - test 'renders global params if template specified' do - host = FactoryBot.build_stubbed(:host) - # rubocop:disable Lint/InterpolationCheck - FactoryBot.create(:common_parameter, :name => 'test_param1', :value => '<%= "test_value1-#{@host.name}" %>') - # rubocop:enable Lint/InterpolationCheck - - assert_equal "test_value1-#{host.name}", host.host_params['test_param1'] - end - end - test "should find smart proxy ids" do host_1 = FactoryBot.create(:host, :with_tftp_orchestration) host_2 = FactoryBot.create(:host, :with_dns_orchestration) diff --git a/test/models/orchestration/compute_test.rb b/test/models/orchestration/compute_test.rb index 6428b944192..7be55dee45a 100644 --- a/test/models/orchestration/compute_test.rb +++ b/test/models/orchestration/compute_test.rb @@ -126,6 +126,7 @@ class ComputeOrchestrationTest < ActiveSupport::TestCase image = images(:one) host = FactoryBot.build_stubbed(:host, :operatingsystem => image.operatingsystem, :image => image, :compute_resource => image.compute_resource) + TemplateKind.where(name: "user_data").destroy_all # cleanup from fixtures prov_temp = FactoryBot.create(:provisioning_template, :template_kind => TemplateKind.create(:name => "user_data")) host.stubs(:provisioning_template).returns(prov_temp) attrs = {} diff --git a/test/unit/orchestration/templates_test.rb b/test/unit/orchestration/templates_test.rb index 79875bf8f80..082183b3034 100644 --- a/test/unit/orchestration/templates_test.rb +++ b/test/unit/orchestration/templates_test.rb @@ -27,4 +27,21 @@ class TemplatesTest < ActiveSupport::TestCase assert_equal 1, @queue.count refute @host.set_renderability end + + test 'with transient host parameter' do + template = FactoryBot.build :provisioning_template, + name: 'fail_without_hp_parameter', + template: "<% raise 'BOOOM' if host_param('transient-hp', '').empty? -%>" + @host.stubs(:provisioning_template).returns(template) + + @host.queue_render_checks + assert_equal 1, @queue.count + refute @host.set_renderability + + @host.clear_host_parameters_cache! + @host.host_parameters << FactoryBot.build(:host_parameter, name: 'transient-hp', value: 'i-am-not-saved-in-db') + @host.queue_render_checks + assert_equal 1, @queue.count + assert @host.set_renderability + end end