foreman_templates 3.1.0 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 82ee874e71d9e9079295163e6047be8d000ec0da
4
- data.tar.gz: dced21a45bdb893b228b1ac6656eecfaa38bee92
3
+ metadata.gz: 93bf3ba6264276231731d04135d565544b718db2
4
+ data.tar.gz: dbc56dbd3b5b992dc9537c043eea071e61085140
5
5
  SHA512:
6
- metadata.gz: 4177cb40d2c6dfa46b6ce5435320b7b84d4d870846a59c82b48824a46d16466b92b16c38a7304cbf7ed48efc74fc421425bbaf99211e8751f2f737fdcb4c93f2
7
- data.tar.gz: 6e06c16092fe06fd6913575e3dbf618658a4ea1c1723187ac57ce680a785b4407ce181235b4bdd15e3e322b848e28f753c196baf8f05a4d18702cd8ab86d7397
6
+ metadata.gz: d1887e56355692e0edc5a4961237763a7dca030bc3326ef10874ed8e51541b9809add0ac9c340dae9ec5634fb5cbd0d8e8eb339fde42b86ef91a7b93827eed97
7
+ data.tar.gz: d10d1091249e6ec67815f36903049c570c04fcfe109ba9520c2a173bc54667f6eaca8cd7027d1bceaa692fb959313b92b6d348a8071ce9f0b874ceb80c9528e3
data/README.md CHANGED
@@ -21,7 +21,8 @@ You can get the develop branch of the plugin by specifying your Gemfile in this
21
21
 
22
22
  ## Configuration
23
23
 
