foreman_git_templates 1.0.1 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9c38324b0492c54b19ee28e823d91e8f18b6d1427f477710e6516544115b7b1a
4
- data.tar.gz: 1317ddbf95b8fb0b3601494828e3a6658bdad95a1b656b567edf7617a17378f7
3
+ metadata.gz: 030b1cb7373a31b3b7a72326668906b00d523c5c92a0a62e41d2467570aa9d8e
4
+ data.tar.gz: 0b27bc9ebb34b8b288234b366a6d1ac431eb0413d883e08ba605a9d419f2660a
5
5
  SHA512:
6
- metadata.gz: a47d11977a3bbf7a2b86d409ae75a42045c932a96191aa0c4384890171d071588aa26682ef5e75ba889bd64f119ec9ab039d9940a06c524adb9b8d0735d86566
7
- data.tar.gz: '054158b459f6a48992f170a3f6f39e54d500a18aef4d4eab1b2c151901cc3ca1e449b2c1cc13cc1ac2d87b09ac464ae08d81817a550cbd0d471931594f69933a'
6
+ metadata.gz: b1fcc6b0035e91332f0600389db9445ca00c201c534ec19c26e2b55e0f2e33f23df73d0904b0256bdd81b7cf8b77903a3c17480aeb47174931c70efe11065b3e
7
+ data.tar.gz: 6ef071e866eeca0076167ab6f04a780cd3b4c46b88bec95cb241a8fb91cc193e64e01aafd65c79d5c813ed59480f742a836675be62a50eb0621318db026e773d
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanGitTemplates
4
+ module UnattendedControllerExtensions
5
+ extend ActiveSupport::Concern
6
+
7
+ module Overrides
8
+ def render_local_boot_template
9
+ return super unless @host&.repository_path
10
+
11
+ return unless verify_found_host
12
+
13
+ template = ForemanGitTemplates::DefaultLocalBootRepositoryTemplate.new(name: 'iPXE')
14
+ safe_render(template)
15
+ rescue ForemanGitTemplates::RepositoryReader::MissingFileError
16
+ render_ipxe_message(message: _('iPXE default local boot template not found in repository at templates/iPXE/default_local_boot.erb'))
17
+ end
18
+ end
19
+
20
+ included do
21
+ prepend Overrides
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanGitTemplates
4
+ module ApplicationHelper
5
+ extend ActiveSupport::Concern
6
+
7
+ module Overrides
8
+ def display_link_if_authorized(name, options = {}, html_options = {})
9
+ # rubocop:disable Rails/HelperInstanceVariable
10
+
11
+ return if @host&.repository_path && options[:use_route] == 'edit_provisioning_template'
12
+
13
+ # rubocop:enable Rails/HelperInstanceVariable
14
+
15
+ super
16
+ end
17
+ end
18
+
19
+ included do
20
+ prepend Overrides
21
+ end
22
+ end
23
+ end
@@ -2,10 +2,16 @@
2
2
 
3
3
  module ForemanGitTemplates
4
4
  module Renderer
5
- def get_source(klass: Foreman::Renderer::Source::Database, template:, **args)
5
+ REPOSITORY_SOURCE_CLASS = ForemanGitTemplates::Renderer::Source::Repository
6
+
7
+ def get_source(klass: nil, template:, **args)
8
+ return super if klass && klass != REPOSITORY_SOURCE_CLASS
9
+
6
10
  repository_path = repository_path(args[:host])
7
11
  if repository_path
8
- ForemanGitTemplates::Renderer::Source::Repository.new(template, repository_path)
12
+ REPOSITORY_SOURCE_CLASS.new(template, repository_path)
13
+ elsif !repository_path && Gem::Version.new(SETTINGS[:version].version) < Gem::Version.new('1.23')
14
+ super(klass: klass || Foreman::Renderer::Source::Database, template: template, **args)
9
15
  else
10
16
  super
11
17
  end
@@ -2,10 +2,35 @@
2
2
 
3
3
  module ForemanGitTemplates
4
4
  module HostExtensions
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ validates_associated :host_parameters
9
+ end
10
+
11
+ def repository_klass
12
+ build? ? MainRepositoryTemplate : DefaultLocalBootRepositoryTemplate
13
+ end
14
+
5
15
  def repository_path
6
- return unless host_params['template_url']
16
+ return unless git_template_url
17
+
18
+ git_template_tmpfile&.path
19
+ end
20
+
21
+ private
22
+
23
+ def git_template_url
24
+ @git_template_url ||= host_params['template_url']
25
+ end
26
+
27
+ def git_template_tmpfile
28
+ return unless git_template_url
7
29
 
