foreman_templates 6.0.0 → 6.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/api/v2/template_controller.rb +10 -8
- data/app/controllers/concerns/foreman/controller/parameters/template_params.rb +19 -2
- data/app/services/foreman_templates/action.rb +2 -11
- data/app/services/foreman_templates/export_result.rb +41 -0
- data/app/services/foreman_templates/parse_result.rb +92 -0
- data/app/services/foreman_templates/template_exporter.rb +73 -25
- data/app/services/foreman_templates/template_importer.rb +88 -65
- data/lib/foreman_templates/version.rb +1 -1
- data/lib/tasks/foreman_templates_tasks.rake +8 -9
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0c518e8c2822c6112f13654488a324eb9c2918a
|
4
|
+
data.tar.gz: b32fab2dde41371d5367c8d95db70fd2eb85d0ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b647c76ec12f0262f6dc95703487fee408ab094bb918b77f0df6141080cb90b3373cb7d4c27620488b75aa66c0d39450c033ed9ae9145e2cf023656189c3ee18
|
7
|
+
data.tar.gz: '0981be0b744c1a1573fdf0c8c7cec0f82357679cb3873d7ff7264a5af6cc1348e8b8d38da4b9ea5e073b82366e2a79ca284f8b0a4e4037a9951b816c5d692902'
|
@@ -9,7 +9,6 @@ module Api
|
|
9
9
|
param :filter, String, :required => false, :desc => N_("Export templates with names matching this regex (case-insensitive; snippets are not filtered).")
|
10
10
|
param :negate, :bool, :required => false, :desc => N_("Negate the prefix (for purging).")
|
11
11
|
param :dirname, String, :required => false, :desc => N_("The directory within Git repo containing the templates")
|
12
|
-
param :verbose, :bool, :required => false, :desc => N_("Set verbosity of import")
|
13
12
|
end
|
14
13
|
|
15
14
|
api :POST, "/templates/import/", N_("Initiate Import")
|
@@ -17,21 +16,24 @@ module Api
|
|
17
16
|
param :associate, Setting::TemplateSync.associate_types.keys, :required => false, :desc => N_("Associate to OS's, Locations & Organizations. Options are: always, new or never.")
|
18
17
|
param :force, :bool, :required => false, :desc => N_("Update templates that are locked")
|
19
18
|
param :lock, :bool, :required => false, :desc => N_("Lock imported templates")
|
19
|
+
param :verbose, :bool, :required => false, :desc => N_("Show template diff in response")
|
20
20
|
param_group :foreman_template_sync_params
|
21
|
+
param_group :taxonomies, ::Api::V2::BaseController
|
21
22
|
def import
|
22
|
-
|
23
|
-
|
23
|
+
verbose = params['verbose']
|
24
|
+
@result = ForemanTemplates::TemplateImporter.new(template_import_params).import!
|
25
|
+
render :json => { :message => { :templates => @result[:results].map { |res| res.to_h(verbose) },
|
26
|
+
:repo => @result[:repo],
|
27
|
+
:branch => @result[:branch] } }
|
24
28
|
end
|
25
29
|
|
26
30
|
api :POST, "/templates/export", N_("Initiate Export")
|
27
31
|
param :metadata_export_mode, Setting::TemplateSync.metadata_export_mode_types.keys, :required => false, :desc => N_("Specify how to handle metadata")
|
28
32
|
param_group :foreman_template_sync_params
|
33
|
+
param_group :taxonomies, ::Api::V2::BaseController
|
29
34
|
def export
|
30
|
-
ForemanTemplates::TemplateExporter.new(template_export_params).export!
|
31
|
-
render :json => { :message =>
|
32
|
-
rescue StandardError => e
|
33
|
-
logger.debug e
|
34
|
-
render :json => { :message => (_('Something went wrong during export: %s') % e.message) }, :status => :internal_server_error
|
35
|
+
@result = ForemanTemplates::TemplateExporter.new(template_export_params).export!
|
36
|
+
render :json => { :message => @result.to_h }, :status => @result.exported ? 200 : 500
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
@@ -3,6 +3,7 @@ module Foreman
|
|
3
3
|
module Parameters
|
4
4
|
module TemplateParams
|
5
5
|
extend ActiveSupport::Concern
|
6
|
+
include Foreman::Controller::Parameters::Taxonomix
|
6
7
|
|
7
8
|
class_methods do
|
8
9
|
def filter_params_list
|
@@ -25,11 +26,27 @@ module Foreman
|
|
25
26
|
end
|
26
27
|
|
27
28
|
def template_import_params
|
28
|
-
self.class.template_params_filter(self.class.extra_import_params)
|
29
|
+
add_taxonomy_params(self.class.template_params_filter(self.class.extra_import_params)
|
30
|
+
.filter_params(params, parameter_filter_context, :none).with_indifferent_access)
|
29
31
|
end
|
30
32
|
|
31
33
|
def template_export_params
|
32
|
-
self.class.template_params_filter(self.class.extra_export_params)
|
34
|
+
add_taxonomy_params(self.class.template_params_filter(self.class.extra_export_params)
|
35
|
+
.filter_params(params, parameter_filter_context, :none).with_indifferent_access)
|
36
|
+
end
|
37
|
+
|
38
|
+
def organization_params
|
39
|
+
self.class.organization_params_filter(Hash).filter_params(params, parameter_filter_context, :none)
|
40
|
+
end
|
41
|
+
|
42
|
+
def location_params
|
43
|
+
self.class.location_params_filter(Hash).filter_params(params, parameter_filter_context, :none)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def add_taxonomy_params(params)
|
49
|
+
params.merge(:organization_params => organization_params.to_h).merge(:location_params => location_params.to_h)
|
33
50
|
end
|
34
51
|
end
|
35
52
|
end
|
@@ -19,20 +19,11 @@ module ForemanTemplates
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def initialize(args = {})
|
22
|
+
@taxonomies = { :organizations => args[:organization_params] || {},
|
23
|
+
:locations => args[:location_params] || {} }
|
22
24
|
assign_attributes args
|
23
25
|
end
|
24
26
|
|
25
|
-
def get_default_branch(repo)
|
26
|
-
branch_names = repo.branches.map(&:name).uniq
|
27
|
-
|
28
|
-
# Always use develop on Foreman-nightly, if present, or else relevant stable branch
|
29
|
-
target = SETTINGS[:version].tag == 'develop' ? 'develop' : "#{SETTINGS[:version].short}-stable"
|
30
|
-
return target if branch_names.include?(target)
|
31
|
-
|
32
|
-
# stay on default branch as fallback
|
33
|
-
nil
|
34
|
-
end
|
35
|
-
|
36
27
|
def git_repo?
|
37
28
|
@repo.start_with?('http://', 'https://', 'git://', 'ssh://', 'git+ssh://', 'ssh+git://')
|
38
29
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ForemanTemplates
|
2
|
+
class ExportResult
|
3
|
+
attr_accessor :exported, :error, :warning
|
4
|
+
|
5
|
+
def initialize(repo, branch, git_user)
|
6
|
+
@repo = repo
|
7
|
+
@branch = branch
|
8
|
+
@git_user = git_user
|
9
|
+
@error = nil
|
10
|
+
@warning = nil
|
11
|
+
@templates = []
|
12
|
+
@exported = false
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_exported_templates(templates)
|
16
|
+
@templates.concat templates
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_h
|
20
|
+
{ :error => @error,
|
21
|
+
:warning => @warning,
|
22
|
+
:repo => @repo,
|
23
|
+
:branch => @branch,
|
24
|
+
:git_user => @git_user,
|
25
|
+
:templates => dumped_files_result }
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def dumped_files_result
|
31
|
+
@templates.map { |template| to_template_h template }
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_template_h(template)
|
35
|
+
{ :id => template.id,
|
36
|
+
:name => template.name,
|
37
|
+
:exported => @exported,
|
38
|
+
:type => template.class.name.underscore }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module ForemanTemplates
|
2
|
+
class ParseResult
|
3
|
+
attr_accessor :name, :template
|
4
|
+
attr_reader :imported, :diff, :exception, :additional_errors
|
5
|
+
|
6
|
+
def initialize(template_file)
|
7
|
+
@template_file = template_file.split('/').last
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_h(verbose = false)
|
11
|
+
res = {
|
12
|
+
:name => @name,
|
13
|
+
:id => @template.present? ? @template.id : nil,
|
14
|
+
:changed => changed?,
|
15
|
+
:imported => @imported,
|
16
|
+
:additional_errors => @additional_errors,
|
17
|
+
:exception => @exception ? @exception.message : nil,
|
18
|
+
:validation_errors => errors.to_h,
|
19
|
+
:file => @template_file,
|
20
|
+
:type => @template.present? ? @template.class.name.underscore : nil
|
21
|
+
}
|
22
|
+
|
23
|
+
# false comes as a string when using rake tasks
|
24
|
+
res[:diff] = @diff if verbose && verbose != 'false'
|
25
|
+
res
|
26
|
+
end
|
27
|
+
|
28
|
+
def errors
|
29
|
+
@template ? @template.errors : nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def corrupted_metadata
|
33
|
+
generic_error "Failed to parse metadata"
|
34
|
+
end
|
35
|
+
|
36
|
+
def matching_filter
|
37
|
+
generic_error "Skipping, 'name' filtered out based on 'filter' and 'negate' settings"
|
38
|
+
end
|
39
|
+
|
40
|
+
def no_metadata_name
|
41
|
+
generic_error "No 'name' found in metadata"
|
42
|
+
end
|
43
|
+
|
44
|
+
def missing_model
|
45
|
+
generic_error "No 'model' found in metadata"
|
46
|
+
end
|
47
|
+
|
48
|
+
def generic_error(additional_msg)
|
49
|
+
@imported = false
|
50
|
+
@additional_errors = additional_msg
|
51
|
+
Logging.logger('app').debug "Error in '#{@template_file}': #{additional_msg}"
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def check_for_errors
|
56
|
+
@imported = @template.errors.blank?
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_exception(exception)
|
61
|
+
@imported = false
|
62
|
+
@exception = exception
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
def name_error(exception, template_type)
|
67
|
+
@imported = false
|
68
|
+
@exception = exception
|
69
|
+
@additional_errors = "Template type #{template_type} was not found, are you missing a plugin?"
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
def determine_result_diff
|
74
|
+
return if @template.nil? || !@template.template_changed?
|
75
|
+
template_was = @template.template_was
|
76
|
+
template_is = @template.template
|
77
|
+
@diff = calculate_diff(template_was, template_is)
|
78
|
+
end
|
79
|
+
|
80
|
+
def changed?
|
81
|
+
@diff.present?
|
82
|
+
end
|
83
|
+
|
84
|
+
def calculate_diff(old, new)
|
85
|
+
if old.present? && new.present? && old != new
|
86
|
+
Diffy::Diff.new(old, new, :include_diff_info => true).to_s(:color)
|
87
|
+
else
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -7,61 +7,69 @@ module ForemanTemplates
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def export!
|
10
|
+
@export_result = ExportResult.new(@repo, @branch, foreman_git_user)
|
10
11
|
if git_repo?
|
11
12
|
export_to_git
|
12
13
|
else
|
13
14
|
export_to_files
|
14
15
|
end
|
15
16
|
|
16
|
-
return
|
17
|
+
return @export_result
|
17
18
|
end
|
18
19
|
|
19
20
|
def export_to_files
|
20
21
|
@dir = get_absolute_repo_path
|
21
22
|
verify_path!(@dir)
|
22
23
|
dump_files!
|
24
|
+
@export_result.exported = true
|
23
25
|
end
|
24
26
|
|
25
27
|
def export_to_git
|
26
28
|
@dir = Dir.mktmpdir
|
27
|
-
|
29
|
+
return @export_result if branch_missing?
|
28
30
|
git_repo = Git.clone(@repo, @dir)
|
29
|
-
logger.debug "cloned #{@repo} to #{@dir}"
|
30
|
-
branch = @branch ? @branch : get_default_branch(git_repo)
|
31
|
-
# either checkout to existing or create a new one and checkout afterwards
|
32
|
-
if branch
|
33
|
-
if git_repo.is_branch?(branch)
|
34
|
-
git_repo.checkout(branch)
|
35
|
-
else
|
36
|
-
git_repo.branch(branch).checkout
|
37
|
-
if git_repo.is_remote_branch?(branch) # if we work with remote branch we need to sync it first
|
38
|
-
git_repo.reset_hard("origin/#{branch}")
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
31
|
+
logger.debug "cloned '#{@repo}' to '#{@dir}'"
|
42
32
|
|
33
|
+
setup_git_branch git_repo
|
43
34
|
dump_files!
|
44
35
|
git_repo.add
|
45
36
|
|
46
37
|
status = git_repo.status
|
47
38
|
if status.added.any? || status.changed.any? || status.deleted.any? || status.untracked.any?
|
48
|
-
|
49
|
-
git_repo.commit "Templates export made by Foreman user #{User.current.try(:login) || User::ANONYMOUS_ADMIN}"
|
50
|
-
|
51
|
-
logger.debug "pushing to branch #{branch} at origin #{@repo}"
|
39
|
+
git_repo.commit "Templates export made by Foreman user #{foreman_git_user}"
|
52
40
|
git_repo.push 'origin', branch
|
41
|
+
@export_result.exported = true
|
53
42
|
else
|
54
|
-
|
43
|
+
@export_result.warning = 'No change detected, skipping the commit and push'
|
55
44
|
end
|
45
|
+
rescue StandardError => e
|
46
|
+
@export_result.error = e.message
|
56
47
|
ensure
|
57
48
|
FileUtils.remove_entry_secure(@dir) if File.exist?(@dir)
|
49
|
+
@export_result
|
50
|
+
end
|
51
|
+
|
52
|
+
def setup_git_branch(git_repo)
|
53
|
+
logger.debug "checking out branch '#{@branch}'"
|
54
|
+
if git_repo.is_branch?(@branch)
|
55
|
+
git_repo.checkout(@branch)
|
56
|
+
else
|
57
|
+
git_repo.branch(@branch).checkout
|
58
|
+
if git_repo.is_remote_branch?(@branch) # if we work with remote branch we need to sync it first
|
59
|
+
git_repo.reset_hard("origin/#{@branch}")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def foreman_git_user
|
65
|
+
User.current.try(:login) || User::ANONYMOUS_ADMIN
|
58
66
|
end
|
59
67
|
|
60
68
|
def dump_files!
|
61
|
-
|
69
|
+
templates = templates_to_dump
|
70
|
+
templates.map do |template|
|
62
71
|
current_dir = get_dump_dir(template)
|
63
72
|
FileUtils.mkdir_p current_dir
|
64
|
-
|
65
73
|
filename = File.join(current_dir, get_template_filename(template))
|
66
74
|
File.open(filename, 'w+') do |file|
|
67
75
|
logger.debug "Writing to file #{filename}"
|
@@ -69,6 +77,7 @@ module ForemanTemplates
|
|
69
77
|
logger.debug "finished writing #{bytes}"
|
70
78
|
end
|
71
79
|
end
|
80
|
+
@export_result.add_exported_templates templates
|
72
81
|
end
|
73
82
|
|
74
83
|
def get_template_filename(template)
|
@@ -77,13 +86,13 @@ module ForemanTemplates
|
|
77
86
|
|
78
87
|
def get_dump_dir(template)
|
79
88
|
kind = template.respond_to?(:template_kind) ? template.template_kind.try(:name) || 'snippet' : nil
|
80
|
-
template_class_dir = template.model_name.
|
81
|
-
template_class_dir
|
89
|
+
template_class_dir = template.model_name.plural
|
90
|
+
template_class_dir = 'partition_tables_templates' if template_class_dir == 'ptables'
|
82
91
|
File.join(@dir, dirname.to_s, template_class_dir, kind.to_s)
|
83
92
|
end
|
84
93
|
|
85
94
|
def templates_to_dump
|
86
|
-
base =
|
95
|
+
base = find_templates
|
87
96
|
if filter.present?
|
88
97
|
method = negate ? :reject : :select
|
89
98
|
base.public_send(method) { |template| template.name.match(/#{filter}/i) }
|
@@ -92,6 +101,14 @@ module ForemanTemplates
|
|
92
101
|
end
|
93
102
|
end
|
94
103
|
|
104
|
+
def branch_missing?
|
105
|
+
if @branch.blank?
|
106
|
+
@export_result.error = "Please specify a branch when exporting into a git repo"
|
107
|
+
return true
|
108
|
+
end
|
109
|
+
false
|
110
|
+
end
|
111
|
+
|
95
112
|
# * refresh - template.to_erb stripping existing metadata,
|
96
113
|
# * remove - just template.template with stripping existing metadata,
|
97
114
|
# * keep - taking the whole template.template
|
@@ -107,5 +124,36 @@ module ForemanTemplates
|
|
107
124
|
raise "Unknown metadata export mode #{@metadata_export_mode}"
|
108
125
|
end
|
109
126
|
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def find_templates
|
131
|
+
@taxonomies.values.all?(&:empty?) ? Template.all : find_taxed_templates
|
132
|
+
end
|
133
|
+
|
134
|
+
def find_taxed_templates
|
135
|
+
location_ids = taxes_ids('location')
|
136
|
+
organization_ids = taxes_ids('organization')
|
137
|
+
if location_ids.empty?
|
138
|
+
templates_query(organization_ids)
|
139
|
+
elsif organization_ids.empty?
|
140
|
+
templates_query(location_ids)
|
141
|
+
else
|
142
|
+
templates_query(organization_ids) & templates_query(location_ids)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def templates_query(tax_ids)
|
147
|
+
Template.where(:id => TaxableTaxonomy.where(:taxonomy_id => tax_ids,
|
148
|
+
:taxable_type => Template.subclasses.map(&:name)).pluck(:taxable_id))
|
149
|
+
end
|
150
|
+
|
151
|
+
def taxes_ids(tax_type)
|
152
|
+
tax_type.capitalize.constantize
|
153
|
+
.where(:name => @taxonomies[tax_type.pluralize.to_sym]["#{tax_type}_names".to_sym])
|
154
|
+
.pluck(:id)
|
155
|
+
.concat(@taxonomies[tax_type.pluralize.to_sym]["#{tax_type}_ids".to_sym] || [])
|
156
|
+
.uniq
|
157
|
+
end
|
110
158
|
end
|
111
159
|
end
|
@@ -11,6 +11,7 @@ module ForemanTemplates
|
|
11
11
|
@verbose = parse_bool(@verbose)
|
12
12
|
@force = parse_bool(@force)
|
13
13
|
@lock = parse_bool(@lock)
|
14
|
+
@result_lines = []
|
14
15
|
end
|
15
16
|
|
16
17
|
def import!
|
@@ -24,7 +25,7 @@ module ForemanTemplates
|
|
24
25
|
def import_from_files
|
25
26
|
@dir = get_absolute_repo_path
|
26
27
|
verify_path!(@dir)
|
27
|
-
|
28
|
+
parse_files!
|
28
29
|
end
|
29
30
|
|
30
31
|
def import_from_git
|
@@ -32,95 +33,117 @@ module ForemanTemplates
|
|
32
33
|
@dir = Dir.mktmpdir
|
33
34
|
|
34
35
|
begin
|
36
|
+
logger.debug "cloned '#{@repo}' to '#{@dir}'"
|
35
37
|
gitrepo = Git.clone(@repo, @dir)
|
36
|
-
|
37
|
-
|
38
|
+
if @branch
|
39
|
+
logger.debug "checking out branch '#{@branch}'"
|
40
|
+
gitrepo.checkout(@branch)
|
41
|
+
end
|
38
42
|
|
39
|
-
|
43
|
+
parse_files!
|
40
44
|
ensure
|
41
45
|
FileUtils.remove_entry_secure(@dir) if File.exist?(@dir)
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
45
49
|
def parse_files!
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
Dir["#{@dir}#{@dirname}/**/*.erb"].each do |template|
|
50
|
-
text = File.read(template)
|
51
|
-
result_lines << 'Parsing: ' + template.gsub(/#{@dir}#{@dirname}/, '') if @verbose
|
50
|
+
Dir["#{@dir}#{@dirname}/**/*.erb"].each do |template_file|
|
51
|
+
logger.debug 'Parsing: ' + template_file.gsub(/#{@dir}#{@dirname}/, '')
|
52
|
+
parse_result = ParseResult.new(template_file)
|
52
53
|
|
54
|
+
text = File.read(template_file)
|
53
55
|
metadata = Template.parse_metadata(text)
|
54
56
|
|
55
|
-
|
56
|
-
|
57
|
-
name =
|
58
|
-
|
59
|
-
|
60
|
-
matching = !matching if @negate
|
61
|
-
unless matching
|
62
|
-
result_lines << "Skipping template '#{name}' since it's name is matching filter condition" if @verbose
|
63
|
-
next
|
64
|
-
end
|
65
|
-
end
|
57
|
+
next if metadata_corrupted?(metadata, parse_result)
|
58
|
+
|
59
|
+
next unless (name = auto_prefix_name(metadata, parse_result))
|
60
|
+
|
61
|
+
next if filtered_out name, parse_result
|
66
62
|
|
67
|
-
options = { :force => @force, :associate => @associate, :lock => @lock }
|
68
|
-
template_type = 'Unknown template type'
|
69
63
|
begin
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
data = {}
|
80
|
-
if template.template_changed?
|
81
|
-
data[:old] = template.template_was
|
82
|
-
data[:new] = template.template
|
83
|
-
if data[:diff].nil? && data[:old].present? && data[:new].present?
|
84
|
-
data[:diff] = calculate_diff(data[:old], data[:new])
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
if options[:force]
|
89
|
-
template.ignore_locking { template.save! }
|
90
|
-
else
|
91
|
-
template.save!
|
92
|
-
end
|
93
|
-
|
94
|
-
template_type = template.class.model_name.human
|
95
|
-
data[:status] = template.errors.blank? ? "#{template_type} '#{name}' import successful" : "#{template_type} '#{name}' import failed"
|
96
|
-
data[:errors] = template.errors.full_messages
|
97
|
-
|
98
|
-
if @verbose
|
99
|
-
result_lines << data[:diff] unless data[:diff].nil?
|
100
|
-
end
|
101
|
-
result_lines << data[:status]
|
102
|
-
result_lines << data[:errors] unless data[:errors].empty?
|
64
|
+
next unless (template_type = template_model(metadata, parse_result))
|
65
|
+
template = template_type.import_without_save(name, text, import_options)
|
66
|
+
parse_result.template = template
|
67
|
+
parse_result.determine_result_diff
|
68
|
+
|
69
|
+
save_template template, @force
|
70
|
+
@result_lines << parse_result.check_for_errors
|
71
|
+
rescue NameError => e
|
72
|
+
@result_lines << parse_result.name_error(e, metadata['model'])
|
103
73
|
rescue => e
|
104
|
-
|
105
|
-
result_lines << "#{template_type} '#{name}' import failed - #{e.message}"
|
106
|
-
next
|
74
|
+
@result_lines << parse_result.add_exception(e)
|
107
75
|
end
|
108
76
|
end
|
109
|
-
result_lines
|
77
|
+
{ :results => @result_lines, :repo => @repo, :branch => @branch }
|
110
78
|
end
|
111
79
|
|
112
|
-
def
|
113
|
-
|
80
|
+
def import_options
|
81
|
+
{ :force => @force,
|
82
|
+
:associate => @associate,
|
83
|
+
:lock => @lock,
|
84
|
+
:organization_params => @organizations,
|
85
|
+
:location_params => @locations }
|
114
86
|
end
|
115
87
|
|
116
|
-
def
|
117
|
-
if
|
118
|
-
|
88
|
+
def template_model(metadata, parse_result)
|
89
|
+
if metadata.key?('model')
|
90
|
+
metadata['model'].constantize
|
119
91
|
else
|
92
|
+
@result_lines << parse_result.missing_model
|
120
93
|
nil
|
121
94
|
end
|
122
95
|
end
|
123
96
|
|
97
|
+
def save_template(template, force)
|
98
|
+
result = nil
|
99
|
+
if force
|
100
|
+
result = template.ignore_locking { template.save }
|
101
|
+
else
|
102
|
+
result = template.save
|
103
|
+
end
|
104
|
+
|
105
|
+
if result
|
106
|
+
logger.debug 'saved'
|
107
|
+
else
|
108
|
+
logger.error "couldn't save the template because of: #{template.errors.full_messages.join(', ')}"
|
109
|
+
end
|
110
|
+
result
|
111
|
+
end
|
112
|
+
|
113
|
+
def filtered_out(name, parse_result)
|
114
|
+
if @filter && !name_matching_filter?(name)
|
115
|
+
@result_lines << parse_result.matching_filter
|
116
|
+
true
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def metadata_corrupted?(metadata, parse_result)
|
121
|
+
if metadata.empty?
|
122
|
+
@result_lines << parse_result.corrupted_metadata
|
123
|
+
return true
|
124
|
+
end
|
125
|
+
false
|
126
|
+
end
|
127
|
+
|
128
|
+
def name_matching_filter?(name)
|
129
|
+
matching = name.match(/#{@filter}/i)
|
130
|
+
return !matching if @negate
|
131
|
+
matching
|
132
|
+
end
|
133
|
+
|
134
|
+
def auto_prefix_name(metadata, parse_result)
|
135
|
+
unless (name = metadata['name'])
|
136
|
+
@result_lines << parse_result.no_metadata_name
|
137
|
+
return nil
|
138
|
+
end
|
139
|
+
parse_result.name = auto_prefix(name)
|
140
|
+
auto_prefix(name)
|
141
|
+
end
|
142
|
+
|
143
|
+
def auto_prefix(name)
|
144
|
+
name.start_with?(@prefix) ? name : [@prefix, name].compact.join
|
145
|
+
end
|
146
|
+
|
124
147
|
def purge!
|
125
148
|
clause = "name #{@negate ? 'NOT ' : ''}LIKE ?"
|
126
149
|
ProvisioningTemplate.where(clause, "#{@prefix}%").each do |template|
|
@@ -1,4 +1,6 @@
|
|
1
|
+
require 'pp'
|
1
2
|
# Tasks
|
3
|
+
# rubocop:disable Metrics/BlockLength
|
2
4
|
namespace :templates do
|
3
5
|
desc 'Import templates according to settings'
|
4
6
|
task :import => :environment do
|
@@ -15,11 +17,11 @@ namespace :templates do
|
|
15
17
|
# * filter => Import names matching this regex (case-insensitive; snippets are not filtered)
|
16
18
|
# * associate => Associate to OS's, Locations & Organizations. Options are: always, new or never [new]
|
17
19
|
# * lock => Lock imported templates [false]
|
18
|
-
|
19
20
|
User.current = User.anonymous_admin
|
21
|
+
verbose = ENV['verbose']
|
20
22
|
|
21
23
|
results = ForemanTemplates::TemplateImporter.new({
|
22
|
-
verbose:
|
24
|
+
verbose: verbose,
|
23
25
|
repo: ENV['repo'],
|
24
26
|
branch: ENV['branch'],
|
25
27
|
prefix: ENV['prefix'],
|
@@ -29,35 +31,31 @@ namespace :templates do
|
|
29
31
|
lock: ENV['lock'],
|
30
32
|
}).import!
|
31
33
|
|
32
|
-
|
34
|
+
pp(results.map { |result| result.to_h(verbose) })
|
33
35
|
end
|
34
36
|
|
35
37
|
task :sync => :import
|
36
|
-
|
37
38
|
desc 'Export templates according to settings'
|
38
39
|
task :export => :environment do
|
39
40
|
ActiveSupport::Deprecation.warn "You are using a deprecated behavior, 'rake templates:export' will be removed in a future version. Please use appropriate API endpoint for this functionality"
|
40
41
|
User.current = User.anonymous_admin
|
41
42
|
|
42
|
-
ForemanTemplates::TemplateExporter.new({
|
43
|
-
verbose: ENV['verbose'],
|
43
|
+
result = ForemanTemplates::TemplateExporter.new({
|
44
44
|
repo: ENV['repo'],
|
45
45
|
branch: ENV['branch'],
|
46
46
|
prefix: ENV['prefix'],
|
47
47
|
dirname: ENV['dirname'],
|
48
48
|
filter: ENV['filter'],
|
49
|
-
# associate: ENV['associate'],
|
50
49
|
metadata_export_mode: ENV['metadata_export_mode'],
|
51
50
|
}).export!
|
52
51
|
|
53
|
-
|
52
|
+
pp result
|
54
53
|
end
|
55
54
|
|
56
55
|
desc 'Purge unwanted templates from foreman'
|
57
56
|
task :purge => :environment do
|
58
57
|
ActiveSupport::Deprecation.warn "You are using a deprecated behavior, 'rake templates:purge' will be removed in a future version. Please use appropriate API endpoint for this functionality"
|
59
58
|
User.current = User.anonymous_admin
|
60
|
-
|
61
59
|
ForemanTemplates::TemplateImporter.new({
|
62
60
|
# * negate => negate query [false]
|
63
61
|
# * prefix => The string all templates to purge should ( or not ) begin with [Community ]
|
@@ -75,6 +73,7 @@ namespace :templates do
|
|
75
73
|
puts 'Clean up finished, you can now remove the plugin from your system'
|
76
74
|
end
|
77
75
|
end
|
76
|
+
# rubocop:enable Metrics/BlockLength
|
78
77
|
|
79
78
|
# Tests
|
80
79
|
namespace :test do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foreman_templates
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.0.
|
4
|
+
version: 6.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg Sutcliffe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: diffy
|
@@ -68,6 +68,8 @@ files:
|
|
68
68
|
- app/models/setting/template_sync.rb
|
69
69
|
- app/services/foreman_templates/action.rb
|
70
70
|
- app/services/foreman_templates/cleaner.rb
|
71
|
+
- app/services/foreman_templates/export_result.rb
|
72
|
+
- app/services/foreman_templates/parse_result.rb
|
71
73
|
- app/services/foreman_templates/template_exporter.rb
|
72
74
|
- app/services/foreman_templates/template_importer.rb
|
73
75
|
- config/routes.rb
|