foreman_templates 9.0.0 → 9.2.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/app/controllers/api/v2/template_controller.rb +3 -3
- data/app/controllers/ui_template_syncs_controller.rb +9 -3
- data/app/services/foreman_templates/template_exporter.rb +1 -1
- data/app/services/foreman_templates/template_importer.rb +1 -1
- data/app/views/template_sync_settings/show.json.rabl +2 -2
- data/app/views/template_syncs/index.html.erb +14 -17
- data/app/views/ui_template_syncs/template_attrs.json.rabl +1 -1
- data/db/migrate/20211122154929_templates_settings_category_to_dsl.rb +5 -0
- data/lib/foreman_templates/engine.rb +76 -10
- data/lib/foreman_templates/version.rb +1 -1
- data/lib/foreman_templates.rb +15 -0
- data/lib/tasks/foreman_templates_tasks.rake +10 -9
- data/webpack/ForemanTemplates.js +17 -13
- data/webpack/__mocks__/foremanReact/Root/Context/ForemanContext.js +2 -0
- data/webpack/__mocks__/foremanReact/components/Pagination/index.js +2 -0
- data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/NewTemplateSyncForm.js +95 -140
- data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/NewTemplateSyncFormHelpers.js +43 -0
- data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/index.js +0 -4
- data/webpack/components/TemplateSyncResult/TemplateSyncResultHelpers.js +2 -2
- data/webpack/components/TemplateSyncResult/TemplateSyncResultReducer.js +1 -1
- data/webpack/components/TemplateSyncResult/__tests__/__snapshots__/TemplateSyncResultReducer.test.js.snap +2 -2
- data/webpack/components/TemplateSyncResult/components/SyncResultList.js +11 -6
- data/webpack/components/TemplateSyncResult/components/__tests__/SyncResultList.test.js +1 -1
- data/webpack/components/TemplateSyncResult/components/__tests__/__snapshots__/SyncResultList.test.js.snap +3 -9
- metadata +7 -5
- data/app/models/setting/template_sync.rb +0 -115
- data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +0 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bda8e472a4ae76b0f1480738e9059423a249c4156842deebc385baa2f3c2a5ca
|
|
4
|
+
data.tar.gz: bb04b38ce6791e62f90fcea5a177d38ca62402e6c3037e7f3ed85c416f91696c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3c35d3ca52df290a50a3e1788ea654a0588067ab02278a5b77829bfaec46d8c855ae36f554a608eaf8e9c5797b650d5be1a95ed4e7f8486c905e601068180fc5
|
|
7
|
+
data.tar.gz: b58a200b8374f22481e1397949cc4126315234b6238ce08895acedb628c826515ce9ab514b85942b8388350f0e8939b0d088ccc6641fc4b3b84a1fc65ef16961
|
|
@@ -17,9 +17,9 @@ module Api
|
|
|
17
17
|
|
|
18
18
|
api :POST, "/templates/import/", N_("Initiate Import")
|
|
19
19
|
param :prefix, String, :required => false, :desc => N_("The string all imported templates should begin with.")
|
|
20
|
-
param :associate,
|
|
20
|
+
param :associate, ForemanTemplates.associate_types.keys, :required => false, :desc => N_("Associate to OS's, Locations & Organizations. Options are: always, new or never.")
|
|
21
21
|
param :force, :bool, :required => false, :desc => N_("Update templates that are locked")
|
|
22
|
-
param :lock,
|
|
22
|
+
param :lock, ForemanTemplates.lock_types.keys + ["true", "false", "0", "1"], :required => false, :desc => N_("Lock imported templates")
|
|
23
23
|
param :verbose, :bool, :required => false, :desc => N_("Show template diff in response")
|
|
24
24
|
param_group :foreman_template_sync_params
|
|
25
25
|
param_group :taxonomies, ::Api::V2::BaseController
|
|
@@ -32,7 +32,7 @@ module Api
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
api :POST, "/templates/export", N_("Initiate Export")
|
|
35
|
-
param :metadata_export_mode,
|
|
35
|
+
param :metadata_export_mode, ForemanTemplates.metadata_export_mode_types.keys, :required => false, :desc => N_("Specify how to handle metadata")
|
|
36
36
|
param :commit_msg, String, :desc => N_("Custom commit message for templates export")
|
|
37
37
|
param_group :foreman_template_sync_params
|
|
38
38
|
param_group :taxonomies, ::Api::V2::BaseController
|
|
@@ -8,8 +8,8 @@ class UiTemplateSyncsController < ApplicationController
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def sync_settings
|
|
11
|
-
import_settings =
|
|
12
|
-
export_settings =
|
|
11
|
+
import_settings = setting_definitions(ForemanTemplates::IMPORT_SETTING_NAMES)
|
|
12
|
+
export_settings = setting_definitions(ForemanTemplates::EXPORT_SETTING_NAMES)
|
|
13
13
|
@results = OpenStruct.new(:import => import_settings, :export => export_settings)
|
|
14
14
|
end
|
|
15
15
|
|
|
@@ -43,6 +43,12 @@ class UiTemplateSyncsController < ApplicationController
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def render_errors(messages, severity = 'danger')
|
|
46
|
-
render :json => { :error => { :errors => { :base => messages }, :severity => severity } }, :status => :unprocessable_entity
|
|
46
|
+
render :json => { :error => { :errors => { :base => messages }, full_messages: messages, :severity => severity } }, :status => :unprocessable_entity
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def setting_definitions(short_names)
|
|
52
|
+
short_names.map { |name| Foreman.settings.find("template_sync_#{name}") }
|
|
47
53
|
end
|
|
48
54
|
end
|
|
@@ -94,7 +94,7 @@ module ForemanTemplates
|
|
|
94
94
|
def templates_to_dump
|
|
95
95
|
find_templates.each do |template|
|
|
96
96
|
if filter.present?
|
|
97
|
-
exportable =
|
|
97
|
+
exportable = /#{filter}/i.match?(template.name) ? !negate : negate
|
|
98
98
|
result = ExportResult.new(template, exportable)
|
|
99
99
|
next @result_lines << result.matching_filter unless exportable
|
|
100
100
|
|
|
@@ -70,7 +70,7 @@ module ForemanTemplates
|
|
|
70
70
|
@result_lines << parse_result.check_for_errors
|
|
71
71
|
rescue NameError => e
|
|
72
72
|
@result_lines << parse_result.name_error(e, metadata['model'])
|
|
73
|
-
rescue => e
|
|
73
|
+
rescue StandardError => e
|
|
74
74
|
@result_lines << parse_result.add_exception(e)
|
|
75
75
|
end
|
|
76
76
|
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
object @setting
|
|
2
2
|
|
|
3
3
|
node do |setting|
|
|
4
|
-
{ :name => setting.
|
|
4
|
+
{ :name => setting.name.delete_prefix('template_sync_') }
|
|
5
5
|
end
|
|
6
6
|
|
|
7
7
|
attributes :id, :value, :description, :settings_type, :default, :full_name
|
|
8
8
|
|
|
9
9
|
node do |setting|
|
|
10
|
-
{ :selection => setting.
|
|
10
|
+
{ :selection => (setting.select_values || {}).map { |key, label| { value: key, label: label } } }
|
|
11
11
|
end
|
|
@@ -5,20 +5,17 @@
|
|
|
5
5
|
<%= webpacked_plugins_css_for :foreman_templates %>
|
|
6
6
|
<% end %>
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
:export => authorized_for(:controller => :ui_template_syncs, :action => :export)
|
|
23
|
-
}
|
|
24
|
-
}.to_json )%>
|
|
8
|
+
<%= react_component('ForemanTemplates',
|
|
9
|
+
{ :apiUrls => {
|
|
10
|
+
:exportUrl => export_ui_template_syncs_path,
|
|
11
|
+
:syncSettingsUrl => sync_settings_ui_template_syncs_path,
|
|
12
|
+
:importUrl => import_ui_template_syncs_path
|
|
13
|
+
},
|
|
14
|
+
:validationData => { :repo => ForemanTemplates::Action.repo_start_with },
|
|
15
|
+
:editPaths => edit_paths,
|
|
16
|
+
:fileRepoStartWith => ForemanTemplates::Action.file_repo_start_with,
|
|
17
|
+
:userPermissions => {
|
|
18
|
+
:import => authorized_for(:controller => :ui_template_syncs, :action => :import),
|
|
19
|
+
:export => authorized_for(:controller => :ui_template_syncs, :action => :export)
|
|
20
|
+
}
|
|
21
|
+
})%>
|
|
@@ -11,7 +11,7 @@ node(:class_name) do |template|
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
node(:humanized_class_name) do |template|
|
|
14
|
-
template.class.name.underscore.split('_').map
|
|
14
|
+
template.class.name.underscore.split('_').map(&:capitalize).join(' ')
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
node(:can_edit) do |template|
|
|
@@ -10,10 +10,6 @@ module ForemanTemplates
|
|
|
10
10
|
class Engine < ::Rails::Engine
|
|
11
11
|
engine_name 'foreman_templates'
|
|
12
12
|
|
|
13
|
-
initializer 'foreman_templates.load_default_settings', :before => :load_config_initializers do
|
|
14
|
-
require_dependency File.expand_path('../../app/models/setting/template_sync.rb', __dir__) if (Setting.table_exists? rescue(false))
|
|
15
|
-
end
|
|
16
|
-
|
|
17
13
|
initializer "foreman_templates.add_rabl_view_path" do
|
|
18
14
|
Rabl.configure do |config|
|
|
19
15
|
config.view_paths << ForemanTemplates::Engine.root.join('app', 'views')
|
|
@@ -28,10 +24,78 @@ module ForemanTemplates
|
|
|
28
24
|
|
|
29
25
|
initializer 'foreman_templates.register_plugin', :before => :finisher_hook do
|
|
30
26
|
Foreman::Plugin.register :foreman_templates do
|
|
31
|
-
requires_foreman '>=
|
|
27
|
+
requires_foreman '>= 3.2'
|
|
32
28
|
|
|
33
29
|
apipie_documented_controllers ["#{ForemanTemplates::Engine.root}/app/controllers/api/v2/*.rb"]
|
|
34
30
|
|
|
31
|
+
settings do
|
|
32
|
+
category(:template_sync, N_('Template Sync')) do
|
|
33
|
+
setting('template_sync_verbose',
|
|
34
|
+
type: :boolean,
|
|
35
|
+
description: N_('Choose verbosity for Rake task importing templates'),
|
|
36
|
+
default: false,
|
|
37
|
+
full_name: N_('Verbosity'))
|
|
38
|
+
setting('template_sync_associate',
|
|
39
|
+
type: :string,
|
|
40
|
+
description: N_('Associate templates to OS, organization and location'),
|
|
41
|
+
default: 'new',
|
|
42
|
+
full_name: N_('Associate'),
|
|
43
|
+
collection: -> { ForemanTemplates.associate_types })
|
|
44
|
+
setting('template_sync_prefix',
|
|
45
|
+
type: :string,
|
|
46
|
+
description: N_('The string that will be added as prefix to imported templates'),
|
|
47
|
+
default: "",
|
|
48
|
+
full_name: N_('Prefix'))
|
|
49
|
+
setting('template_sync_dirname',
|
|
50
|
+
type: :string,
|
|
51
|
+
description: N_('The directory within the Git repo containing the templates'),
|
|
52
|
+
default: '/',
|
|
53
|
+
full_name: N_('Dirname'))
|
|
54
|
+
setting('template_sync_filter',
|
|
55
|
+
type: :string,
|
|
56
|
+
description: N_('Import/export names matching this regex (case-insensitive; snippets are not filtered)'),
|
|
57
|
+
default: '',
|
|
58
|
+
full_name: N_('Filter'))
|
|
59
|
+
setting('template_sync_repo',
|
|
60
|
+
type: :string,
|
|
61
|
+
description: N_('Target path to import/export. Different protocols can be used, for example /tmp/dir, git://example.com, https://example.com, ssh://example.com. When exporting to /tmp, note that production deployments may be configured to use private tmp.'),
|
|
62
|
+
default: 'https://github.com/theforeman/community-templates.git',
|
|
63
|
+
full_name: N_('Repo'))
|
|
64
|
+
setting('template_sync_negate',
|
|
65
|
+
type: :boolean,
|
|
66
|
+
description: N_('Negate the filter for import/export'),
|
|
67
|
+
default: false,
|
|
68
|
+
full_name: N_('Negate'))
|
|
69
|
+
setting('template_sync_branch',
|
|
70
|
+
type: :string,
|
|
71
|
+
description: N_('Default branch in Git repo'),
|
|
72
|
+
default: '',
|
|
73
|
+
full_name: N_('Branch'))
|
|
74
|
+
setting('template_sync_metadata_export_mode',
|
|
75
|
+
type: :string,
|
|
76
|
+
description: N_('Default metadata export mode, refresh re-renders metadata, keep will keep existing metadata, remove exports template without metadata'),
|
|
77
|
+
default: 'refresh',
|
|
78
|
+
full_name: N_('Metadata export mode'),
|
|
79
|
+
collection: -> { ForemanTemplates.metadata_export_mode_types })
|
|
80
|
+
setting('template_sync_force',
|
|
81
|
+
type: :boolean,
|
|
82
|
+
description: N_('Should importing overwrite locked templates?'),
|
|
83
|
+
default: false,
|
|
84
|
+
full_name: N_('Force import'))
|
|
85
|
+
setting('template_sync_lock',
|
|
86
|
+
type: :string,
|
|
87
|
+
description: N_('How to handle lock for imported templates?'),
|
|
88
|
+
default: 'keep',
|
|
89
|
+
full_name: N_('Lock templates'),
|
|
90
|
+
collection: -> { ForemanTemplates.lock_types })
|
|
91
|
+
setting('template_sync_commit_msg',
|
|
92
|
+
type: :string,
|
|
93
|
+
description: N_('Custom commit message for templates export'),
|
|
94
|
+
default: 'Templates export made by a Foreman user',
|
|
95
|
+
full_name: N_('Commit message'))
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
35
99
|
security_block :templates do
|
|
36
100
|
permission :import_templates, {
|
|
37
101
|
:"api/v2/template" => [:import],
|
|
@@ -49,15 +113,17 @@ module ForemanTemplates
|
|
|
49
113
|
add_all_permissions_to_default_roles
|
|
50
114
|
|
|
51
115
|
menu :top_menu, :template_sync,
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
116
|
+
:url_hash => { :controller => :template_syncs, :action => :index },
|
|
117
|
+
:caption => N_('Sync Templates'),
|
|
118
|
+
:parent => :hosts_menu,
|
|
119
|
+
:before => :ptables,
|
|
120
|
+
:turbolinks => false
|
|
57
121
|
end
|
|
58
122
|
end
|
|
59
123
|
|
|
60
124
|
config.to_prepare do
|
|
125
|
+
Setting::NOT_STRIPPED << 'template_sync_prefix'
|
|
126
|
+
|
|
61
127
|
Template.include ForemanTemplates::TemplateExtensions
|
|
62
128
|
end
|
|
63
129
|
end
|
data/lib/foreman_templates.rb
CHANGED
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
require 'foreman_templates/engine'
|
|
2
2
|
|
|
3
3
|
module ForemanTemplates
|
|
4
|
+
BASE_SETTING_NAMES = %w(repo branch dirname filter negate).freeze
|
|
5
|
+
IMPORT_SETTING_NAMES = (BASE_SETTING_NAMES | %w(prefix associate force lock)).freeze
|
|
6
|
+
EXPORT_SETTING_NAMES = (BASE_SETTING_NAMES | %w(metadata_export_mode commit_msg)).freeze
|
|
7
|
+
|
|
8
|
+
def self.associate_types
|
|
9
|
+
{ 'always' => _('Always'), 'new' => _('New'), 'never' => _('Never') }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.lock_types
|
|
13
|
+
{ 'lock' => _('Lock'), 'keep_lock_new' => _('Keep, lock new'), 'keep' => _('Keep, do not lock new'), 'unlock' => _('Unlock') }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.metadata_export_mode_types
|
|
17
|
+
{ 'refresh' => _('Refresh'), 'keep' => _('Keep'), 'remove' => _('Remove') }
|
|
18
|
+
end
|
|
4
19
|
end
|
|
@@ -20,14 +20,14 @@ namespace :templates do
|
|
|
20
20
|
verbose = ENV['verbose']
|
|
21
21
|
|
|
22
22
|
results = ForemanTemplates::TemplateImporter.new({
|
|
23
|
-
verbose:
|
|
24
|
-
repo:
|
|
25
|
-
branch:
|
|
26
|
-
prefix:
|
|
27
|
-
dirname:
|
|
28
|
-
filter:
|
|
23
|
+
verbose: verbose,
|
|
24
|
+
repo: ENV['repo'],
|
|
25
|
+
branch: ENV['branch'],
|
|
26
|
+
prefix: ENV['prefix'],
|
|
27
|
+
dirname: ENV['dirname'],
|
|
28
|
+
filter: ENV['filter'],
|
|
29
29
|
associate: ENV['associate'],
|
|
30
|
-
lock:
|
|
30
|
+
lock: ENV['lock'],
|
|
31
31
|
}).import!
|
|
32
32
|
pp(results[:results].map { |result| result.to_h(verbose) })
|
|
33
33
|
end
|
|
@@ -58,8 +58,8 @@ namespace :templates do
|
|
|
58
58
|
# * negate => negate query [false]
|
|
59
59
|
# * prefix => The string all templates to purge should ( or not ) begin with [Community ]
|
|
60
60
|
# * verbose => Print extra information during the run [false]
|
|
61
|
-
negate:
|
|
62
|
-
prefix:
|
|
61
|
+
negate: ENV['negate'],
|
|
62
|
+
prefix: ENV['prefix'],
|
|
63
63
|
verbose: ENV['verbose'],
|
|
64
64
|
}).purge!
|
|
65
65
|
end
|
|
@@ -89,6 +89,7 @@ namespace :foreman_templates do
|
|
|
89
89
|
begin
|
|
90
90
|
require 'rubocop/rake_task'
|
|
91
91
|
RuboCop::RakeTask.new(:rubocop_foreman_templates) do |task|
|
|
92
|
+
task.options = ['--config', ForemanTemplates::Engine.root.join('.rubocop.yml').to_s]
|
|
92
93
|
task.patterns = ["#{ForemanTemplates::Engine.root}/app/**/*.rb",
|
|
93
94
|
"#{ForemanTemplates::Engine.root}/lib/**/*.rb",
|
|
94
95
|
"#{ForemanTemplates::Engine.root}/test/**/*.rb"]
|
data/webpack/ForemanTemplates.js
CHANGED
|
@@ -4,26 +4,30 @@ import PropTypes from 'prop-types';
|
|
|
4
4
|
|
|
5
5
|
import Routes from './Routes';
|
|
6
6
|
|
|
7
|
-
const ForemanTemplates = ({
|
|
7
|
+
const ForemanTemplates = ({
|
|
8
|
+
apiUrls,
|
|
9
|
+
validationData,
|
|
10
|
+
fileRepoStartWith,
|
|
11
|
+
userPermissions,
|
|
12
|
+
editPaths,
|
|
13
|
+
}) => (
|
|
8
14
|
<Router>
|
|
9
15
|
<Routes
|
|
10
|
-
apiUrls={
|
|
11
|
-
validationData={
|
|
12
|
-
editPaths={
|
|
13
|
-
fileRepoStartWith={
|
|
14
|
-
userPermissions={
|
|
16
|
+
apiUrls={apiUrls}
|
|
17
|
+
validationData={validationData}
|
|
18
|
+
editPaths={editPaths}
|
|
19
|
+
fileRepoStartWith={fileRepoStartWith}
|
|
20
|
+
userPermissions={userPermissions}
|
|
15
21
|
/>
|
|
16
22
|
</Router>
|
|
17
23
|
);
|
|
18
24
|
|
|
19
25
|
ForemanTemplates.propTypes = {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
fileRepoStartWith: PropTypes.array,
|
|
26
|
-
}).isRequired,
|
|
26
|
+
apiUrls: PropTypes.object.isRequired,
|
|
27
|
+
validationData: PropTypes.object.isRequired,
|
|
28
|
+
editPaths: PropTypes.object.isRequired,
|
|
29
|
+
userPermissions: PropTypes.object.isRequired,
|
|
30
|
+
fileRepoStartWith: PropTypes.array.isRequired,
|
|
27
31
|
};
|
|
28
32
|
|
|
29
33
|
export default ForemanTemplates;
|
data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/NewTemplateSyncForm.js
CHANGED
|
@@ -1,159 +1,116 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { compose } from 'redux';
|
|
4
4
|
|
|
5
5
|
import ForemanForm from 'foremanReact/components/common/forms/ForemanForm';
|
|
6
|
-
import
|
|
6
|
+
import {
|
|
7
|
+
useForemanLocation,
|
|
8
|
+
useForemanOrganization,
|
|
9
|
+
} from 'foremanReact/Root/Context/ForemanContext';
|
|
10
|
+
|
|
7
11
|
import SyncSettingsFields from '../SyncSettingFields';
|
|
8
12
|
import SyncTypeRadios from '../SyncTypeRadios';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
', '
|
|
36
|
-
)}`,
|
|
37
|
-
repoFormat(validationData.repo)
|
|
38
|
-
)
|
|
39
|
-
.required("can't be blank"),
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
return memo;
|
|
43
|
-
},
|
|
44
|
-
{}
|
|
13
|
+
import { redirectToResult, syncFormSchema } from './NewTemplateSyncFormHelpers';
|
|
14
|
+
|
|
15
|
+
const NewTemplateSyncForm = ({
|
|
16
|
+
error,
|
|
17
|
+
submitForm,
|
|
18
|
+
importSettings,
|
|
19
|
+
exportSettings,
|
|
20
|
+
history,
|
|
21
|
+
validationData,
|
|
22
|
+
importUrl,
|
|
23
|
+
exportUrl,
|
|
24
|
+
initialValues,
|
|
25
|
+
userPermissions,
|
|
26
|
+
}) => {
|
|
27
|
+
const allowedSyncType = (currentUserPermissions, radioAttrs) =>
|
|
28
|
+
currentUserPermissions[radioAttrs.permission];
|
|
29
|
+
|
|
30
|
+
const radioButtons = [
|
|
31
|
+
{ label: 'Import', value: 'import', permission: 'import' },
|
|
32
|
+
{ label: 'Export', value: 'export', permission: 'export' },
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const [syncType, setSyncType] = useState(
|
|
36
|
+
radioButtons.find(radioAttrs =>
|
|
37
|
+
allowedSyncType(userPermissions, radioAttrs)
|
|
38
|
+
).value
|
|
45
39
|
);
|
|
46
40
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
class NewTemplateSyncForm extends React.Component {
|
|
53
|
-
allowedSyncType = (userPermissions, radioAttrs) =>
|
|
54
|
-
this.props.userPermissions[radioAttrs.permission];
|
|
55
|
-
|
|
56
|
-
constructor(props) {
|
|
57
|
-
super(props);
|
|
58
|
-
|
|
59
|
-
this.radioButtons = [
|
|
60
|
-
{ label: 'Import', value: 'import', permission: 'import' },
|
|
61
|
-
{ label: 'Export', value: 'export', permission: 'export' },
|
|
62
|
-
];
|
|
63
|
-
|
|
64
|
-
this.state = {
|
|
65
|
-
syncType: this.radioButtons.find(radioAttrs =>
|
|
66
|
-
this.allowedSyncType(props.userPermissions, radioAttrs)
|
|
67
|
-
).value,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
updateSyncType = event => {
|
|
72
|
-
this.setState({ syncType: event.target.value });
|
|
41
|
+
const updateSyncType = event => {
|
|
42
|
+
setSyncType(event.target.value);
|
|
73
43
|
};
|
|
74
44
|
|
|
75
|
-
permitRadioButtons = buttons =>
|
|
45
|
+
const permitRadioButtons = buttons =>
|
|
76
46
|
buttons.filter(buttonAttrs =>
|
|
77
|
-
|
|
47
|
+
allowedSyncType(userPermissions, buttonAttrs)
|
|
78
48
|
);
|
|
79
49
|
|
|
80
|
-
initRadioButtons =
|
|
81
|
-
|
|
50
|
+
const initRadioButtons = templateSyncType =>
|
|
51
|
+
permitRadioButtons(radioButtons).map(buttonAttrs => ({
|
|
82
52
|
get checked() {
|
|
83
|
-
return
|
|
53
|
+
return buttonAttrs.value === templateSyncType;
|
|
84
54
|
},
|
|
85
|
-
onChange:
|
|
55
|
+
onChange: updateSyncType,
|
|
86
56
|
...buttonAttrs,
|
|
87
57
|
}));
|
|
88
58
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
controlLabel="Action type"
|
|
145
|
-
radios={this.initRadioButtons(this.state.syncType)}
|
|
146
|
-
/>
|
|
147
|
-
<SyncSettingsFields
|
|
148
|
-
importSettings={importSettings}
|
|
149
|
-
exportSettings={exportSettings}
|
|
150
|
-
syncType={this.state.syncType}
|
|
151
|
-
resetField={resetToDefault}
|
|
152
|
-
/>
|
|
153
|
-
</ForemanForm>
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
59
|
+
const addTaxParams = (key, currentTax) => params => {
|
|
60
|
+
if (currentTax && currentTax.id) {
|
|
61
|
+
return { ...params, [key]: [currentTax.id] };
|
|
62
|
+
}
|
|
63
|
+
return params;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const addOrgParams = addTaxParams(
|
|
67
|
+
'organization_ids',
|
|
68
|
+
useForemanOrganization()
|
|
69
|
+
);
|
|
70
|
+
const addLocParams = addTaxParams('location_ids', useForemanLocation());
|
|
71
|
+
|
|
72
|
+
const resetToDefault = (fieldName, fieldValue) => resetFn =>
|
|
73
|
+
resetFn(fieldName, fieldValue);
|
|
74
|
+
|
|
75
|
+
const handleSubmit = (values, actions) => {
|
|
76
|
+
const url = syncType === 'import' ? importUrl : exportUrl;
|
|
77
|
+
return submitForm({
|
|
78
|
+
url,
|
|
79
|
+
values: compose(addLocParams, addOrgParams)(values[syncType]),
|
|
80
|
+
message: `Templates were ${syncType}ed.`,
|
|
81
|
+
item: 'TemplateSync',
|
|
82
|
+
actions,
|
|
83
|
+
successCallback: () =>
|
|
84
|
+
history.replace({ pathname: '/template_syncs/result' }),
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<ForemanForm
|
|
90
|
+
onSubmit={handleSubmit}
|
|
91
|
+
initialValues={initialValues}
|
|
92
|
+
validationSchema={syncFormSchema(
|
|
93
|
+
syncType,
|
|
94
|
+
{ import: importSettings, export: exportSettings },
|
|
95
|
+
validationData
|
|
96
|
+
)}
|
|
97
|
+
onCancel={redirectToResult(history)}
|
|
98
|
+
error={error}
|
|
99
|
+
>
|
|
100
|
+
<SyncTypeRadios
|
|
101
|
+
name="syncType"
|
|
102
|
+
controlLabel="Action type"
|
|
103
|
+
radios={initRadioButtons(syncType)}
|
|
104
|
+
/>
|
|
105
|
+
<SyncSettingsFields
|
|
106
|
+
importSettings={importSettings}
|
|
107
|
+
exportSettings={exportSettings}
|
|
108
|
+
syncType={syncType}
|
|
109
|
+
resetField={resetToDefault}
|
|
110
|
+
/>
|
|
111
|
+
</ForemanForm>
|
|
112
|
+
);
|
|
113
|
+
};
|
|
157
114
|
|
|
158
115
|
NewTemplateSyncForm.propTypes = {
|
|
159
116
|
importSettings: PropTypes.array,
|
|
@@ -166,8 +123,6 @@ NewTemplateSyncForm.propTypes = {
|
|
|
166
123
|
exportUrl: PropTypes.string.isRequired,
|
|
167
124
|
importUrl: PropTypes.string.isRequired,
|
|
168
125
|
submitForm: PropTypes.func.isRequired,
|
|
169
|
-
currentLocation: PropTypes.object.isRequired,
|
|
170
|
-
currentOrganization: PropTypes.object.isRequired,
|
|
171
126
|
};
|
|
172
127
|
|
|
173
128
|
NewTemplateSyncForm.defaultProps = {
|
data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/NewTemplateSyncFormHelpers.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as Yup from 'yup';
|
|
2
|
+
|
|
3
|
+
export const redirectToResult = history => () =>
|
|
4
|
+
history.push({ pathname: '/template_syncs/result' });
|
|
5
|
+
|
|
6
|
+
const repoFormat = formatAry => value => {
|
|
7
|
+
if (value === undefined) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const valid = formatAry
|
|
12
|
+
.map(item => value.startsWith(item))
|
|
13
|
+
.reduce((memo, item) => item || memo, false);
|
|
14
|
+
|
|
15
|
+
return value && valid;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const syncFormSchema = (syncType, settingsObj, validationData) => {
|
|
19
|
+
const schema = (settingsObj[syncType].asMutable() || []).reduce(
|
|
20
|
+
(memo, setting) => {
|
|
21
|
+
if (setting.name === 'repo') {
|
|
22
|
+
return {
|
|
23
|
+
...memo,
|
|
24
|
+
repo: Yup.string()
|
|
25
|
+
.test(
|
|
26
|
+
'repo-format',
|
|
27
|
+
`Invalid repo format, must start with one of: ${validationData.repo.join(
|
|
28
|
+
', '
|
|
29
|
+
)}`,
|
|
30
|
+
repoFormat(validationData.repo)
|
|
31
|
+
)
|
|
32
|
+
.required("can't be blank"),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return memo;
|
|
36
|
+
},
|
|
37
|
+
{}
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return Yup.object().shape({
|
|
41
|
+
[syncType]: Yup.object().shape(schema),
|
|
42
|
+
});
|
|
43
|
+
};
|
|
@@ -2,8 +2,6 @@ import { connect } from 'react-redux';
|
|
|
2
2
|
|
|
3
3
|
import * as FormActions from 'foremanReact/redux/actions/common/forms';
|
|
4
4
|
|
|
5
|
-
import { selectLayout } from 'foremanReact/components/Layout/LayoutSelectors';
|
|
6
|
-
|
|
7
5
|
import NewTemplateSyncForm from './NewTemplateSyncForm';
|
|
8
6
|
|
|
9
7
|
import {
|
|
@@ -24,8 +22,6 @@ const mapStateToProps = (state, ownProps) => {
|
|
|
24
22
|
initialValues: { ...initialFormValues },
|
|
25
23
|
importSettings,
|
|
26
24
|
exportSettings,
|
|
27
|
-
currentOrganization: selectLayout(state).currentOrganization,
|
|
28
|
-
currentLocation: selectLayout(state).currentLocation,
|
|
29
25
|
};
|
|
30
26
|
};
|
|
31
27
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// move to some sort of pagination helper in core
|
|
2
2
|
export const templatesPage = (templates, pagination) => {
|
|
3
|
-
const offset = (pagination.page - 1) * pagination.
|
|
3
|
+
const offset = (pagination.page - 1) * pagination.per_page;
|
|
4
4
|
|
|
5
|
-
return templates.slice(offset, offset + pagination.
|
|
5
|
+
return templates.slice(offset, offset + pagination.per_page);
|
|
6
6
|
};
|
|
@@ -4,7 +4,7 @@ exports[`TemplateSyncResultReducer should return initial state 1`] = `
|
|
|
4
4
|
Object {
|
|
5
5
|
"pagination": Object {
|
|
6
6
|
"page": 1,
|
|
7
|
-
"
|
|
7
|
+
"per_page": 20,
|
|
8
8
|
},
|
|
9
9
|
"resultAction": "",
|
|
10
10
|
"templates": Array [],
|
|
@@ -27,7 +27,7 @@ Object {
|
|
|
27
27
|
"branch": "master",
|
|
28
28
|
"pagination": Object {
|
|
29
29
|
"page": 1,
|
|
30
|
-
"
|
|
30
|
+
"per_page": 20,
|
|
31
31
|
},
|
|
32
32
|
"repo": "https://github.com/theforeman/community-templates.git",
|
|
33
33
|
"resultAction": "import",
|
|
@@ -2,13 +2,19 @@ import React from 'react';
|
|
|
2
2
|
import { ListView } from 'patternfly-react';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
|
|
5
|
-
import Pagination from 'foremanReact/components/Pagination
|
|
5
|
+
import Pagination from 'foremanReact/components/Pagination';
|
|
6
6
|
|
|
7
7
|
import SyncedTemplate from './SyncedTemplate';
|
|
8
8
|
import { templatesPage } from '../TemplateSyncResultHelpers';
|
|
9
9
|
import ListViewHeader from './ListViewHeader';
|
|
10
10
|
|
|
11
|
-
const SyncResultList = ({
|
|
11
|
+
const SyncResultList = ({
|
|
12
|
+
pagination,
|
|
13
|
+
pagination: { page, per_page: perPage },
|
|
14
|
+
pageChange,
|
|
15
|
+
templates,
|
|
16
|
+
editPaths,
|
|
17
|
+
}) => (
|
|
12
18
|
<ListView>
|
|
13
19
|
<ListViewHeader />
|
|
14
20
|
{templatesPage(templates, pagination).map((template, idx) => (
|
|
@@ -19,11 +25,10 @@ const SyncResultList = ({ pagination, pageChange, templates, editPaths }) => (
|
|
|
19
25
|
/>
|
|
20
26
|
))}
|
|
21
27
|
<Pagination
|
|
22
|
-
viewType="list"
|
|
23
28
|
itemCount={templates.length}
|
|
24
|
-
pagination={pagination}
|
|
25
29
|
onChange={pageChange}
|
|
26
|
-
|
|
30
|
+
page={page}
|
|
31
|
+
perPage={perPage}
|
|
27
32
|
/>
|
|
28
33
|
</ListView>
|
|
29
34
|
);
|
|
@@ -31,7 +36,7 @@ const SyncResultList = ({ pagination, pageChange, templates, editPaths }) => (
|
|
|
31
36
|
SyncResultList.propTypes = {
|
|
32
37
|
pagination: PropTypes.shape({
|
|
33
38
|
page: PropTypes.number,
|
|
34
|
-
|
|
39
|
+
per_page: PropTypes.number,
|
|
35
40
|
}).isRequired,
|
|
36
41
|
pageChange: PropTypes.func.isRequired,
|
|
37
42
|
templates: PropTypes.array.isRequired,
|
|
@@ -88,17 +88,11 @@ exports[`SyncResultList should render 1`] = `
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
/>
|
|
91
|
-
<
|
|
92
|
-
dropdownButtonId="template-sync-result-dropdown"
|
|
91
|
+
<Pagination
|
|
93
92
|
itemCount={5}
|
|
94
93
|
onChange={[Function]}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
"page": 1,
|
|
98
|
-
"perPage": 20,
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
viewType="list"
|
|
94
|
+
page={1}
|
|
95
|
+
perPage={20}
|
|
102
96
|
/>
|
|
103
97
|
</ListView>
|
|
104
98
|
`;
|
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: 9.
|
|
4
|
+
version: 9.2.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: 2022-02-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: diffy
|
|
@@ -69,7 +69,6 @@ files:
|
|
|
69
69
|
- app/controllers/ui_template_syncs_controller.rb
|
|
70
70
|
- app/helpers/foreman_templates_helper.rb
|
|
71
71
|
- app/models/concerns/foreman_templates/template_extensions.rb
|
|
72
|
-
- app/models/setting/template_sync.rb
|
|
73
72
|
- app/services/foreman_templates/action.rb
|
|
74
73
|
- app/services/foreman_templates/cleaner.rb
|
|
75
74
|
- app/services/foreman_templates/export_result.rb
|
|
@@ -89,6 +88,7 @@ files:
|
|
|
89
88
|
- app/views/ui_template_syncs/template_import_results.json.rabl
|
|
90
89
|
- config/routes.rb
|
|
91
90
|
- db/migrate/20180627134929_change_lock_setting.rb
|
|
91
|
+
- db/migrate/20211122154929_templates_settings_category_to_dsl.rb
|
|
92
92
|
- lib/foreman_templates.rb
|
|
93
93
|
- lib/foreman_templates/engine.rb
|
|
94
94
|
- lib/foreman_templates/version.rb
|
|
@@ -96,9 +96,10 @@ files:
|
|
|
96
96
|
- package.json
|
|
97
97
|
- webpack/ForemanTemplates.js
|
|
98
98
|
- webpack/Routes.js
|
|
99
|
+
- webpack/__mocks__/foremanReact/Root/Context/ForemanContext.js
|
|
99
100
|
- webpack/__mocks__/foremanReact/common/helpers.js
|
|
100
101
|
- webpack/__mocks__/foremanReact/components/Layout/LayoutSelectors.js
|
|
101
|
-
- webpack/__mocks__/foremanReact/components/Pagination/
|
|
102
|
+
- webpack/__mocks__/foremanReact/components/Pagination/index.js
|
|
102
103
|
- webpack/__mocks__/foremanReact/components/common/forms/CommonForm.js
|
|
103
104
|
- webpack/__mocks__/foremanReact/components/common/forms/ForemanForm.js
|
|
104
105
|
- webpack/__mocks__/foremanReact/components/common/forms/TextField.js
|
|
@@ -120,6 +121,7 @@ files:
|
|
|
120
121
|
- webpack/components/NewTemplateSync/__tests__/__snapshots__/NewTemplateSyncSelectors.test.js.snap
|
|
121
122
|
- webpack/components/NewTemplateSync/components/ButtonTooltip.js
|
|
122
123
|
- webpack/components/NewTemplateSync/components/NewTemplateSyncForm/NewTemplateSyncForm.js
|
|
124
|
+
- webpack/components/NewTemplateSync/components/NewTemplateSyncForm/NewTemplateSyncFormHelpers.js
|
|
123
125
|
- webpack/components/NewTemplateSync/components/NewTemplateSyncForm/NewTemplateSyncFormSelectors.js
|
|
124
126
|
- webpack/components/NewTemplateSync/components/NewTemplateSyncForm/__tests__/NewTemplateSyncFormSelectors.test.js
|
|
125
127
|
- webpack/components/NewTemplateSync/components/NewTemplateSyncForm/__tests__/__snapshots__/NewTemplateSyncFormSelectors.test.js.snap
|
|
@@ -198,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
198
200
|
- !ruby/object:Gem::Version
|
|
199
201
|
version: '0'
|
|
200
202
|
requirements: []
|
|
201
|
-
rubygems_version: 3.
|
|
203
|
+
rubygems_version: 3.1.2
|
|
202
204
|
signing_key:
|
|
203
205
|
specification_version: 4
|
|
204
206
|
summary: Template-syncing engine for Foreman
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
class Setting
|
|
2
|
-
class TemplateSync < ::Setting
|
|
3
|
-
self.include_root_in_json = false
|
|
4
|
-
|
|
5
|
-
def self.common_stripped_names
|
|
6
|
-
%w(verbose repo branch dirname filter negate)
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def self.import_stripped_names
|
|
10
|
-
%w(prefix associate force lock)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def self.export_stripped_names
|
|
14
|
-
%w(metadata_export_mode commit_msg)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def self.import_setting_names(except = [])
|
|
18
|
-
map_prefix omit_settings(common_stripped_names + import_stripped_names, except)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def self.export_setting_names(except = [])
|
|
22
|
-
map_prefix omit_settings(common_stripped_names + export_stripped_names, except)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def self.map_prefix(stripped_names)
|
|
26
|
-
stripped_names.map { |item| "template_sync_#{item}" }
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def self.omit_settings(setting_names, except_array)
|
|
30
|
-
setting_names.reject { |name| except_array.include? name }
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def self.associate_types
|
|
34
|
-
{
|
|
35
|
-
'always' => _('Always'),
|
|
36
|
-
'new' => _('New'),
|
|
37
|
-
'never' => _('Never')
|
|
38
|
-
}
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def self.lock_types
|
|
42
|
-
{
|
|
43
|
-
'lock' => _('Lock'),
|
|
44
|
-
'keep_lock_new' => _('Keep, lock new'),
|
|
45
|
-
'keep' => _('Keep, do not lock new'),
|
|
46
|
-
'unlock' => _('Unlock')
|
|
47
|
-
}
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def self.metadata_export_mode_types
|
|
51
|
-
{
|
|
52
|
-
'refresh' => _('Refresh'),
|
|
53
|
-
'keep' => _('Keep'),
|
|
54
|
-
'remove' => _('Remove')
|
|
55
|
-
}
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def short_name
|
|
59
|
-
name.split('template_sync_').last
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def selection
|
|
63
|
-
selection_method = name.split('template_sync_').last.concat('_types')
|
|
64
|
-
return transformed_selection(selection_method) if self.class.respond_to?(selection_method)
|
|
65
|
-
|
|
66
|
-
[]
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def self.load_defaults
|
|
70
|
-
return unless super
|
|
71
|
-
|
|
72
|
-
%w(template_sync_filter template_sync_branch template_sync_prefix).each { |s| Setting::BLANK_ATTRS << s }
|
|
73
|
-
Setting::NOT_STRIPPED << 'template_sync_prefix'
|
|
74
|
-
|
|
75
|
-
self.transaction do
|
|
76
|
-
[
|
|
77
|
-
self.set('template_sync_verbose', N_('Choose verbosity for Rake task importing templates'), false, N_('Verbosity')),
|
|
78
|
-
self.set('template_sync_associate', N_('Associate templates to OS, organization and location'), 'new', N_('Associate'), nil, { :collection => Proc.new { self.associate_types } }),
|
|
79
|
-
self.set('template_sync_prefix', N_('The string that will be added as prefix to imported templates'), "", N_('Prefix')),
|
|
80
|
-
self.set('template_sync_dirname', N_('The directory within the Git repo containing the templates'), '/', N_('Dirname')),
|
|
81
|
-
self.set('template_sync_filter', N_('Import/export names matching this regex (case-insensitive; snippets are not filtered)'), '', N_('Filter')),
|
|
82
|
-
self.set('template_sync_repo', N_('Target path to import/export. Different protocols can be used, for example /tmp/dir, git://example.com, https://example.com, ssh://example.com. When exporting to /tmp, note that production deployments may be configured to use private tmp.'), 'https://github.com/theforeman/community-templates.git', N_('Repo')),
|
|
83
|
-
self.set('template_sync_negate', N_('Negate the filter for import/export'), false, N_('Negate')),
|
|
84
|
-
self.set('template_sync_branch', N_('Default branch in Git repo'), '', N_('Branch')),
|
|
85
|
-
self.set('template_sync_metadata_export_mode', N_('Default metadata export mode, refresh re-renders metadata, keep will keep existing metadata, remove exports template without metadata'), 'refresh', N_('Metadata export mode'), nil, { :collection => Proc.new { self.metadata_export_mode_types } }),
|
|
86
|
-
self.set('template_sync_force', N_('Should importing overwrite locked templates?'), false, N_('Force import')),
|
|
87
|
-
self.set('template_sync_lock', N_('How to handle lock for imported templates?'), 'keep', N_('Lock templates'), nil, { :collection => Proc.new { self.lock_types } }),
|
|
88
|
-
self.set('template_sync_commit_msg', N_('Custom commit message for templates export'), 'Templates export made by a Foreman user', N_('Commit message'))
|
|
89
|
-
].compact.each { |s| self.create! s.update(:category => "Setting::TemplateSync") }
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
true
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def validate_template_sync_associate(record)
|
|
96
|
-
values = record.class.associate_types.keys
|
|
97
|
-
if record.value && !values.include?(record.value)
|
|
98
|
-
record.errors[:base] << (_("template_sync_associate must be one of %s") % values.join(', '))
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def validate_template_sync_metadata_export_mode(record)
|
|
103
|
-
values = record.class.metadata_export_mode_types.keys
|
|
104
|
-
if record.value && !values.include?(record.value)
|
|
105
|
-
record.errors[:base] << (_("template_sync_metadata_export_mode must be one of %s") % values.join(', '))
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
private
|
|
110
|
-
|
|
111
|
-
def transformed_selection(selection_method)
|
|
112
|
-
self.class.public_send(selection_method).map { |key, translated| { :value => key, :label => translated } }
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|