8
- @repository_path ||= RepositoryFetcher.call(host_params['template_url'])
30
+ @git_template_tmpfile ||= RepositoryFetcher.call(git_template_url)
31
+ rescue ::ForemanGitTemplates::RepositoryFetcher::RepositoryFetcherError => e
32
+ Foreman::Logging.exception("GitTemplates: Failed to fetch data from #{git_template_url}", e)
33
+ nil
9
34
  end
10
35
  end
11
36
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ForemanGitTemplates
4
+ module HostParameterExtensions
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ validate :template_url_is_reachable, if: ->(p) { p.name == 'template_url' }
9
+ end
10
+
11
+ private
12
+
13
+ def template_url_is_reachable
14
+ RestClient::Request.execute(method: :head, url: value, timeout: Setting::GitTemplates['template_url_validation_timeout'])
15
+ rescue RestClient::ExceptionWithResponse, URI::InvalidURIError, SocketError => e
16
+ errors.add(:value, _('Cannot fetch templates from %{url}: %{error}') % { url: value, error: e.message })
17
+ end
18
+ end
19
+ end
@@ -17,8 +17,8 @@ module ForemanGitTemplates
17
17
  return super unless repository_path
18
18
 
19
19
  @available_template_kinds ||= template_kinds(provisioning).map do |kind|
20
- MainRepositoryTemplate.new(name: kind.name).tap do |template|
21
- RepositoryReader.call(repository_path, template.path)
20
+ repository_klass.new(name: kind.name).tap do |t|
21
+ t.template = RepositoryReader.call(repository_path, t.path)
22
22
  end
23
23
  rescue RepositoryReader::FileUnreadableError # file is missing or empty
24
24
  next
@@ -9,16 +9,33 @@ module ForemanGitTemplates
9
9
  delegate :render_template, to: :host
10
10
 
11
11
  def generate_pxe_template(kind)
12
- return super unless host.repository_path
12
+ return super unless host.params['template_url']
13
13
 
14
- template_klass = build? ? MainRepositoryTemplate : DefaultLocalBootRepositoryTemplate
15
- template = template_klass.new(name: kind)
14
+ template = host.repository_klass.new(name: kind)
16
15
  render_template(template: template)
17
- rescue ForemanGitTemplates::RepositoryReader::MissingFileError => e
18
- # re-raise the exception if we have a main template defined for this type
19
- raise e if host.available_template_kinds.map(&:name).include?(kind)
16
+ rescue ForemanGitTemplates::RepositoryReader::MissingFileError
20
17
  nil
21
18
  end
19
+
20
+ private
21
+
22
+ def validate_tftp
23
+ return super unless feasible_for_git_template_rendering?
24
+ return unless tftp? || tftp6?
25
+ return unless host.operatingsystem
26
+
27
+ pxe_kind = host.operatingsystem.pxe_loader_kind(host)
28
+ return unless pxe_kind && host.provisioning_template(kind: pxe_kind).nil?
29
+
30
+ failure _('No %{kind} template was found for host %{host}. Repository url: %{url}') % { kind: pxe_kind, host: host.name, url: host.params['template_url'] }
31
+ end
32
+
33
+ def feasible_for_git_template_rendering?
34
+ return false unless host.is_a?(Host::Managed)
35
+ return false unless host.params['template_url']
36
+
37
+ true
38
+ end
22
39
  end
23
40
 
24
41
  included do
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Setting
4
+ class GitTemplates < ::Setting
5
+ def self.default_settings
6
+ [
7
+ set('template_url_validation_timeout', N_('Template URL validation timeout in seconds'), 15, N_('Template URL validation timeout'))
8
+ ]
9
+ end
10
+
11
+ def self.load_defaults
12
+ # Check the table exists
13
+ return unless super
14
+
15
+ transaction do
16
+ default_settings.each { |s| create! s.update(category: 'Setting::GitTemplates') }
17
+ end
18
+
19
+ true
20
+ end
21
+
22
+ def self.humanized_category
23
+ N_('GitTemplates')
24
+ end
25
+ end
26
+ end
@@ -9,7 +9,7 @@ module ForemanGitTemplates
9
9
  end
10
10
 
11
11
  def call
12
- Down.download(repository_url).path
12
+ Down.download(repository_url)
13
13
  rescue Down::ResponseError => e
14
14
  raise RepositoryFetcherError, "Cannot fetch repository from #{repository_url}. Response code: #{e.response.code}"
15
15
  rescue Down::Error => e
@@ -9,6 +9,7 @@ module ForemanGitTemplates
9
9
 
10
10
  def call
11
11
  raise MissingFileError, "The #{file} file is missing" if content.nil?
12
+
12
13
  content
13
14
  end
14
15
 
@@ -30,13 +31,15 @@ module ForemanGitTemplates
30
31
  @content ||= Tar.untar(repository_path) do |tar|
31
32
  return tar.each do |entry|
32
33
  next unless entry.file? && entry.full_name.end_with?(file)
34
+
33
35
  break entry.read.tap do |entry_content|
