Project

General

Profile

« Previous | Next » 

Revision 404ead2a

Added by Marek Hulán over 7 years ago

Fixes #17403 - enable exporting of templates

View differences:

app/controllers/api/v2/provisioning_templates_controller.rb
include Foreman::Controller::Parameters::ProvisioningTemplate
before_action :find_optional_nested_object
before_action :find_resource, :only => %w{show update destroy clone}
before_action :find_resource, :only => %w{show update destroy clone export}
before_action :handle_template_upload, :only => [:create, :update]
before_action :process_template_kind, :only => [:create, :update]
......
end
end
api :GET, '/provisioning_templates/:id/export', N_('Export a provisioning template to ERB')
param :id, :identifier, :required => true
def export
send_data @provisioning_template.to_erb, :type => 'text/plain', :disposition => 'attachment', :filename => @provisioning_template.filename
end
private
def resource_class
......
case params[:action]
when 'clone'
'create'
when 'export'
'view'
else
super
end
app/controllers/api/v2/ptables_controller.rb
wrap_parameters :ptable, :include => ptable_params_filter.accessible_attributes(parameter_filter_context)
before_action :find_optional_nested_object
before_action :find_resource, :only => %w{show update destroy clone}
before_action :find_resource, :only => %w{show update destroy clone export}
api :GET, "/ptables/", N_("List all partition tables")
api :GET, "/operatingsystems/:operatingsystem_id/ptables", N_("List all partition tables for an operating system")
......
process_response @ptable.save
end
api :GET, '/ptables/:id/export', N_('Export a partition template to ERB')
param :id, :identifier, :required => true
def export
send_data @ptable.to_erb, :type => 'text/plain', :disposition => 'attachment', :filename => @ptable.filename
end
private
def load_vars_from_ptable
......
case params[:action]
when 'clone'
'create'
when 'export'
'view'
else
super
end
app/controllers/templates_controller.rb
include Foreman::Controller::AutoCompleteSearch
before_action :handle_template_upload, :only => [:create, :update]
before_action :find_resource, :only => [:edit, :update, :destroy, :clone_template, :lock, :unlock]
before_action :find_resource, :only => [:edit, :update, :destroy, :clone_template, :lock, :unlock, :export]
before_action :load_history, :only => :edit
before_action :type_name_plural, :type_name_singular, :resource_class
......
safe_render(@template)
end
def export
send_data @template.to_erb, :type => 'text/plain', :disposition => 'attachment', :filename => @template.filename
end
private
def safe_render(template)
......
case params[:action]
when 'lock', 'unlock'
:lock
when 'clone_template', 'preview'
when 'clone_template', 'preview', 'export'
:view
else
super
app/helpers/provisioning_templates_helper.rb
end
def permitted_actions(template)
actions = [display_link_if_authorized(_('Clone'), template_hash_for_member(template, 'clone_template'))]
actions = [
display_link_if_authorized(_('Clone'), template_hash_for_member(template, 'clone_template')),
display_link_if_authorized(_('Export'), template_hash_for_member(template, 'export'), { :data => { :no_turbolink => true } })
]
if template.locked?
confirm = [
app/models/provisioning_template.rb
scoped_search :in => :hostgroups, :on => :name, :rename => :hostgroup, :complete_value => true
scoped_search :in => :template_kind, :on => :name, :rename => :kind, :complete_value => true
attr_exportable :kind => Proc.new { |template| template.template_kind.try(:name) },
:oses => Proc.new { |template| template.operatingsystems.map(&:name).uniq }
# Override method in Taxonomix as Template is not used attached to a Host,
# and matching a Host does not prevent removing a template from its taxonomy.
def used_taxonomy_ids(type)
app/models/ptable.rb
alias_attribute :layout, :template
attr_exportable :os_family
# with proc support, default_scope can no longer be chained
# include all default scoping here
default_scope lambda {
app/models/template.rb
class Template < ActiveRecord::Base
include Exportable
validates_lengths_from_database
validates :name, :presence => true
......
before_save :remove_trailing_chars
attr_exportable :name, :snippet
class Jail < Safemode::Jail
allow :name
end
......
Host.authorized(:view_hosts).order(:name).limit(100)
end
def metadata
"<%#\n#{to_export(false).to_yaml.sub(/\A---$/, '').strip}\n%>\n"
end
def to_erb
if self.template.start_with?('<%#')
metadata + template_without_metadata
else
lines = template_without_metadata.split("\n")
[ lines[0], metadata, lines[1..-1] ].flatten.join("\n")
end
end
def template_without_metadata
# Regexp like /.../m includes \n in .
template.sub(/^<%#\n.*?name.*?%>$\n?/m, '')
end
def filename
name.downcase.delete('-').gsub(/\s+/, '_') + '.erb'
end
private
def allowed_changes
app/services/foreman/access_permissions.rb
end
permission_set.security_block :provisioning_templates do |map|
map.permission :view_provisioning_templates, {:provisioning_templates => [:index, :show, :revision, :auto_complete_search, :preview],
map.permission :view_provisioning_templates, {:provisioning_templates => [:index, :show, :revision, :auto_complete_search, :preview, :export],
:"api/v1/config_templates" => [:index, :show, :revision],
:"api/v2/config_templates" => [:index, :show, :revision],
:"api/v2/provisioning_templates" => [:index, :show, :revision],
:"api/v2/provisioning_templates" => [:index, :show, :revision, :export],
:"api/v2/template_combinations" => [:index, :show],
:"api/v1/template_kinds" => [:index],
:"api/v2/template_kinds" => [:index]
......
end
permission_set.security_block :partition_tables do |map|
map.permission :view_ptables, {:ptables => [:index, :show, :auto_complete_search, :revision, :preview, :welcome],
map.permission :view_ptables, {:ptables => [:index, :show, :auto_complete_search, :revision, :preview, :welcome, :export],
:"api/v1/ptables" => [:index, :show],
:"api/v2/ptables" => [:index, :show, :revision]
:"api/v2/ptables" => [:index, :show, :revision, :export]
}
map.permission :create_ptables, {:ptables => [:new, :create, :clone_template],
:"api/v1/ptables" => [:create],
config/routes.rb
get 'clone_template'
get 'lock'
get 'unlock'
get 'export'
post 'preview'
end
collection do
......
get 'clone_template'
get 'lock'
get 'unlock'
get 'export'
post 'preview'
end
collection do
config/routes/api/v2.rb
resources :provisioning_templates, :except => [:new, :edit] do
(resources :locations, :only => [:index, :show]) if SETTINGS[:locations_enabled]
(resources :organizations, :only => [:index, :show]) if SETTINGS[:organizations_enabled]
post :clone, :on => :member
member do
post :clone
get :export
end
collection do
post 'build_pxe_default'
get 'revision'
......
resources :ptables, :except => [:new, :edit] do
(resources :locations, :only => [:index, :show]) if SETTINGS[:locations_enabled]
(resources :organizations, :only => [:index, :show]) if SETTINGS[:organizations_enabled]
post :clone, :on => :member
member do
post :clone
get :export
end
collection do
get 'revision'
end
test/controllers/api/v2/provisioning_templates_controller_test.rb
assert_response :unprocessable_entity
end
test 'export should export the erb of the template' do
get :export, { :id => templates(:pxekickstart).to_param }
assert_response :success
assert_equal 'text/plain', response.content_type
assert_equal templates(:pxekickstart).to_erb, response.body
assert_equal 'attachment; filename="centos5_3_pxelinux.erb"', response.headers['Content-Disposition']
end
test "should show templates from os" do
get :index, { :operatingsystem_id => operatingsystems(:centos5_3).fullname }
assert_response :success
test/controllers/api/v2/ptables_controller_test.rb
assert_equal(template['template'], original_ptable.template)
end
test 'export should export the erb of the template' do
ptable = FactoryGirl.create(:ptable)
get :export, { :id => ptable.to_param }
assert_response :success
assert_equal 'text/plain', response.content_type
assert_equal ptable.to_erb, response.body
end
test 'clone name should not be blank' do
post :clone, { :id => FactoryGirl.create(:ptable).to_param,
:ptable => {:name => ''} }
test/controllers/provisioning_templates_controller_test.rb
assert_template 'new'
end
test "export" do
get :export, { :id => templates(:pxekickstart).to_param }, set_session_user
assert_response :success
assert_equal 'text/plain', response.content_type
assert_equal templates(:pxekickstart).to_erb, response.body
assert_equal 'attachment; filename="centos5_3_pxelinux.erb"', response.headers['Content-Disposition']
end
test "update invalid" do
ProvisioningTemplate.any_instance.stubs(:valid?).returns(false)
put :update, {:id => templates(:pxekickstart).to_param, :provisioning_template => {:name => "123"} }, set_session_user
test/controllers/ptables_controller_test.rb
assert !Ptable.exists?(ptable.id)
end
test "export" do
get :export, { :id => @ptable.to_param }, set_session_user
assert_response :success
assert_equal 'text/plain', response.content_type
assert_equal @ptable.to_erb, response.body
end
def setup_view_user
@request.session[:user] = users(:one).id
users(:one).roles = [Role.default, Role.find_by_name('Viewer')]
test/models/provisioning_template_test.rb
TemplatesController.any_instance.expects(:render_safe).with(anything, includes(*Foreman::Renderer::ALLOWED_GENERIC_HELPERS), anything).returns(true)
ProvisioningTemplate.build_pxe_default(TemplatesController.new)
end
test "#metadata should include OSes and kind" do
template = FactoryGirl.build(:provisioning_template, :operatingsystems => [
FactoryGirl.create(:operatingsystem, :name => 'CentOS'),
FactoryGirl.create(:operatingsystem, :name => 'CentOS'),
FactoryGirl.create(:operatingsystem, :name => 'Fedora')])
lines = template.metadata.split("\n")
assert_includes lines, '- CentOS'
assert_includes lines, '- Fedora'
assert_equal 1, lines.select { |l| l == '- CentOS' }.size
assert_includes lines, "kind: #{template.template_kind.name}"
assert_includes lines, "name: #{template.name}"
end
end
end
test/models/ptable_test.rb
Host.expects(:authorized).with(:view_hosts).returns(Host.where(nil))
ptable.preview_host_collection
end
test "#metadata should include OS family" do
ptable = FactoryGirl.build(:ptable)
lines = ptable.metadata.split("\n")
assert_includes lines, "os_family: #{ptable.os_family}"
assert_includes lines, "name: #{ptable.name}"
end
end
test/models/template_test.rb
require 'test_helper'
class TemplateTest < ActiveSupport::TestCase
describe "generating metadata" do
setup do
@template = Template.new :name => 'Name of template'
end
test "metadata are placed in erb comment" do
assert_match /\A<%#(\n|.)*%>/, @template.metadata
end
test "metadata contains name unchanged" do
assert_match /^name: Name of template$/, @template.metadata
end
test "metadata skips blank attributes" do
@template.name = ''
refute_match /^name:&/, @template.metadata
end
test "metadata does not contain dashes prefix" do
refute_includes @template.metadata, '---'
end
end
describe "stripping metadata" do
setup do
content = "<%#
name: basic
%>
few
lines
below"
@template = Template.new :name => 'basic', :template => content
end
test "metadata are stripped from the beginning" do
without = @template.template_without_metadata
refute_includes without, '<%#'
end
test "silent metadata are stripped too" do
@template.template.gsub('%>', '-%>')
without = @template.template_without_metadata
refute_includes without, '<%#'
end
test "metadata are stripped from the middle" do
@template.template = "<%#\another comment\n%>\nsome\ndata\n" + @template.template
without = @template.template_without_metadata
refute_includes without, 'name: basic'
end
test "other erb comments not containing name: are preserved" do
@template.template = "prefix\n<% another erb tag %>\nsome\ndata\n" + @template.template
without = @template.template_without_metadata
assert_includes without, "prefix"
assert_includes without, "<% another erb tag %>"
assert_includes without, "\nsome\ndata\n"
assert_includes without, "\nfew\nlines\nbelow"
end
test "metadata are detected by name attribute on any comment line" do
lines = @template.template.lines
@template.template = [ lines[0], 'another: comment', lines[1..-1] ].flatten.join("\n")
without = @template.template_without_metadata
refute_includes without, 'name: basic'
end
end
describe "#filename" do
setup do
@template = Template.new
end
test "filename adds erb suffix" do
@template.name = 'a'
assert_equal 'a.erb', @template.filename
end
test "filename replaces spaces to underscores" do
@template.name = 'a bc d'
assert_equal 'a_bc_d.erb', @template.filename
end
test "filename removes dashes" do
@template.name = 'a-bc-d'
assert_equal 'abcd.erb', @template.filename
end
end
describe "#to_erb" do
setup do
content = "<%#
name: basic
%>
data"
@template = Template.new :name => 'basic', :template => content
end
test "it generates fresh fresh metadata and replaces original ones" do
@template.stub(:metadata, "METADATA\n") do
assert_equal "METADATA\ndata", @template.to_erb
end
end
test "it keeps data that present before original metadata" do
@template.template = "<?xml ...>\n" + @template.template
@template.stub(:metadata, "METADATA") do
assert_equal "<?xml ...>\nMETADATA\ndata", @template.to_erb
end
end
end
end

Also available in: Unified diff