foreman_templates 5.0.1 → 6.0.0
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 +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
|