34
36
  raise EmptyFileError, "The #{file} file is empty" if entry_content.nil?
35
37
  end
36
38
  end
37
39
  end
38
- rescue Errno::ENOENT
39
- raise RepositoryUnreadableError, "Cannot read repository from #{repository_path}"
40
+ rescue Errno::ENOENT, Zlib::GzipFile::Error => e
41
+ Foreman::Logging.exception("GitTemplates: Cannot read repository from #{repository_path}", e)
42
+ raise RepositoryUnreadableError, _('Cannot read repository from %{repository_path}: %{error}') % { repository_path: repository_path, error: e.message }
40
43
  end
41
44
  end
42
45
  end
@@ -6,6 +6,15 @@ module ForemanGitTemplates
6
6
 
7
7
  config.autoload_paths += Dir["#{config.root}/app/lib"]
8
8
  config.autoload_paths += Dir["#{config.root}/app/services"]
9
+ config.autoload_paths += Dir["#{config.root}/app/controllers/concerns"]
10
+
11
+ initializer 'foreman_git_templates.load_default_settings', before: :load_config_initializers do
12
+ require_dependency File.expand_path('../../app/models/setting/git_templates.rb', __dir__) if begin
13
+ Setting.table_exists?
14
+ rescue StandardError
15
+ (false)
16
+ end
17
+ end
9
18
 
10
19
  initializer 'foreman_git_templates.register_plugin', before: :finisher_hook do |_app|
11
20
  Foreman::Plugin.register :foreman_git_templates do
@@ -18,7 +27,10 @@ module ForemanGitTemplates
18
27
  Foreman::Renderer.singleton_class.prepend(ForemanGitTemplates::Renderer)
19
28
  Host::Managed.include(ForemanGitTemplates::Hostext::OperatingSystem)
20
29
  Host::Managed.include(ForemanGitTemplates::HostExtensions)
30
+ HostParameter.include(ForemanGitTemplates::HostParameterExtensions)
21
31
  Nic::Managed.include(ForemanGitTemplates::Orchestration::TFTP)
32
+ UnattendedController.include(ForemanGitTemplates::UnattendedControllerExtensions)
33
+ ::ApplicationHelper.include(ForemanGitTemplates::ApplicationHelper)
22
34
  rescue StandardError => e
23
35
  Rails.logger.warn "ForemanGitTemplates: skipping engine hook (#{e})"
24
36
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ForemanGitTemplates
4
- VERSION = '1.0.1'
4
+ VERSION = '1.0.6'
5
5
  end
@@ -2,46 +2,19 @@
2
2
 
3
3
  require 'rake/testtask'
4
4
 
5
- # Tasks
6
- namespace :foreman_git_templates do
7
- namespace :example do
8
- desc 'Example Task'
9
- task task: :environment do
10
- # Task goes here
11
- end
12
- end
13
- end
14
-
15
5
  # Tests
16
6
  namespace :test do
17
7
  desc 'Test ForemanGitTemplates'
18
8
  Rake::TestTask.new(:foreman_git_templates) do |t|
19
- test_dir = File.join(File.dirname(__FILE__), '../..', 'test')
9
+ test_dir = File.join(ForemanGitTemplates::Engine.root, 'test')
20
10
  t.libs << ['test', test_dir]
21
- t.pattern = "#{test_dir}/**/*_test.rb"
11
+ t.pattern = File.join(test_dir, '**', '*_test.rb')
22
12
  t.verbose = true
23
13
  t.warning = false
24
14
  end
25
15
  end
26
16
 
27
- namespace :foreman_git_templates do
28
- task :rubocop do
29
- begin
30
- require 'rubocop/rake_task'
31
- RuboCop::RakeTask.new(:rubocop_foreman_git_templates) do |task|
32
- task.patterns = ["#{ForemanGitTemplates::Engine.root}/app/**/*.rb",
33
- "#{ForemanGitTemplates::Engine.root}/lib/**/*.rb",
34
- "#{ForemanGitTemplates::Engine.root}/test/**/*.rb"]
35
- end
36
- rescue StandardError
37
- puts 'Rubocop not loaded.'
38
- end
39
-
40
- Rake::Task['rubocop_foreman_git_templates'].invoke
41
- end
42
- end
43
-
44
17
  Rake::Task[:test].enhance ['test:foreman_git_templates']
45
18
 
46
19
  load 'tasks/jenkins.rake'
47
- Rake::Task['jenkins:unit'].enhance ['test:foreman_git_templates', 'foreman_git_templates:rubocop'] if Rake::Task.task_defined?(:'jenkins:unit')
20
+ Rake::Task['jenkins:unit'].enhance ['test:foreman_git_templates'] if Rake::Task.task_defined?(:'jenkins:unit')
@@ -3,7 +3,7 @@
3
3
  require 'test_plugin_helper'
4
4
 
