Revision 404ead2a
Added by Marek Hulán over 7 years ago
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
Fixes #17403 - enable exporting of templates