24
- There is no UI configuration at this time.
24
+ The plugin comes with settings providing sane defaults for import. You can change them under Administer > Settings, TemplateSync tab.
25
+ These can be overriden for each import by passing options directly to a Rake task (see [Usage](https://github.com/theforeman/foreman_templates#usage) section for how to do that)
25
26
 
26
27
  ## Usage
27
28
 
@@ -42,7 +43,7 @@ template will be automatically associated with the OS
42
43
  #### Rake options
43
44
 
44
45
  * verbose => Print extra information during the run [false]
45
- * repo => Sync templates from a different Git repo [https://github.com/theforeman/community-templates]
46
+ * repo => Sync templates from a different repo [https://github.com/theforeman/community-templates]. Importing from git and file system is supported.
46
47
  * branch => Branch in Git repo [_see note below_]
47
48
  * prefix => The string all imported templates should begin with [Community]
48
49
  * dirname => The directory within the git tree containing the templates [/]
@@ -53,6 +54,8 @@ The `branch` default will use *develop* if you're on Foreman-nightly; or the
53
54
  matching *1.X-stable* branch for your version of Foreman (if it exists); or
54
55
  finally it will remain on the default branch as a fallback.
55
56
 
57
+ Passing any option to a Rake task overrides its default value from a corresponding Setting.
58
+
56
59
  #### Examples
57
60
 
58
61
  Just import all the templates from the default repo
@@ -71,6 +74,10 @@ Import templates from a subdirectory of a git repo:
71
74
 
72
75
  foreman-rake templates:sync repo="http://github.com/GregSutcliffe/community-templates" dirname='/subdir'
73
76
 
77
+ Import templates from file system:
78
+
79
+ foreman-rake templates:sync repo="/path/to/my/templates"
80
+
74
81
  ### Purge
75
82
 
76
83
  This task deletes matching templates from the Foreman DB
@@ -0,0 +1,54 @@
1
+ class Setting::TemplateSync < Setting
2
+ def self.associate_types
3
+ {
4
+ 'always' => _('Always'),
5
+ 'new' => _('New'),
6
+ 'never' => _('Never')
7
+ }
8
+ end
9
+
10
+ def self.metadata_export_mode_types
11
+ {
12
+ 'refresh' => _('Refresh'),
13
+ 'keep' => _('Keep'),
14
+ 'remove' => _('Remove')
15
+ }
16
+ end
17
+
18
+
19
+ def self.load_defaults
20
+ return unless super
21
+
22
+ %w(template_sync_filter template_sync_branch).each { |s| Setting::BLANK_ATTRS << s }
23
+
24
+ self.transaction do
25
+ [
26
+ 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'), "Community ", N_('Prefix')),
29
+ self.set('template_sync_dirname', N_('The directory within the Git repo containing the templates'), '/', N_('Dirname')),
30
+ 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_('Default Git repo to sync from'), 'https://github.com/theforeman/community-templates.git', N_('Repo')),
32
+ self.set('template_sync_negate', N_('Negate the prefix (for purging) / filter (for importing/exporting)'), false, N_('Negate')),
33
+ self.set('template_sync_branch', N_('Default branch in Git repo'), nil, N_('Branch')),
34
+ 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
+ ].compact.each { |s| self.create! s.update(:category => "Setting::TemplateSync") }
36
+ end
37
+
38
+ true
39
+ end
40
+
41
+ def validate_template_sync_associate(record)
42
+ values = record.class.associate_types.keys
43
+ if record.value && !values.include?(record.value)
44
+ record.errors[:base] << (_("template_sync_associate must be one of %s") % values.join(', '))
45
+ end
46
+ end
47
+
48
+ def validate_template_sync_metadata_export_mode(record)
49
+ values = record.class.metadata_export_mode_types.keys
50
+ if record.value && !values.include?(record.value)
51
+ record.errors[:base] << (_("template_sync_metadata_export_mode must be one of %s") % values.join(', '))
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,56 @@
1
+ module ForemanTemplates
2
+ class Action
3
+ delegate :logger, :to => :Rails
4
+
5
+ def self.setting_overrides
6
+ %i(verbose prefix dirname filter repo negate branch)
7
+ end
8
+
9
+ def method_missing(method, *args, &block)
10
+ if self.class.setting_overrides.include?(method)
11
+ instance_variable_get("@#{method}")
12
+ else
13
+ super
14
+ end
15
+ end
16
+
17
+ def repond_to_missing?(method, include_private = false)
18
+ self.class.setting_overrides.include?(method)
19
+ end
20
+
21
+ def initialize(args = {})
22
+ assign_attributes args
23
+ end
24
+
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
+ def git_repo?
37
+ @repo.start_with?('http://', 'https://', 'git://')
38
+ end
39
+
40
+ def get_absolute_repo_path
41
+ File.expand_path(@repo)
42
+ end
43
+
44
+ def verify_path!(path)
45
+ raise "Using file-based synchronization, but couldn't find #{path}" unless Dir.exist?(path)
46
+ end
47
+
48
+ private
49
+
50
+ def assign_attributes(args = {})
51
+ self.class.setting_overrides.each do |attribute|
52
+ instance_variable_set("@#{attribute}", args[attribute.to_sym] || Setting["template_sync_#{attribute}".to_sym])
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,110 @@
1
+ module ForemanTemplates
2
+ class TemplateExporter < Action
3
+ def self.setting_overrides
4
+ super + %i(metadata_export_mode)
5
+ end
6
+
7
+ def export!
8
+ if git_repo?
9
+ export_to_git
10
+ else
11
+ export_to_files
12
+ end
13
+
14
+ return true
15
+ end
16
+
17
+ def export_to_files
18
+ @dir = get_absolute_repo_path
19
+ verify_path!(@dir)
20
+ dump_files!
21
+ end
22
+
23
+ def export_to_git
24
+ @dir = Dir.mktmpdir
25
+
26
+ git_repo = Git.clone(@repo, @dir)
27
+ logger.debug "cloned #{@repo} to #{@dir}"
28
+ branch = @branch ? @branch : get_default_branch(git_repo)
29
+ # either checkout to existing or create a new one and checkout afterwards
30
+ if branch
31
+ if git_repo.is_branch?(branch)
32
+ git_repo.checkout(branch)
33
+ else
34
+ git_repo.branch(branch).checkout
35
+ if git_repo.is_remote_branch?(branch) # if we work with remote branch we need to sync it first
36
+ git_repo.reset_hard("origin/#{branch}")
37
+ end
38
+ end
39
+ end
40
+
41
+ dump_files!
42
+ git_repo.add
43
+
44
+ status = git_repo.status
45
+ if status.added.any? || status.changed.any? || status.deleted.any? || status.untracked.any?
46
+ logger.debug "committing changes in cloned repo"
47
+ git_repo.commit "Templates export made by Foreman user #{User.current.try(:login) || User::ANONYMOUS_ADMIN}"
48
+
49
+ logger.debug "pushing to branch #{branch} at origin #{@repo}"
50
+ git_repo.push 'origin', branch
51
+ else
52
+ logger.debug 'no change detected, skipping the commit and push'
53
+ end
54
+ ensure
55
+ FileUtils.remove_entry_secure(@dir) if File.exist?(@dir)
56
+ end
57
+
58
+ def dump_files!
59
+ templates_to_dump.map do |template|
60
+ current_dir = get_dump_dir(template)
61
+ FileUtils.mkdir_p current_dir
62
+
63
+ filename = File.join(current_dir, get_template_filename(template))
64
+ File.open(filename, 'w+') do |file|
65
+ logger.debug "Writing to file #{filename}"
66
+ bytes = file.write template.public_send(export_method)
67
+ logger.debug "finished writing #{bytes}"
68
+ end
69
+ end
70
+ end
71
+
72
+ def get_template_filename(template)
73
+ template.name.downcase.tr(' ', '_') + '.erb'
74
+ end
75
+
76
+ def get_dump_dir(template)
77
+ kind = template.respond_to?(:template_kind) ? template.template_kind.try(:name) || 'snippet' : nil
78
+ template_class_dir = template.model_name.human.pluralize.downcase.tr(' ', '_')
79
+ template_class_dir += '_templates' if template_class_dir == 'partition_tables'
80
+ File.join(@dir, dirname.to_s, template_class_dir, kind.to_s)
81
+ end
82
+
83
+ def templates_to_dump
84
+ base = Template.all
85
+ if filter.present?
86
+ method = negate ? :reject : :select
87
+ base.public_send(method) { |template| template.name.match(/#{filter}/i) }
88
+ else
89
+ base
90
+ end
91
+ end
92
+
93
+ # * refresh - template.to_erb stripping existing metadata,
94
+ # * remove - just template.template with stripping existing metadata,
95
+ # * keep - taking the whole template.template
96
+ def export_method
97
+ case @metadata_export_mode
98
+ when 'refresh'
99
+ :to_erb
100
+ when 'remove'
101
+ :template_without_metadata
102
+ when 'keep'
103
+ :template
104
+ else
105
+ raise "Unknown metadata export mode #{@metadata_export_mode}"
106
+ end
107
+ end
108
+
109
+ end
110
+ end
@@ -2,20 +2,15 @@ class NoKindError < Exception; end
2
2
  class MissingKindError < Exception; end
3
3
 
4
4
  module ForemanTemplates
5
- class TemplateImporter
6
- delegate :logger, :to => :Rails
5
+ class TemplateImporter < Action
7
6
  attr_accessor :metadata, :name, :text
8
7
 
9
- def initialize(args = {})
10
- @verbose = args[:verbose] || false
11
- @associate = args[:associate] || 'new'
12
- @prefix = args[:prefix] || 'Community '
13
- @dirname = args[:dirname] || '/'
14
- @filter = args[:filter] || nil
15
- @repo = args[:repo] || 'https://github.com/theforeman/community-templates.git'
16
- @negate = args[:negate] || false
17
- @branch = args[:branch] || false
8
+ def self.setting_overrides
9
+ super + %i(associate)
10
+ end
18
11
 
12
+ def initialize(args = {})
13
+ super
19
14
  # Rake hands off strings, not booleans, and "false" is true...
20
15
  if @verbose.is_a?(String)
21
16
  @verbose = if @verbose == 'false'
@@ -27,6 +22,20 @@ module ForemanTemplates
27
22
  end
28
23
 
29
24
  def import!
25
+ if git_repo?
26
+ import_from_git
27
+ else
28
+ import_from_files
29
+ end
30
+ end
31
+
32
+ def import_from_files
33
+ @dir = get_absolute_repo_path
34
+ verify_path!(@dir)
35
+ return parse_files!
36
+ end
37
+
38
+ def import_from_git
30
39
  # Check out the community templates to a temp location
31
40
  @dir = Dir.mktmpdir
32
41
 
@@ -56,10 +65,12 @@ module ForemanTemplates
56
65
  filename = template.split('/').last
57
66
  title = filename.split('.').first
58
67
  name = metadata['name'] || title
59
- name = [@prefix, name].compact.join
60
- next if @filter && !name.match(/#{@filter}/i)
61
-
62
- raise MissingKindError unless metadata['kind']
68
+ name = auto_prefix(name)
69
+ if @filter
70
+ matching = name.match(/#{@filter}/i)
71
+ matching = !matching if @negate
72
+ next if !matching
73
+ end
63
74
 
64
75
  begin
65
76
  # Expects a return of { :diff, :status, :result }
@@ -102,6 +113,10 @@ module ForemanTemplates
102
113
  result_lines
103
114
  end
104
115
 
116
+ def auto_prefix(name)
117
+ name.start_with?(@prefix) ? name : [@prefix, name].compact.join
118
+ end
119
+
105
120
  def calculate_diff(old, new)
106
121
  if old != new
107
122
  Diffy::Diff.new(old, new, :include_diff_info => true).to_s(:color)
@@ -110,17 +125,6 @@ module ForemanTemplates
110
125
  end
111
126
  end
112
127
 
113
- def get_default_branch(repo)
114
- branch_names = repo.branches.map(&:name).uniq
115
-
116
- # Always use develop on Foreman-nightly, if present, or else relevant stable branch
117
- target = SETTINGS[:version].tag == 'develop' ? 'develop' : "#{SETTINGS[:version].short}-stable"
118
- return target if branch_names.include?(target)
119
-
120
- # stay on default branch as fallback
121
- nil
122
- end
123
-
124
128
  def parse_metadata(text)
125
129
  # Pull out the first erb comment only - /m is for a multiline regex
126
130
  extracted = text.match(/<%\#[\t a-z0-9=:]*(.+?).-?%>/m)
@@ -9,9 +9,13 @@ module ForemanTemplates
9
9
  class Engine < ::Rails::Engine
10
10
  engine_name 'foreman_templates'
11
11
 
12
+ initializer 'foreman_templates.load_default_settings', :before => :load_config_initializers do
13
+ require_dependency File.expand_path('../../../app/models/setting/template_sync.rb', __FILE__) if (Setting.table_exists? rescue(false))
14
+ end
15
+
12
16
  initializer 'foreman_templates.register_plugin', :before => :finisher_hook do
13
17
  Foreman::Plugin.register :foreman_templates do
14
- requires_foreman '>= 1.12'
18
+ requires_foreman '>= 1.14'
15
19
  end
16
20
  end
17
21
 
@@ -1,3 +1,3 @@
1
1
  module ForemanTemplates
2
- VERSION = '3.1.0'.freeze
2
+ VERSION = '4.0.1'.freeze
3
3
  end
@@ -1,7 +1,10 @@
1
1
  # Tasks
2
2
  namespace :templates do
3
- desc 'Synchronize templates from a git repo'
4
- task :sync => :environment do
3
+ desc 'Import templates according to settings'
4
+ task :import => :environment do
5
+ if Rake.application.top_level_tasks.include?('templates:sync')
6
+ ActiveSupport::Deprecation.warn('templates:sync task has been renamed to templates:import and will be removed in a future version')
7
+ end
5
8
  # Available options:
6
9
  #* verbose => Print extra information during the run [false]
7
10
  #* repo => Sync templates from a different Git repo [https://github.com/theforeman/community-templates]
@@ -24,6 +27,24 @@ namespace :templates do
24
27
  puts results.join("\n")
25
28
  end
26
29
 
30
+ task :sync => :import
31
+
32
+ desc 'Export templates according to settings'
33
+ task :export => :environment do
34
+ ForemanTemplates::TemplateExporter.new({
35
+ verbose: ENV['verbose'],
36
+ repo: ENV['repo'],
37
+ branch: ENV['branch'],
38
+ prefix: ENV['prefix'],
39
+ dirname: ENV['dirname'],
40
+ filter: ENV['filter'],
41
+ # associate: ENV['associate'],
42
+ metadata_export_mode: ENV['metadata_export_mode'],
43
+ }).export!
44
+
45
+ puts 'Export finished'
46
+ end
47
+
27
48
  desc 'Purge unwanted templates from foreman'
28
49
  task :purge => :environment do
29
50
  ForemanTemplates::TemplateImporter.new({
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: 3.1.0
4
+ version: 4.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: 2016-10-03 00:00:00.000000000 Z
11
+ date: 2017-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: diffy
@@ -52,6 +52,9 @@ files:
52
52
  - app/models/concerns/foreman_templates/provisioning_template_import.rb
53
53
  - app/models/concerns/foreman_templates/ptable_import.rb
54
54
  - app/models/concerns/foreman_templates/template_import.rb
55
+ - app/models/setting/template_sync.rb
56
+ - app/services/foreman_templates/action.rb
57
+ - app/services/foreman_templates/template_exporter.rb
55
58
  - app/services/foreman_templates/template_importer.rb
56
59
  - lib/foreman_templates.rb
57
60
  - lib/foreman_templates/engine.rb