5
5
  class HostsControllerTest < ActionController::TestCase
6
- let(:host) { FactoryBot.create(:host, :managed, :with_template_url) }
6
+ let(:host) { FactoryBot.create(:host, :managed, :with_template_url, build: true) }
7
7
 
8
8
  describe '#templates' do
9
9
  it 'returns only templates that are defined in the archive' do
@@ -3,9 +3,9 @@
3
3
  require 'test_plugin_helper'
4
4
 
5
5
  class UnattendedControllerTest < ActionController::TestCase
6
- let(:os) { FactoryBot.create(:operatingsystem, :with_archs, :with_ptables, type: 'Redhat') }
6
+ let(:os) { FactoryBot.create(:operatingsystem, :with_associations, type: 'Redhat') }
7
7
  let(:host) do
8
- FactoryBot.create(:host, :managed, :with_template_url, operatingsystem: os, ptable: os.ptables.first)
8
+ FactoryBot.create(:host, :managed, :with_template_url, build: true, operatingsystem: os, ptable: os.ptables.first)
9
9
  end
10
10
 
11
11
  test 'should render template from repository' do
@@ -68,4 +68,53 @@ class UnattendedControllerTest < ActionController::TestCase
68
68
  assert_equal 'foo bar', response.body.strip
69
69
  end
70
70
  end
71
+
72
+ describe 'iPXE templates' do
73
+ let(:host) do
74
+ FactoryBot.create(:host, :managed, :with_template_url, build: false, operatingsystem: os, ptable: os.ptables.first)
75
+ end
76
+
77
+ context 'host not in build mode' do
78
+ test 'should render iPXE local boot template from repository' do
79
+ assert_not_nil host.params['template_url']
80
+
81
+ Dir.mktmpdir do |dir|
82
+ kind = 'iPXE'
83
+
84
+ stub_repository host.params['template_url'], "#{dir}/repo.tar.gz" do |tar|
85
+ tar.add_file_simple("templates/#{kind}/default_local_boot.erb", 644, 5) { |io| io.write('local') }
86
+ tar.add_file_simple("templates/#{kind}/template.erb", 644, host.name.length) { |io| io.write(host.name) }
87
+ end
88
+
89
+ get :host_template, params: { kind: kind, hostname: host.name }, session: set_session_user
90
+ assert_response :success
91
+ assert_equal 'local', response.body.strip
92
+ end
93
+ end
94
+ end
95
+
96
+ context 'host in build mode' do
97
+ setup do
98
+ host.update!(build: true)
99
+ end
100
+
101
+ test 'should render iPXE template from repository' do
102
+ host.reload
103
+ assert_not_nil host.params['template_url']
104
+
105
+ Dir.mktmpdir do |dir|
106
+ kind = 'iPXE'
107
+
108
+ stub_repository host.params['template_url'], "#{dir}/repo.tar.gz" do |tar|
109
+ tar.add_file_simple("templates/#{kind}/default_local_boot.erb", 644, 5) { |io| io.write('local') }
110
+ tar.add_file_simple("templates/#{kind}/template.erb", 644, host.name.length) { |io| io.write(host.name) }
111
+ end
112
+
113
+ get :host_template, params: { kind: kind, hostname: host.name }, session: set_session_user
114
+ assert_response :success
115
+ assert_equal host.name, response.body.strip
116
+ end
117
+ end
118
+ end
119
+ end
71
120
  end
@@ -4,7 +4,9 @@ FactoryBot.modify do
4
4
  factory :host do
5
5
  trait :with_template_url do
6
6
  after(:create) do |host, _evaluator|
7
- FactoryBot.create(:host_parameter, host: host, name: 'template_url', value: 'http://www.api.com/repository.tar.gz')
7
+ url = 'http://www.api.com/repository.tar.gz'
8
+ WebMock::API.stub_request(:head, url).to_return(status: 200)
9
+ FactoryBot.create(:host_parameter, host: host, name: 'template_url', value: url)
8
10
  end
9
11
  end
10
12
  end
@@ -4,7 +4,7 @@ require 'test_plugin_helper'
4
4
 
5
5
  module Hostext
6
6
  class OperatingSystemTest < ActiveSupport::TestCase
7
- let(:host) { FactoryBot.create(:host, :managed, :with_template_url) }
7
+ let(:host) { FactoryBot.create(:host, :managed, :with_template_url, build: true) }
8
8
 
9
9
  describe '#provisioning_template' do
10
10
  it 'finds all PXELinux template kinds' do
@@ -13,7 +13,9 @@ module Hostext
13
13
  tar.add_file_simple('templates/PXELinux/template.erb', 644, host.name.length) { |io| io.write(host.name) }
14
14
  end
15
15
 
