foreman_templates 5.0.1 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -5
- data/Rakefile +0 -0
- data/app/controllers/api/v2/template_controller.rb +20 -37
- data/app/controllers/concerns/foreman/controller/parameters/template_params.rb +37 -0
- data/app/models/setting/template_sync.rb +6 -4
- data/app/services/foreman_templates/template_importer.rb +43 -87
- data/lib/foreman_templates/engine.rb +2 -12
- data/lib/foreman_templates/version.rb +1 -1
- data/lib/tasks/foreman_templates_tasks.rake +6 -1
- metadata +18 -6
- data/app/models/concerns/foreman_templates/provisioning_template_import.rb +0 -94
- data/app/models/concerns/foreman_templates/ptable_import.rb +0 -89
- data/app/models/concerns/foreman_templates/template_import.rb +0 -65
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 756a604ec2486b327c246ae19a1c2b153c4217b7
|
4
|
+
data.tar.gz: 563b26321d12a2fad2b8d3f8f9202bcba689cf70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5cc02e60ced60af1126efed7dda4c89c167a8a59f8a009c3eb9c2fcd855d4f4c61cc4083d15c41993e4583f5fe367b5114c3fa38d9f44a388d8422385ca9f37b
|
7
|
+
data.tar.gz: 8638ebcf4335c45bf137ece2bd534a94e3f7dbc30040e4d5ee7c9c020c1258a159d10a769acc89a19c99174fe13d479d450181bf0d16cdad168fc07f6b280fd4
|
data/README.md
CHANGED
@@ -26,7 +26,7 @@ These can be overriden for each import by passing options directly to a Rake tas
|
|
26
26
|
|
27
27
|
## Usage
|
28
28
|
|
29
|
-
### Import
|
29
|
+
### Import via Rake task
|
30
30
|
|
31
31
|
The plugin provides a Rake task to import the templates. To use it, simply do
|
32
32
|
|
@@ -49,6 +49,7 @@ template will be automatically associated with the OS
|
|
49
49
|
* dirname => The directory within the git tree containing the templates [/]
|
50
50
|
* filter => Import names matching this regex (case-insensitive; snippets are not filtered)
|
51
51
|
* associate => Associate to OS, "always", when "new" or "never" [new]
|
52
|
+
* lock => Lock imported templates [false]
|
52
53
|
|
53
54
|
The `branch` default will use *develop* if you're on Foreman-nightly; or the
|
54
55
|
matching *1.X-stable* branch for your version of Foreman (if it exists); or
|
@@ -102,6 +103,15 @@ Purge all templates that do not begin with 'Community '
|
|
102
103
|
|
103
104
|
foreman-rake templates:purge negate=true
|
104
105
|
|
106
|
+
### Import and Export via API
|
107
|
+
|
108
|
+
There is an API (`/template/import/`) to initiate import from external
|
109
|
+
repository. The API uses Foreman's authorization and authentication
|
110
|
+
mechanisms. There is also an export action available.
|
111
|
+
|
112
|
+
Unfortunately, there is no CLI support yet. For examples about how to
|
113
|
+
use the API, [visit our documentation](https://theforeman.org/plugins/foreman_templates/5.0/index.html#5.API).
|
114
|
+
|
105
115
|
## Integration with other Foreman Plugins
|
106
116
|
|
107
117
|
`templates` will start processing a template by looking for a metadata entry of
|
@@ -135,10 +145,6 @@ get written to a file in `/tmp`.
|
|
135
145
|
* `:old` and `:new` (in which case this plugin will calculate the diff)
|
136
146
|
* :result` (text, may be nil).
|
137
147
|
|
138
|
-
## TODO
|
139
|
-
|
140
|
-
* Add a button to the UI with Deface to run the rake task
|
141
|
-
|
142
148
|
## Copyright
|
143
149
|
|
144
150
|
Copyright (c) 2013 Greg Sutcliffe
|
data/Rakefile
CHANGED
File without changes
|
@@ -1,54 +1,37 @@
|
|
1
1
|
module Api
|
2
2
|
module V2
|
3
3
|
class TemplateController < ::Api::V2::BaseController
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
include ::Foreman::Controller::Parameters::TemplateParams
|
5
|
+
|
6
|
+
def_param_group :foreman_template_sync_params do
|
7
|
+
param :branch, String, :required => false, :desc => N_("Branch in Git repo.")
|
8
|
+
param :repo, String, :required => false, :desc => N_("Override the default repo from settings.")
|
9
|
+
param :filter, String, :required => false, :desc => N_("Export templates with names matching this regex (case-insensitive; snippets are not filtered).")
|
10
|
+
param :negate, :bool, :required => false, :desc => N_("Negate the prefix (for purging).")
|
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
|
+
end
|
14
|
+
|
15
|
+
api :POST, "/templates/import/", N_("Initiate Import")
|
8
16
|
param :prefix, String, :required => false, :desc => N_("The string all imported templates should begin with.")
|
9
|
-
param :dirname, String, :required => false, :desc => N_("The directory within the git tree containing the templates.")
|
10
|
-
param :filter, String, :required => false, :desc => N_("Import templates with names matching this regex (case-insensitive; snippets are not filtered).")
|
11
|
-
param :negate, :bool, :required => false, :desc => N_("Negate the prefix (for purging).")
|
12
17
|
param :associate, Setting::TemplateSync.associate_types.keys, :required => false, :desc => N_("Associate to OS's, Locations & Organizations. Options are: always, new or never.")
|
13
18
|
param :force, :bool, :required => false, :desc => N_("Update templates that are locked")
|
14
|
-
|
19
|
+
param :lock, :bool, :required => false, :desc => N_("Lock imported templates")
|
20
|
+
param_group :foreman_template_sync_params
|
15
21
|
def import
|
16
|
-
results = ForemanTemplates::TemplateImporter.new(
|
17
|
-
verbose: params['verbose'],
|
18
|
-
repo: params['repo'],
|
19
|
-
branch: params['branch'],
|
20
|
-
prefix: params['prefix'],
|
21
|
-
dirname: params['dirname'],
|
22
|
-
filter: params['filter'],
|
23
|
-
associate: params['associate'],
|
24
|
-
negate: params['negate'],
|
25
|
-
force: params['force']
|
26
|
-
}).import!
|
22
|
+
results = ForemanTemplates::TemplateImporter.new(template_import_params).import!
|
27
23
|
render :json => { :message => results }
|
28
24
|
end
|
29
25
|
|
30
|
-
api :POST, "/
|
31
|
-
param :verbose, :bool, :required => false, :desc => N_("Set verbosity of export")
|
32
|
-
param :repo, String, :required => false, :desc => N_("Override the default repo from settings")
|
33
|
-
param :branch, String, :required => false, :desc => N_("Branch in Git repo.")
|
34
|
-
param :filter, String, :required => false, :desc => N_("Export templates with names matching this regex (case-insensitive; snippets are not filtered).")
|
35
|
-
param :negate, :bool, :required => false, :desc => N_("Negate the prefix (for purging).")
|
26
|
+
api :POST, "/templates/export", N_("Initiate Export")
|
36
27
|
param :metadata_export_mode, Setting::TemplateSync.metadata_export_mode_types.keys, :required => false, :desc => N_("Specify how to handle metadata")
|
37
|
-
|
28
|
+
param_group :foreman_template_sync_params
|
38
29
|
def export
|
39
|
-
ForemanTemplates::TemplateExporter.new(
|
40
|
-
verbose: params['verbose'],
|
41
|
-
repo: params['repo'],
|
42
|
-
branch: params['branch'],
|
43
|
-
filter: params['filter'],
|
44
|
-
negate: params['negate'],
|
45
|
-
metadata_export_mode: params['metadata_export_mode'],
|
46
|
-
dir: params['dir']
|
47
|
-
}).export!
|
30
|
+
ForemanTemplates::TemplateExporter.new(template_export_params).export!
|
48
31
|
render :json => { :message => _('Success') }
|
49
|
-
rescue => e
|
32
|
+
rescue StandardError => e
|
50
33
|
logger.debug e
|
51
|
-
render :json => { :message => (_('Something went wrong during export: %s') % e.message) }, :status =>
|
34
|
+
render :json => { :message => (_('Something went wrong during export: %s') % e.message) }, :status => :internal_server_error
|
52
35
|
end
|
53
36
|
end
|
54
37
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Foreman
|
2
|
+
module Controller
|
3
|
+
module Parameters
|
4
|
+
module TemplateParams
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
class_methods do
|
8
|
+
def filter_params_list
|
9
|
+
%i(verbose repo branch dirname filter negate metadata_export_mode dirname)
|
10
|
+
end
|
11
|
+
|
12
|
+
def extra_import_params
|
13
|
+
%i(associate force prefix lock)
|
14
|
+
end
|
15
|
+
|
16
|
+
def extra_export_params
|
17
|
+
[:metadata_export_mode]
|
18
|
+
end
|
19
|
+
|
20
|
+
def template_params_filter(extra_params = [])
|
21
|
+
Foreman::ParameterFilter.new(Hash).tap do |filter|
|
22
|
+
filter.permit filter_params_list.concat(extra_params)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def template_import_params
|
28
|
+
self.class.template_params_filter(self.class.extra_import_params).filter_params(params, parameter_filter_context, :none)
|
29
|
+
end
|
30
|
+
|
31
|
+
def template_export_params
|
32
|
+
self.class.template_params_filter(self.class.extra_export_params).filter_params(params, parameter_filter_context, :none)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -19,20 +19,22 @@ class Setting
|
|
19
19
|
def self.load_defaults
|
20
20
|
return unless super
|
21
21
|
|
22
|
-
%w(template_sync_filter template_sync_branch).each { |s| Setting::BLANK_ATTRS << s }
|
22
|
+
%w(template_sync_filter template_sync_branch template_sync_prefix).each { |s| Setting::BLANK_ATTRS << s }
|
23
|
+
Setting::NOT_STRIPPED << 'template_sync_prefix'
|
23
24
|
|
24
25
|
self.transaction do
|
25
26
|
[
|
26
27
|
self.set('template_sync_verbose', N_('Choose verbosity for Rake task importing templates'), false, N_('Verbosity')),
|
27
|
-
self.set('template_sync_associate', N_('Associate templates to OS'), 'new', N_('Associate'), nil, { :collection => Proc.new { self.associate_types } }),
|
28
|
-
self.set('template_sync_prefix', N_('The string all imported templates should begin with'), "
|
28
|
+
self.set('template_sync_associate', N_('Associate templates to OS, organization and location'), 'new', N_('Associate'), nil, { :collection => Proc.new { self.associate_types } }),
|
29
|
+
self.set('template_sync_prefix', N_('The string all imported templates should begin with'), "", N_('Prefix')),
|
29
30
|
self.set('template_sync_dirname', N_('The directory within the Git repo containing the templates'), '/', N_('Dirname')),
|
30
31
|
self.set('template_sync_filter', N_('Import or export names matching this regex (case-insensitive; snippets are not filtered)'), nil, N_('Filter')),
|
31
|
-
self.set('template_sync_repo', N_('
|
32
|
+
self.set('template_sync_repo', N_('Target path to import and export. Different protocols can be used, e.g. /tmp/dir, git://example.com, https://example.com, ssh://example.com'), 'https://github.com/theforeman/community-templates.git', N_('Repo')),
|
32
33
|
self.set('template_sync_negate', N_('Negate the prefix (for purging) / filter (for importing/exporting)'), false, N_('Negate')),
|
33
34
|
self.set('template_sync_branch', N_('Default branch in Git repo'), nil, N_('Branch')),
|
34
35
|
self.set('template_sync_metadata_export_mode', N_('Default metadata export mode, refresh re-renders metadata, keep will keep existing metadata, remove exports template withou metadata'), 'refresh', N_('Metadata export mode'), nil, { :collection => Proc.new { self.metadata_export_mode_types } }),
|
35
36
|
self.set('template_sync_force', N_('Should importing overwrite locked templates?'), false, N_('Force import')),
|
37
|
+
self.set('template_sync_lock', N_('Should importing lock templates?'), false, N_('Lock templates')),
|
36
38
|
].compact.each { |s| self.create! s.update(:category => "Setting::TemplateSync") }
|
37
39
|
end
|
38
40
|
|
@@ -1,18 +1,16 @@
|
|
1
|
-
class NoKindError < RuntimeError; end
|
2
|
-
class MissingKindError < RuntimeError; end
|
3
|
-
|
4
1
|
module ForemanTemplates
|
5
2
|
class TemplateImporter < Action
|
6
3
|
attr_accessor :metadata, :name, :text
|
7
4
|
|
8
5
|
def self.setting_overrides
|
9
|
-
super + %i(associate force)
|
6
|
+
super + %i(associate force lock)
|
10
7
|
end
|
11
8
|
|
12
9
|
def initialize(args = {})
|
13
10
|
super
|
14
11
|
@verbose = parse_bool(@verbose)
|
15
12
|
@force = parse_bool(@force)
|
13
|
+
@lock = parse_bool(@lock)
|
16
14
|
end
|
17
15
|
|
18
16
|
def import!
|
@@ -52,55 +50,59 @@ module ForemanTemplates
|
|
52
50
|
text = File.read(template)
|
53
51
|
result_lines << 'Parsing: ' + template.gsub(/#{@dir}#{@dirname}/, '') if @verbose
|
54
52
|
|
55
|
-
metadata = parse_metadata(text)
|
56
|
-
metadata['associate'] = @associate
|
53
|
+
metadata = Template.parse_metadata(text)
|
57
54
|
|
58
55
|
# Get the name and filter
|
59
|
-
|
60
|
-
|
61
|
-
name = metadata['name'] || title
|
62
|
-
name = auto_prefix(name)
|
56
|
+
name = metadata['name']
|
57
|
+
name = auto_prefix(name)
|
63
58
|
if @filter
|
64
59
|
matching = name.match(/#{@filter}/i)
|
65
60
|
matching = !matching if @negate
|
66
|
-
|
61
|
+
unless matching
|
62
|
+
result_lines << "Skipping template '#{name}' since it's name is matching filter condition" if @verbose
|
63
|
+
next
|
64
|
+
end
|
67
65
|
end
|
68
66
|
|
67
|
+
options = { :force => @force, :associate => @associate, :lock => @lock }
|
68
|
+
template_type = 'Unknown template type'
|
69
69
|
begin
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
if data[:diff].nil? && data[:old].present? && data[:new].present?
|
87
|
-
data[:diff] = calculate_diff(data[:old], data[:new])
|
70
|
+
if metadata.key?('model')
|
71
|
+
template_type = metadata['model'].constantize
|
72
|
+
else
|
73
|
+
result_lines << "Metadata for template '#{name}' do not specify 'model', import failed"
|
74
|
+
next
|
75
|
+
end
|
76
|
+
|
77
|
+
template = template_type.import_without_save(name, text, options)
|
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
|
88
86
|
end
|
89
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
|
+
|
90
98
|
if @verbose
|
91
|
-
result_lines << data[:result]
|
92
99
|
result_lines << data[:diff] unless data[:diff].nil?
|
93
100
|
end
|
94
|
-
result_lines <<
|
101
|
+
result_lines << data[:status]
|
95
102
|
result_lines << data[:errors] unless data[:errors].empty?
|
96
|
-
rescue
|
97
|
-
|
98
|
-
|
99
|
-
rescue NoKindError
|
100
|
-
result_lines << " Skipping: '#{name}' - Unknown template kind '#{metadata['kind']}'"
|
101
|
-
next
|
102
|
-
rescue NameError
|
103
|
-
result_lines << " Skipping: '#{name}' - Unknown template model '#{metadata['model']}'"
|
103
|
+
rescue => e
|
104
|
+
Foreman::Logging.exception 'error during template import', e, :level => :debug
|
105
|
+
result_lines << "#{template_type} '#{name}' import failed - #{e.message}"
|
104
106
|
next
|
105
107
|
end
|
106
108
|
end
|
@@ -119,65 +121,19 @@ module ForemanTemplates
|
|
119
121
|
end
|
120
122
|
end
|
121
123
|
|
122
|
-
def parse_metadata(text)
|
123
|
-
# Pull out the first erb comment only - /m is for a multiline regex
|
124
|
-
extracted = text.match(/<%\#[\t a-z0-9=:]*(.+?).-?%>/m)
|
125
|
-
extracted.nil? ? {} : YAML.load(extracted[1])
|
126
|
-
end
|
127
|
-
|
128
|
-
def update_job_template(name, text)
|
129
|
-
file = name.gsub(/^#{@prefix}/, '')
|
130
|
-
puts 'Deprecation warning: JobTemplate support is moving to the Remote Execution plugin'
|
131
|
-
puts "- please add 'model: JobTemplate' to the metadata in '#{file}' to call the right method"
|
132
|
-
|
133
|
-
unless defined?(JobTemplate)
|
134
|
-
return {
|
135
|
-
:status => false,
|
136
|
-
:result => 'Skipping job template import, remote execution plugin is not installed.'
|
137
|
-
}
|
138
|
-
end
|
139
|
-
template = JobTemplate.import(
|
140
|
-
text.sub(/^name: .*$/, "name: #{name}"),
|
141
|
-
:update => true
|
142
|
-
)
|
143
|
-
|
144
|
-
c_or_u = template.new_record? ? 'Created' : 'Updated'
|
145
|
-
id_string = ('id' + template.id) rescue ''
|
146
|
-
|
147
|
-
if template.template != template.template_was
|
148
|
-
diff = Diffy::Diff.new(
|
149
|
-
template.template_was,
|
150
|
-
template.template,
|
151
|
-
:include_diff_info => true
|
152
|
-
).to_s(:color)
|
153
|
-
end
|
154
|
-
|
155
|
-
result = " #{c_or_u} Template #{id_string}:#{name}"
|
156
|
-
{ :diff => diff, :status => template.save, :result => result }
|
157
|
-
end
|
158
|
-
|
159
124
|
def purge!
|
160
125
|
clause = "name #{@negate ? 'NOT ' : ''}LIKE ?"
|
161
126
|
ProvisioningTemplate.where(clause, "#{@prefix}%").each do |template|
|
162
127
|
puts template if @verbose
|
163
128
|
template.destroy
|
164
129
|
end
|
165
|
-
|
130
|
+
# :purge
|
131
|
+
end
|
166
132
|
|
167
133
|
private
|
168
134
|
|
169
135
|
def parse_bool(bool_name)
|
170
136
|
bool_name.is_a?(String) ? bool_name != 'false' : bool_name
|
171
137
|
end
|
172
|
-
|
173
|
-
def status_to_text(status, name)
|
174
|
-
msg = "#{name} - import "
|
175
|
-
msg << if status
|
176
|
-
"success"
|
177
|
-
else
|
178
|
-
'failure'
|
179
|
-
end
|
180
|
-
msg
|
181
|
-
end
|
182
138
|
end
|
183
139
|
end
|
@@ -10,12 +10,12 @@ module ForemanTemplates
|
|
10
10
|
engine_name 'foreman_templates'
|
11
11
|
|
12
12
|
initializer 'foreman_templates.load_default_settings', :before => :load_config_initializers do
|
13
|
-
require_dependency File.expand_path('
|
13
|
+
require_dependency File.expand_path('../../app/models/setting/template_sync.rb', __dir__) if (Setting.table_exists? rescue(false))
|
14
14
|
end
|
15
15
|
|
16
16
|
initializer 'foreman_templates.register_plugin', :before => :finisher_hook do
|
17
17
|
Foreman::Plugin.register :foreman_templates do
|
18
|
-
requires_foreman '>= 1.
|
18
|
+
requires_foreman '>= 1.18'
|
19
19
|
|
20
20
|
apipie_documented_controllers ["#{ForemanTemplates::Engine.root}/app/controllers/api/v2/*.rb"]
|
21
21
|
|
@@ -30,15 +30,5 @@ module ForemanTemplates
|
|
30
30
|
add_all_permissions_to_default_roles
|
31
31
|
end
|
32
32
|
end
|
33
|
-
|
34
|
-
config.to_prepare do
|
35
|
-
begin
|
36
|
-
Template.send(:include, ForemanTemplates::TemplateImport)
|
37
|
-
Ptable.send(:include, ForemanTemplates::PtableImport)
|
38
|
-
ProvisioningTemplate.send(:include, ForemanTemplates::ProvisioningTemplateImport)
|
39
|
-
rescue => e
|
40
|
-
puts "#{ForemanTemplates::ENGINE_NAME}: skipping engine hook (#{e})"
|
41
|
-
end
|
42
|
-
end
|
43
33
|
end
|
44
34
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
namespace :templates do
|
3
3
|
desc 'Import templates according to settings'
|
4
4
|
task :import => :environment do
|
5
|
+
ActiveSupport::Deprecation.warn "You are using a deprecated behavior, 'rake templates:import' will be removed in a future version. Please use appropriate API endpoint for this functionality"
|
5
6
|
if Rake.application.top_level_tasks.include?('templates:sync')
|
6
7
|
ActiveSupport::Deprecation.warn('templates:sync task has been renamed to templates:import and will be removed in a future version')
|
7
8
|
end
|
@@ -13,6 +14,7 @@ namespace :templates do
|
|
13
14
|
# * dirname => The directory within the git tree containing the templates [/]
|
14
15
|
# * filter => Import names matching this regex (case-insensitive; snippets are not filtered)
|
15
16
|
# * associate => Associate to OS's, Locations & Organizations. Options are: always, new or never [new]
|
17
|
+
# * lock => Lock imported templates [false]
|
16
18
|
|
17
19
|
User.current = User.anonymous_admin
|
18
20
|
|
@@ -24,6 +26,7 @@ namespace :templates do
|
|
24
26
|
dirname: ENV['dirname'],
|
25
27
|
filter: ENV['filter'],
|
26
28
|
associate: ENV['associate'],
|
29
|
+
lock: ENV['lock'],
|
27
30
|
}).import!
|
28
31
|
|
29
32
|
puts results.join("\n")
|
@@ -33,6 +36,7 @@ namespace :templates do
|
|
33
36
|
|
34
37
|
desc 'Export templates according to settings'
|
35
38
|
task :export => :environment do
|
39
|
+
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"
|
36
40
|
User.current = User.anonymous_admin
|
37
41
|
|
38
42
|
ForemanTemplates::TemplateExporter.new({
|
@@ -51,6 +55,7 @@ namespace :templates do
|
|
51
55
|
|
52
56
|
desc 'Purge unwanted templates from foreman'
|
53
57
|
task :purge => :environment do
|
58
|
+
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"
|
54
59
|
User.current = User.anonymous_admin
|
55
60
|
|
56
61
|
ForemanTemplates::TemplateImporter.new({
|
@@ -92,7 +97,7 @@ namespace :foreman_templates do
|
|
92
97
|
"#{ForemanTemplates::Engine.root}/lib/**/*.rb",
|
93
98
|
"#{ForemanTemplates::Engine.root}/test/**/*.rb"]
|
94
99
|
end
|
95
|
-
rescue
|
100
|
+
rescue StandardError
|
96
101
|
puts 'Rubocop not loaded.'
|
97
102
|
end
|
98
103
|
|
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:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg Sutcliffe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-04-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: diffy
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
description: Engine to synchronise provisioning templates from GitHub
|
42
56
|
email: gsutclif@redhat.com
|
43
57
|
executables: []
|
@@ -50,9 +64,7 @@ files:
|
|
50
64
|
- README.md
|
51
65
|
- Rakefile
|
52
66
|
- app/controllers/api/v2/template_controller.rb
|
53
|
-
- app/
|
54
|
-
- app/models/concerns/foreman_templates/ptable_import.rb
|
55
|
-
- app/models/concerns/foreman_templates/template_import.rb
|
67
|
+
- app/controllers/concerns/foreman/controller/parameters/template_params.rb
|
56
68
|
- app/models/setting/template_sync.rb
|
57
69
|
- app/services/foreman_templates/action.rb
|
58
70
|
- app/services/foreman_templates/cleaner.rb
|
@@ -83,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
95
|
version: '0'
|
84
96
|
requirements: []
|
85
97
|
rubyforge_project:
|
86
|
-
rubygems_version: 2.
|
98
|
+
rubygems_version: 2.6.8
|
87
99
|
signing_key:
|
88
100
|
specification_version: 4
|
89
101
|
summary: Template-syncing engine for Foreman
|
@@ -1,94 +0,0 @@
|
|
1
|
-
module ForemanTemplates
|
2
|
-
module ProvisioningTemplateImport
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
module ClassMethods
|
6
|
-
def import!(name, text, metadata, force = false)
|
7
|
-
# Check for snippet type
|
8
|
-
return import_snippet!(name, text, force) if metadata['snippet'] || metadata['kind'] == 'snippet'
|
9
|
-
|
10
|
-
# Get template type
|
11
|
-
kind = TemplateKind.find_by(name: metadata['kind'])
|
12
|
-
raise NoKindError unless kind
|
13
|
-
|
14
|
-
# Data
|
15
|
-
template = ProvisioningTemplate.where(:name => name).first_or_initialize
|
16
|
-
data = {
|
17
|
-
:template => text,
|
18
|
-
:snippet => false,
|
19
|
-
:template_kind_id => kind.id
|
20
|
-
}
|
21
|
-
oses = map_metadata(metadata, 'oses')
|
22
|
-
locations = map_metadata(metadata, 'locations')
|
23
|
-
organizations = map_metadata(metadata, 'organizations')
|
24
|
-
|
25
|
-
# Printout helpers
|
26
|
-
c_or_u = template.new_record? ? 'Creating' : 'Updating'
|
27
|
-
id_string = template.new_record? ? '' : "id #{template.id}"
|
28
|
-
if template.locked? && !template.new_record? && !force
|
29
|
-
return { :diff => nil,
|
30
|
-
:status => false,
|
31
|
-
:result => "Skipping Template #{id_string}:#{name} - template is locked" }
|
32
|
-
end
|
33
|
-
|
34
|
-
associate_metadata data, template, metadata, oses, organizations, locations
|
35
|
-
|
36
|
-
diff = nil
|
37
|
-
status = nil
|
38
|
-
if template_changed?(data, template)
|
39
|
-
diff = create_diff(data, template)
|
40
|
-
template.ignore_locking do
|
41
|
-
status = template.update_attributes(data)
|
42
|
-
end
|
43
|
-
result = build_associations_result c_or_u, id_string, name, oses, organizations, locations
|
44
|
-
else
|
45
|
-
status = true
|
46
|
-
result = " No change to Template #{id_string}:#{name}"
|
47
|
-
end
|
48
|
-
|
49
|
-
{ :diff => diff, :status => status, :result => result, :errors => template.errors }
|
50
|
-
end
|
51
|
-
|
52
|
-
def associate_metadata(data, template, metadata, oses, organizations, locations)
|
53
|
-
if (metadata['associate'] == 'new' && template.new_record?) || (metadata['associate'] == 'always')
|
54
|
-
data[:operatingsystem_ids] = oses.map(&:id)
|
55
|
-
data[:location_ids] = locations.map(&:id)
|
56
|
-
data[:organization_ids] = organizations.map(&:id)
|
57
|
-
end
|
58
|
-
data
|
59
|
-
end
|
60
|
-
|
61
|
-
def build_associations_result(c_or_u, id_string, name, oses, organizations, locations)
|
62
|
-
res = " #{c_or_u} Template #{id_string}:#{name}"
|
63
|
-
res += "\n Operatingsystem Associations:\n - #{oses.map(&:fullname).join("\n - ")}" unless oses.empty?
|
64
|
-
res += "\n Organizations Associations:\n - #{organizations.map(&:name).join("\n - ")}" unless organizations.empty?
|
65
|
-
res += "\n Location Associations:\n - #{locations.map(&:name).join("\n - ")}" unless locations.empty?
|
66
|
-
res
|
67
|
-
end
|
68
|
-
|
69
|
-
def create_diff(data, template)
|
70
|
-
if template_content_changed?(template.template, data[:template])
|
71
|
-
Diffy::Diff.new(
|
72
|
-
template.template,
|
73
|
-
data[:template],
|
74
|
-
:include_diff_info => true
|
75
|
-
).to_s(:color)
|
76
|
-
else
|
77
|
-
nil
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def template_content_changed?(template_template, data_template)
|
82
|
-
template_template != data_template
|
83
|
-
end
|
84
|
-
|
85
|
-
def associations_changed?(data)
|
86
|
-
!(data[:operatingsystem_ids] || data[:location_ids] || data[:organization_ids]).nil?
|
87
|
-
end
|
88
|
-
|
89
|
-
def template_changed?(data, template)
|
90
|
-
template_content_changed?(template.template, data[:template]) || associations_changed?(data)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
module ForemanTemplates
|
2
|
-
module PtableImport
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
module ClassMethods
|
6
|
-
def import!(name, text, metadata, force = false)
|
7
|
-
# Check for snippet type
|
8
|
-
return import_snippet!(name, text, force) if metadata['snippet']
|
9
|
-
|
10
|
-
# Data
|
11
|
-
ptable = Ptable.where(:name => name).first_or_initialize
|
12
|
-
data = {
|
13
|
-
:layout => text
|
14
|
-
}
|
15
|
-
oses = map_metadata(metadata, 'oses')
|
16
|
-
locations = map_metadata(metadata, 'locations')
|
17
|
-
organizations = map_metadata(metadata, 'organizations')
|
18
|
-
|
19
|
-
# Printout helpers
|
20
|
-
c_or_u = ptable.new_record? ? 'Creating' : 'Updating'
|
21
|
-
id_string = ptable.new_record? ? '' : "id #{ptable.id}"
|
22
|
-
if ptable.locked? && !ptable.new_record? && !force
|
23
|
-
return { :diff => nil,
|
24
|
-
:status => false,
|
25
|
-
:result => "Skipping Partition Table #{id_string}:#{name} - partition table is locked" }
|
26
|
-
end
|
27
|
-
|
28
|
-
associate_metadata data, ptable, metadata, oses, organizations, locations
|
29
|
-
|
30
|
-
diff = nil
|
31
|
-
status = nil
|
32
|
-
if ptable_changed?(data, ptable)
|
33
|
-
diff = create_diff(data, ptable)
|
34
|
-
ptable.ignore_locking do
|
35
|
-
status = ptable.update_attributes(data)
|
36
|
-
end
|
37
|
-
result = build_associations_result c_or_u, id_string, name, oses, organizations, locations
|
38
|
-
else
|
39
|
-
status = true
|
40
|
-
result = " No change to Ptable #{id_string}:#{name}"
|
41
|
-
end
|
42
|
-
{ :diff => diff, :status => status, :result => result, :errors => ptable.errors }
|
43
|
-
end
|
44
|
-
|
45
|
-
def associate_metadata(data, ptable, metadata, oses, organizations, locations)
|
46
|
-
if (metadata['associate'] == 'new' && ptable.new_record?) || (metadata['associate'] == 'always')
|
47
|
-
data[:operatingsystem_ids] = oses.map(&:id)
|
48
|
-
data[:os_family] = oses.map(&:family).uniq.first
|
49
|
-
data[:location_ids] = locations.map(&:id)
|
50
|
-
data[:organization_ids] = organizations.map(&:id)
|
51
|
-
end
|
52
|
-
data
|
53
|
-
end
|
54
|
-
|
55
|
-
def ptable_content_changed?(data_layout, ptable_layout)
|
56
|
-
data_layout != ptable_layout
|
57
|
-
end
|
58
|
-
|
59
|
-
def associations_changed?(data)
|
60
|
-
!(data[:os_family] || data[:location_ids] || data[:organization_ids]).nil?
|
61
|
-
end
|
62
|
-
|
63
|
-
def create_diff(data, ptable)
|
64
|
-
if ptable_content_changed?(data[:layout], ptable.layout)
|
65
|
-
Diffy::Diff.new(
|
66
|
-
ptable.layout,
|
67
|
-
data[:layout],
|
68
|
-
:include_diff_info => true
|
69
|
-
).to_s(:color)
|
70
|
-
else
|
71
|
-
nil
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
def build_associations_result(c_or_u, id_string, name, oses, organizations, locations)
|
76
|
-
res = " #{c_or_u} Ptable #{id_string}:#{name}"
|
77
|
-
res += "\n Operatingsystem Family:\n - #{oses.map(&:family).uniq.first}" unless oses.empty?
|
78
|
-
res += "\n Operatingsystem Associations:\n - #{oses.map(&:fullname).join("\n - ")}" unless oses.empty?
|
79
|
-
res += "\n Organizations Associations:\n - #{organizations.map(&:name).join("\n - ")}" unless organizations.empty?
|
80
|
-
res += "\n Location Associations:\n - #{locations.map(&:name).join("\n - ")}" unless locations.empty?
|
81
|
-
res
|
82
|
-
end
|
83
|
-
|
84
|
-
def ptable_changed?(data, ptable)
|
85
|
-
ptable_content_changed?(data[:layout], ptable.layout) || associations_changed?(data)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
module ForemanTemplates
|
2
|
-
module TemplateImport
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
module ClassMethods
|
6
|
-
def import_snippet!(name, text, force = false)
|
7
|
-
# Data
|
8
|
-
snippet = self.where(:name => name).first_or_initialize
|
9
|
-
data = {
|
10
|
-
:template => text,
|
11
|
-
:snippet => true
|
12
|
-
}
|
13
|
-
|
14
|
-
# Printout helpers
|
15
|
-
c_or_u = snippet.new_record? ? 'Creating' : 'Updating'
|
16
|
-
id_string = snippet.new_record? ? '' : "id #{snippet.id}"
|
17
|
-
|
18
|
-
if snippet.locked? && !snippet.new_record? && !force
|
19
|
-
return { :diff => nil,
|
20
|
-
:status => false,
|
21
|
-
:result => "Skipping snippet #{id_string}:#{name} - template is locked" }
|
22
|
-
end
|
23
|
-
|
24
|
-
status = nil
|
25
|
-
if data[:template] != snippet.template
|
26
|
-
diff = Diffy::Diff.new(
|
27
|
-
snippet.template,
|
28
|
-
data[:template],
|
29
|
-
:include_diff_info => true
|
30
|
-
).to_s(:color)
|
31
|
-
snippet.ignore_locking do
|
32
|
-
status = snippet.update_attributes(data)
|
33
|
-
end
|
34
|
-
result = " #{c_or_u} Snippet #{id_string}:#{name}"
|
35
|
-
else
|
36
|
-
diff = nil
|
37
|
-
status = true
|
38
|
-
result = " No change to Snippet #{id_string}:#{name}"
|
39
|
-
end
|
40
|
-
{ :diff => diff, :status => status, :result => result, :errors => snippet.errors }
|
41
|
-
end
|
42
|
-
|
43
|
-
def map_metadata(metadata, param)
|
44
|
-
if metadata[param]
|
45
|
-
case param
|
46
|
-
when 'oses'
|
47
|
-
metadata[param].map do |os|
|
48
|
-
Operatingsystem.all.map { |db| db.to_label =~ /^#{os}/ ? db : nil }
|
49
|
-
end.flatten.compact
|
50
|
-
when 'locations'
|
51
|
-
metadata[param].map do |loc|
|
52
|
-
User.current.my_locations.map { |db| db.name =~ /^#{loc}/ ? db : nil }
|
53
|
-
end.flatten.compact
|
54
|
-
when 'organizations'
|
55
|
-
metadata[param].map do |org|
|
56
|
-
User.current.my_organizations.map { |db| db.name =~ /^#{org}/ ? db : nil }
|
57
|
-
end.flatten.compact
|
58
|
-
end
|
59
|
-
else
|
60
|
-
[]
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|