16
- assert_equal 'PXELinux', host.provisioning_template(kind: 'PXELinux')&.name
16
+ actual = host.provisioning_template(kind: 'PXELinux')
17
+ assert_equal 'PXELinux', actual.name
18
+ assert_equal host.name, actual.template
17
19
  end
18
20
  end
19
21
 
@@ -23,7 +25,9 @@ module Hostext
23
25
  tar.add_file_simple('templates/PXELinux/template.erb', 644, host.name.length) { |io| io.write(host.name) }
24
26
  end
25
27
 
26
- assert_equal 'PXELinux', host.provisioning_template(kind: :PXELinux)&.name
28
+ actual = host.provisioning_template(kind: :PXELinux)
29
+ assert_equal 'PXELinux', actual.name
30
+ assert_equal host.name, actual.template
27
31
  end
28
32
  end
29
33
  end
@@ -15,47 +15,42 @@ class TFTPOrchestrationTest < ActiveSupport::TestCase
15
15
  Dir.mktmpdir do |dir|
16
16
  stub_repository host.params['template_url'], "#{dir}/repo.tar.gz" do |tar|
17
17
  tar.add_file_simple("templates/#{kind}/template.erb", 644, template_content.length) { |io| io.write(template_content) }
18
- tar.add_file_simple("templates/#{kind}/default_local_boot.erb", 644, default_local_boot_template_content.length) { |io| io.write(default_local_boot_template_content) }
19
18
  end
20
19
 
21
- assert_equal template_content, host.generate_pxe_template('PXELinux')
20
+ assert_equal template_content, host.generate_pxe_template(kind)
22
21
  end
23
22
  end
24
- end
25
23
 
26
- context 'host is not in build mode' do
27
- let(:host) { FactoryBot.create(:host, :managed, :with_template_url, build: false) }
24
+ context 'when corresponding default local boot template file is missing in the repo' do
25
+ it 'does not generate a pxe template' do
26
+ Dir.mktmpdir do |dir|
27
+ stub_repository host.params['template_url'], "#{dir}/repo.tar.gz"
28
28
 
29
- it 'renders default local boot template' do
30
- Dir.mktmpdir do |dir|
31
- stub_repository host.params['template_url'], "#{dir}/repo.tar.gz" do |tar|
32
- tar.add_file_simple("templates/#{kind}/template.erb", 644, template_content.length) { |io| io.write(template_content) }
33
- tar.add_file_simple("templates/#{kind}/default_local_boot.erb", 644, default_local_boot_template_content.length) { |io| io.write(default_local_boot_template_content) }
29
+ assert_nil host.generate_pxe_template(kind)
34
30
  end
35
-
36
- assert_equal default_local_boot_template_content, host.generate_pxe_template('PXELinux')
37
31
  end
38
32
  end
33
+ end
39
34
 
40
- it 'does not generate a pxe template if the corresponding template file is missing in the repo' do
35
+ context 'host is not in build mode' do
36
+ let(:host) { FactoryBot.create(:host, :managed, :with_template_url, build: false) }
37
+
38
+ it 'renders default local boot template' do
41
39
  Dir.mktmpdir do |dir|
42
40
  stub_repository host.params['template_url'], "#{dir}/repo.tar.gz" do |tar|
43
- tar.add_file_simple("templates/#{kind}/template.erb", 644, template_content.length) { |io| io.write(template_content) }
44
41
  tar.add_file_simple("templates/#{kind}/default_local_boot.erb", 644, default_local_boot_template_content.length) { |io| io.write(default_local_boot_template_content) }
45
42
  end
46
43
 
47
- assert_nil host.generate_pxe_template('PXEGrub2')
44
+ assert_equal default_local_boot_template_content, host.generate_pxe_template(kind)
48
45
  end
49
46
  end
50
47
 
51
- it 'raises an exception when generating a pxe template if the corresponding default local boot template file is missing in the repo' do
52
- Dir.mktmpdir do |dir|
53
- stub_repository host.params['template_url'], "#{dir}/repo.tar.gz" do |tar|
54
- tar.add_file_simple("templates/#{kind}/template.erb", 644, template_content.length) { |io| io.write(template_content) }
55
- end
48
+ context 'when corresponding default local boot template file is missing in the repo' do
49
+ it 'does not generate a pxe template' do
50
+ Dir.mktmpdir do |dir|
51
+ stub_repository host.params['template_url'], "#{dir}/repo.tar.gz"
56
52
 
57
- assert_raises ForemanGitTemplates::RepositoryReader::MissingFileError do
58
- host.generate_pxe_template('PXELinux')
53
+ assert_nil host.generate_pxe_template(kind)
59
54
  end
60
55
  end
61
56
  end
@@ -63,13 +58,14 @@ class TFTPOrchestrationTest < ActiveSupport::TestCase
63
58
  end
64
59
 
65
60
  describe '#validate_tftp' do
66
- let(:host) { FactoryBot.create(:host, :with_tftp_orchestration, :with_template_url, pxe_loader: 'PXELinux BIOS') }
61
+ let(:host) { FactoryBot.create(:host, :with_tftp_orchestration, :with_template_url, build: false, pxe_loader: 'PXELinux BIOS') }
67
62
  let(:kind) { 'PXELinux' }
68
63
  let(:template_content) { 'main template content' }
69
64
  let(:default_local_boot_template_content) { 'default local boot template content' }
70
65
 
71
66
  context 'host is in build mode' do
72
67
  setup do
68
+ host.primary_interface.expects(:valid?).returns(true) if Gem::Version.new(SETTINGS[:version].notag) >= Gem::Version.new('2.0')
73
69
  host.update(build: true)
74
70
  end
75
71
 
@@ -110,6 +106,7 @@ class TFTPOrchestrationTest < ActiveSupport::TestCase
110
106
 
111
107
  context 'host is in build mode' do
112
108
  setup do
109
+ host.primary_interface.expects(:valid?).returns(true) if Gem::Version.new(SETTINGS[:version].notag) >= Gem::Version.new('2.0')
113
110
  host.update(build: true)
114
111
  end
115
112
 
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ module ForemanGitTemplates
6
+ class HostParameterTest < ActiveSupport::TestCase
7
+ describe 'template_url validation' do
8
+ let(:template_url) { 'http://api.com/repo.tar.gz' }
9
+ let(:host) { FactoryBot.create(:host) }
10
+ let(:host_parameter) { FactoryBot.build(:host_parameter, name: 'template_url', value: template_url, host: host) }
11
+
12
+ context 'when template_url returns 200' do
13
+ it 'is valid' do
14
+ stub_request(:head, template_url).to_return(status: 200)
15
+
16
+ assert host_parameter.valid?
17
+ end
18
+ end
19
+
20
+ context 'when template_url returns 401' do
21
+ it 'is invlid' do
22
+ stub_request(:head, template_url).to_return(status: 401)
23
+
24
+ assert_equal false, host_parameter.valid?
25
+ assert_not_empty host_parameter.errors[:value]
26
+ end
27
+ end
28
+
29
+ context 'when template_url returns 404' do
30
+ it 'is invlid' do
31
+ stub_request(:head, template_url).to_return(status: 404)
32
+
33
+ assert_equal false, host_parameter.valid?
34
+ assert_not_empty host_parameter.errors[:value]
35
+ end
36
+ end
37
+
38
+ context 'when template_url returns 500' do
39
+ it 'is invlid' do
40
+ stub_request(:head, template_url).to_return(status: 500)
41
+
42
+ assert_equal false, host_parameter.valid?
43
+ assert_not_empty host_parameter.errors[:value]
44
+ end
45
+ end
46
+
47
+ context 'when template_url is not a valid URL' do
48
+ let(:template_url) { 'not URL value' }
49
+
50
+ it 'is invlid' do
51
+ assert_equal false, host_parameter.valid?
52
+ assert_not_empty host_parameter.errors[:value]
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -6,11 +6,12 @@ module ForemanGitTemplates
6
6
  class HostTest < ActiveSupport::TestCase
7
7
  describe '#repository_path' do
8
8
  context 'with template_url parameter' do
9
- let(:repo_path) { '/tmp/repo.tar.gz' }
9
+ let(:repo_tempfile) { Tempfile.new }
10
+ let(:repo_path) { repo_tempfile.path }
10
11
  let(:host) { FactoryBot.create(:host, :managed, :with_template_url) }
11
12
 
12
13
  it 'returns path to the repository' do
13
- ForemanGitTemplates::RepositoryFetcher.expects(:call).once.with(host.params['template_url']).returns(repo_path)
14
+ ForemanGitTemplates::RepositoryFetcher.expects(:call).once.with(host.params['template_url']).returns(repo_tempfile)
14
15
  assert_equal repo_path, host.repository_path
15
16
  end
16
17
  end
@@ -24,5 +25,93 @@ module ForemanGitTemplates
24
25
  end
25
26
  end
26
27
  end
28
+
29
+ describe '#update' do
30
+ let(:os) { FactoryBot.create(:operatingsystem, :with_associations, type: 'Redhat') }
31
+
32
+ setup do
33
+ host.expects(:skip_orchestration_for_testing?).at_least_once.returns(false)
34
+ end
35
+
36
+ context 'with valid template_url' do
37
+ setup do
38
+ ProxyAPI::TFTP.any_instance.expects(:set).returns(true)
39
+
40
+ if Gem::Version.new(SETTINGS[:version].notag) >= Gem::Version.new('2.0')
41
+ ProxyAPI::TFTP.any_instance.expects(:bootServer).returns('127.0.0.1')
42
+ ProxyAPI::DHCP.any_instance.expects(:set).returns(true)
43
+ ProxyAPI::DHCP.any_instance.expects(:record).with(host.subnet.network, host.dhcp_records.first.mac).returns(host.dhcp_records.first)
44
+ ProxyAPI::DHCP.any_instance.expects(:records_by_ip).with(host.subnet.network, host.provision_interface.ip).returns([host.dhcp_records.first])
45
+ ProxyAPI::DHCP.any_instance.expects(:delete).returns(true)
46
+ end
47
+ end
48
+
49
+ context 'when host is in build mode' do
50
+ let(:host) { FactoryBot.create(:host, :with_tftp_orchestration, :with_template_url, operatingsystem: os, build: true) }
51
+
52
+ it 'updates the host' do
53
+ ProxyAPI::TFTP.any_instance.expects(:fetch_boot_file).twice.returns(true)
54
+
55
+ Dir.mktmpdir do |dir|
56
+ stub_repository host.params['template_url'], "#{dir}/repo.tar.gz" do |tar|
57
+ tar.add_file_simple('templates/PXEGrub2/template.erb', 644, host.name.length) { |io| io.write(host.name) }
58
+ end
59
+
60
+ assert host.update(name: 'newname')
61
+ assert_empty host.errors.messages
62
+ end
63
+ end
64
+ end
65
+
66
+ context 'when host is not in build mode' do
67
+ let(:host) { FactoryBot.create(:host, :with_tftp_orchestration, :with_template_url, operatingsystem: os, build: false) }
68
+
69
+ it 'updates the host' do
70
+ Dir.mktmpdir do |dir|
71
+ stub_repository host.params['template_url'], "#{dir}/repo.tar.gz" do |tar|
72
+ tar.add_file_simple('templates/PXEGrub2/default_local_boot.erb', 644, host.name.length) { |io| io.write(host.name) }
73
+ end
74
+
75
+ assert host.update(name: 'newname')
76
+ assert_empty host.errors.messages
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ context 'with invalid template_url' do
83
+ setup do
84
+ stub_request(:get, host.params['template_url']).to_return(status: 404)
85
+
86
+ if Gem::Version.new(SETTINGS[:version].notag) >= Gem::Version.new('2.0')
87
+ ProxyAPI::TFTP.any_instance.expects(:bootServer).returns('127.0.0.1')
88
+ ProxyAPI::DHCP.any_instance.expects(:record).with(host.subnet.network, host.dhcp_records.first.mac).returns(host.dhcp_records.first)
89
+ ProxyAPI::DHCP.any_instance.expects(:records_by_ip).with(host.subnet.network, host.provision_interface.ip).returns([host.dhcp_records.first])
90
+ end
91
+ end
92
+
93
+ let(:expected_errors) { ["No PXEGrub2 template was found for host #{host.name}. Repository url: #{host.params['template_url']}"] }
94
+
95
+ context 'when host is in build mode' do
96
+ let(:host) { FactoryBot.create(:host, :with_tftp_orchestration, :with_template_url, operatingsystem: os, build: true) }
97
+
98
+ it 'does not update the host' do
99
+ assert_equal false, host.update(name: 'newname')
100
+ assert_equal expected_errors, host.errors[:base]
101
+ assert_equal expected_errors, host.errors[:'interfaces.base']
102
+ end
103
+ end
104
+
105
+ context 'when host is not in build mode' do
106
+ let(:host) { FactoryBot.create(:host, :with_tftp_orchestration, :with_template_url, operatingsystem: os, build: false) }
107
+
108
+ it 'does not update the host' do
109
+ assert_equal false, host.update(name: 'newname')
110
+ assert_equal expected_errors, host.errors[:base]
111
+ assert_equal expected_errors, host.errors[:'interfaces.base']
112
+ end
113
+ end
114
+ end
115
+ end
27
116
  end
28
117
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_plugin_helper'
4
+
5
+ class RendererTest < ActiveSupport::TestCase
6
+ describe '.get_source' do
7
+ subject { Foreman::Renderer.get_source(template: template, host: host, klass: source_klass) }
8
+
9
+ let(:template) { FactoryBot.create(:provisioning_template) }
10
+
11
+ context 'when the host has a template_url defined' do
12
+ let(:host) { FactoryBot.create(:host, :with_template_url) }
13
+
14
+ context 'when the source class is not passed' do
15
+ let(:source_klass) { nil }
16
+
17
+ it 'uses ForemanGitTemplates::Renderer::Source::Repository' do
18
+ Dir.mktmpdir do |dir|
19
+ stub_repository host.params['template_url'], "#{dir}/repo.tar.gz"
20
+
21
+ assert_equal ForemanGitTemplates::Renderer::Source::Repository, subject.class
22
+ end
23
+ end
24
+ end
25
+
26
+ context 'when the source class is implicitly passed' do
27
+ let(:source_klass) { Foreman::Renderer::Source::Database }
28
+
29
+ it { assert_equal Foreman::Renderer::Source::Database, subject.class }
30
+ end
31
+ end
32
+
33
+ context 'when the host has no template_url defined' do
34
+ let(:host) { FactoryBot.create(:host) }
35
+ let(:source_klass) { nil }
36
+
37
+ it { assert_equal Foreman::Renderer::Source::Database, subject.class }
38
+ end
39
+ end
40
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_git_templates
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - dmTECH GmbH
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-17 00:00:00.000000000 Z
11
+ date: 2020-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: down
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rest-client
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rdoc
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -42,17 +56,31 @@ dependencies:
42
56
  name: rubocop
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - '='
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.89.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.89.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
46
74
  - !ruby/object:Gem::Version
47
- version: 0.54.0
75
+ version: '0'
48
76
  type: :development
49
77
  prerelease: false
50
78
  version_requirements: !ruby/object:Gem::Requirement
51
79
  requirements:
52
- - - '='
80
+ - - ">="
53
81
  - !ruby/object:Gem::Version
54
- version: 0.54.0
55
- description:
82
+ version: '0'
83
+ description:
56
84
  email:
57
85
  - opensource@dm.de
58
86
  executables: []
@@ -62,16 +90,20 @@ files:
62
90
  - LICENSE
63
91
  - README.md
64
92
  - Rakefile
93
+ - app/controllers/concerns/foreman_git_templates/unattended_controller_extensions.rb
94
+ - app/helpers/foreman_git_templates/application_helper.rb
65
95
  - app/lib/foreman_git_templates/renderer.rb
66
96
  - app/lib/foreman_git_templates/renderer/source/repository.rb
67
97
  - app/lib/foreman_git_templates/tar.rb
68
98
  - app/models/concerns/foreman_git_templates/host_extensions.rb
99
+ - app/models/concerns/foreman_git_templates/host_parameter_extensions.rb
69
100
  - app/models/concerns/foreman_git_templates/hostext/operating_system.rb
70
101
  - app/models/concerns/foreman_git_templates/orchestration/tftp.rb
71
102
  - app/models/foreman_git_templates/base_repository_template.rb
72
103
  - app/models/foreman_git_templates/default_local_boot_repository_template.rb
73
104
  - app/models/foreman_git_templates/main_repository_template.rb
74
105
  - app/models/foreman_git_templates/snippet_repository_template.rb
106
+ - app/models/setting/git_templates.rb
75
107
  - app/services/foreman_git_templates/repository_fetcher.rb
76
108
  - app/services/foreman_git_templates/repository_reader.rb
77
109
  - config/routes.rb
@@ -84,17 +116,19 @@ files:
84
116
  - test/factories/foreman_git_templates_factories.rb
85
117
  - test/models/concerns/foreman_git_templates/hostext/operating_system_test.rb
86
118
  - test/models/concerns/foreman_git_templates/orchestration/tftp_test.rb
119
+ - test/models/foreman_git_templates/host_parameter_test.rb
87
120
  - test/models/foreman_git_templates/host_test.rb
88
121
  - test/models/foreman_git_templates/snippet_repository_template_test.rb
89
122
  - test/test_plugin_helper.rb
90
123
  - test/unit/foreman/renderer/source/repository_test.rb
124
+ - test/unit/foreman/renderer_test.rb
91
125
  - test/unit/repository_fetcher_test.rb
92
126
  - test/unit/repository_reader_test.rb
93
127
  homepage: https://github.com/dm-drogeriemarkt/foreman_git_templates
94
128
  licenses:
95
129
  - GPL-3.0
96
130
  metadata: {}
97
- post_install_message:
131
+ post_install_message:
98
132
  rdoc_options: []
99
133
  require_paths:
100
134
  - lib
@@ -109,17 +143,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
143
  - !ruby/object:Gem::Version
110
144
  version: '0'
111
145
  requirements: []
112
- rubyforge_project:
113
- rubygems_version: 2.7.3
114
- signing_key:
146
+ rubygems_version: 3.1.2
147
+ signing_key:
115
148
  specification_version: 4
116
149
  summary: Adds support for using templates from Git repositories
117
150
  test_files:
118
151
  - test/unit/repository_fetcher_test.rb
119
152
  - test/unit/foreman/renderer/source/repository_test.rb
153
+ - test/unit/foreman/renderer_test.rb
120
154
  - test/unit/repository_reader_test.rb
121
155
  - test/models/foreman_git_templates/snippet_repository_template_test.rb
122
156
  - test/models/foreman_git_templates/host_test.rb
157
+ - test/models/foreman_git_templates/host_parameter_test.rb
123
158
  - test/models/concerns/foreman_git_templates/hostext/operating_system_test.rb
124
159
  - test/models/concerns/foreman_git_templates/orchestration/tftp_test.rb
125
160
  - test/factories/foreman_git_templates_factories.rb