foreman_remote_execution 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -5
- data/.rubocop_todo.yml +90 -92
- data/app/assets/javascripts/job_templates.js +10 -0
- data/app/assets/stylesheets/modal_window.css.scss +4 -0
- data/app/controllers/api/v2/job_templates_controller.rb +22 -1
- data/app/controllers/job_templates_controller.rb +21 -1
- data/app/helpers/concerns/foreman_remote_execution/job_templates_extensions.rb +3 -2
- data/app/helpers/remote_execution_helper.rb +5 -3
- data/app/lib/actions/middleware/bind_job_invocation.rb +1 -1
- data/app/lib/actions/remote_execution/run_host_job.rb +15 -8
- data/app/lib/actions/remote_execution/run_hosts_job.rb +2 -1
- data/app/models/concerns/foreman_remote_execution/exportable.rb +71 -0
- data/app/models/foreign_input_set.rb +3 -0
- data/app/models/job_invocation.rb +6 -4
- data/app/models/job_invocation_composer.rb +1 -1
- data/app/models/job_template.rb +22 -6
- data/app/models/template_input.rb +4 -0
- data/app/models/template_invocation.rb +1 -1
- data/app/services/proxy_load_balancer.rb +3 -0
- data/app/views/job_invocations/_preview_hosts_modal.html.erb +3 -1
- data/app/views/job_templates/_import_job_template_modal.html.erb +20 -0
- data/app/views/job_templates/index.html.erb +5 -1
- data/config/routes.rb +4 -0
- data/lib/foreman_remote_execution/engine.rb +4 -4
- data/lib/foreman_remote_execution/version.rb +1 -1
- data/locale/Makefile +18 -19
- data/locale/action_names.rb +2 -2
- data/locale/de/LC_MESSAGES/foreman_remote_execution.mo +0 -0
- data/locale/de/foreman_remote_execution.po +823 -0
- data/locale/en/LC_MESSAGES/foreman_remote_execution.mo +0 -0
- data/locale/en/foreman_remote_execution.po +332 -283
- data/locale/en_GB/LC_MESSAGES/foreman_remote_execution.mo +0 -0
- data/locale/en_GB/foreman_remote_execution.po +824 -0
- data/locale/foreman_remote_execution.pot +277 -131
- data/locale/fr/LC_MESSAGES/foreman_remote_execution.mo +0 -0
- data/locale/fr/foreman_remote_execution.po +823 -0
- data/test/functional/api/v2/job_templates_controller_test.rb +15 -0
- data/test/unit/actions/run_host_job_test.rb +50 -0
- data/test/unit/concerns/exportable_test.rb +88 -0
- data/test/unit/job_invocation_composer_test.rb +1 -1
- data/test/unit/job_invocation_test.rb +3 -6
- data/test/unit/job_template_test.rb +34 -2
- data/test/unit/proxy_load_balancer_test.rb +8 -6
- data/test/unit/template_input_test.rb +15 -0
- metadata +17 -2
@@ -6,7 +6,7 @@ module Actions
|
|
6
6
|
def delay(*args)
|
7
7
|
schedule_options, job_invocation = args
|
8
8
|
if !job_invocation.task_id.nil? && job_invocation.task_id != task.id
|
9
|
-
job_invocation = job_invocation.deep_clone
|
9
|
+
job_invocation = job_invocation.deep_clone!
|
10
10
|
args = [schedule_options, job_invocation]
|
11
11
|
end
|
12
12
|
pass(*args).tap { bind(job_invocation) }
|
@@ -9,7 +9,7 @@ module Actions
|
|
9
9
|
:link
|
10
10
|
end
|
11
11
|
|
12
|
-
def plan(job_invocation, host, template_invocation, proxy)
|
12
|
+
def plan(job_invocation, host, template_invocation, proxy, options = {})
|
13
13
|
action_subject(host, :job_category => job_invocation.job_category, :description => job_invocation.description)
|
14
14
|
|
15
15
|
template_invocation.host_id = host.id
|
@@ -24,11 +24,19 @@ module Actions
|
|
24
24
|
|
25
25
|
raise _('Could not use any template used in the job invocation') if template_invocation.blank?
|
26
26
|
|
27
|
-
|
28
|
-
|
27
|
+
if proxy.blank?
|
28
|
+
offline_proxies = options.fetch(:offline_proxies, [])
|
29
|
+
settings = { :count => offline_proxies.count, :proxy_names => offline_proxies.map(&:name).join(', ') }
|
30
|
+
raise n_('The only applicable proxy %{proxy_names} is down',
|
31
|
+
'All %{count} applicable proxies are down. Tried %{proxy_names}',
|
32
|
+
offline_proxies.count) % settings unless offline_proxies.empty?
|
29
33
|
|
30
|
-
|
31
|
-
|
34
|
+
settings = { :global_proxy => 'remote_execution_global_proxy',
|
35
|
+
:fallback_proxy => 'remote_execution_fallback_proxy' }
|
36
|
+
|
37
|
+
raise _('Could not use any proxy. Consider configuring %{global_proxy} ' +
|
38
|
+
'or %{fallback_proxy} in settings') % settings
|
39
|
+
end
|
32
40
|
|
33
41
|
renderer = InputTemplateRenderer.new(template_invocation.template, host, template_invocation)
|
34
42
|
script = renderer.render
|
@@ -70,9 +78,8 @@ module Actions
|
|
70
78
|
|
71
79
|
def find_ip_or_hostname(host)
|
72
80
|
%w(execution primary provision).each do |flag|
|
73
|
-
|
74
|
-
|
75
|
-
end
|
81
|
+
interface = host.send(flag + '_interface')
|
82
|
+
return interface.ip if interface && interface.ip.present?
|
76
83
|
end
|
77
84
|
|
78
85
|
host.interfaces.each do |interface|
|
@@ -31,7 +31,8 @@ module Actions
|
|
31
31
|
template_invocation = job_invocation.pattern_template_invocation_for_host(host).deep_clone
|
32
32
|
template_invocation.host_id = host.id
|
33
33
|
proxy = determine_proxy(template_invocation, host, load_balancer)
|
34
|
-
trigger(RunHostJob, job_invocation, host, template_invocation, proxy
|
34
|
+
trigger(RunHostJob, job_invocation, host, template_invocation, proxy,
|
35
|
+
:offline_proxies => load_balancer.offline)
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# This concern makes it easy to export an ActiveRecord object with specified
|
2
|
+
# attributes and associations in a particular format. If a specified
|
3
|
+
# assocation also includes this concern, then it will likewise be exported.
|
4
|
+
#
|
5
|
+
# Custom attributes can be specified with a custom export lambda in an options
|
6
|
+
# hash.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
# attr_exportable :name, :address, :company => ->(user) { user.company.name }
|
10
|
+
#
|
11
|
+
module ForemanRemoteExecution
|
12
|
+
module Exportable
|
13
|
+
extend ActiveSupport::Concern
|
14
|
+
|
15
|
+
def to_export(include_blank = true)
|
16
|
+
self.class.exportable_attributes.keys.inject({}) do |hash, attribute|
|
17
|
+
value = export_attr(attribute, self.class.exportable_attributes[attribute], include_blank)
|
18
|
+
|
19
|
+
# Rails considers false blank, but if a boolean value is explicitly set false, we want to ensure we export it.
|
20
|
+
if include_blank || value.present? || value == false
|
21
|
+
hash.update(attribute => value)
|
22
|
+
else
|
23
|
+
hash
|
24
|
+
end
|
25
|
+
end.stringify_keys
|
26
|
+
end
|
27
|
+
|
28
|
+
# Export a particular attribute or association.
|
29
|
+
# - If our exportable_attributes value is callable, we call it with self as an argument
|
30
|
+
# - If our object is iterable, then we export each item
|
31
|
+
# - If the attribute or association also includes this concern, call to_export on it
|
32
|
+
def export_attr(attribute, exporter, include_blank)
|
33
|
+
value = if exporter.respond_to?(:call)
|
34
|
+
exporter.call(self)
|
35
|
+
elsif self.respond_to?(exporter)
|
36
|
+
self.send(exporter)
|
37
|
+
end
|
38
|
+
|
39
|
+
value = value.respond_to?(:map) ? export_iterable(value, include_blank) : value
|
40
|
+
value.respond_to?(:to_export) ? value.to_export(include_blank) : value
|
41
|
+
end
|
42
|
+
|
43
|
+
# Exports each item in an iterable. If it's a hash, then export each value.
|
44
|
+
def export_iterable(items, include_blank)
|
45
|
+
if items.is_a?(Hash)
|
46
|
+
items.each { |key, value| items[key] = value.respond_to?(:to_export) ? value.to_export(include_blank) : value }
|
47
|
+
items.to_hash.stringify_keys
|
48
|
+
else
|
49
|
+
items.map { |item| item.respond_to?(:to_export) ? item.to_export(include_blank) : item }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module ClassMethods
|
54
|
+
attr_reader :exportable_attributes
|
55
|
+
|
56
|
+
# Takes an array of exportable attributes, and a custom exports hash. The
|
57
|
+
# custom exports hash should be a key/lambda pair used to export the
|
58
|
+
# particular attribute.
|
59
|
+
def attr_exportable(*args)
|
60
|
+
@exportable_attributes ||= {}
|
61
|
+
args.each do |arg|
|
62
|
+
if arg.is_a?(Hash)
|
63
|
+
@exportable_attributes.merge!(arg)
|
64
|
+
else
|
65
|
+
@exportable_attributes.merge!(arg => arg)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -1,8 +1,11 @@
|
|
1
1
|
class ForeignInputSet < ActiveRecord::Base
|
2
|
+
include ForemanRemoteExecution::Exportable
|
3
|
+
|
2
4
|
class CircularDependencyError < Foreman::Exception
|
3
5
|
end
|
4
6
|
|
5
7
|
attr_accessible :template_id, :target_template_id, :include_all, :include, :exclude
|
8
|
+
attr_exportable :exclude, :include, :include_all, :template => ->(input_set) { input_set.template.name }
|
6
9
|
|
7
10
|
belongs_to :template
|
8
11
|
belongs_to :target_template, :class_name => 'Template'
|
@@ -93,15 +93,18 @@ class JobInvocation < ActiveRecord::Base
|
|
93
93
|
|
94
94
|
def deep_clone
|
95
95
|
JobInvocationComposer.from_job_invocation(self).job_invocation.tap do |invocation|
|
96
|
-
invocation.task_group = JobInvocationTaskGroup.new
|
96
|
+
invocation.task_group = JobInvocationTaskGroup.new
|
97
97
|
invocation.triggering = self.triggering
|
98
98
|
invocation.description_format = self.description_format
|
99
99
|
invocation.description = self.description
|
100
100
|
invocation.pattern_template_invocations = self.pattern_template_invocations.map(&:deep_clone)
|
101
|
-
invocation.save!
|
102
101
|
end
|
103
102
|
end
|
104
103
|
|
104
|
+
def deep_clone!
|
105
|
+
deep_clone.tap(&:save!)
|
106
|
+
end
|
107
|
+
|
105
108
|
def to_action_input
|
106
109
|
{ :id => id, :name => job_category, :description => description }
|
107
110
|
end
|
@@ -151,7 +154,7 @@ class JobInvocation < ActiveRecord::Base
|
|
151
154
|
task.main_action.live_output.first['output']
|
152
155
|
end
|
153
156
|
|
154
|
-
def generate_description
|
157
|
+
def generate_description
|
155
158
|
key_re = /%\{([^\}]+)\}/
|
156
159
|
template_invocation = pattern_template_invocations.first
|
157
160
|
input_names = template_invocation.template.template_inputs_with_foreign(&:name)
|
@@ -165,7 +168,6 @@ class JobInvocation < ActiveRecord::Base
|
|
165
168
|
self.description.gsub!(Regexp.new("%\{#{k}\}"), v || '')
|
166
169
|
end
|
167
170
|
self.description = self.description[0..(JobInvocation.columns_hash['description'].limit - 1)]
|
168
|
-
save!
|
169
171
|
end
|
170
172
|
|
171
173
|
private
|
@@ -468,7 +468,7 @@ class JobInvocationComposer
|
|
468
468
|
template = job_invocation.pattern_template_invocations.first.try(:template)
|
469
469
|
job_invocation.description_format = template.generate_description_format if template
|
470
470
|
end
|
471
|
-
job_invocation.generate_description
|
471
|
+
job_invocation.generate_description if job_invocation.description.blank?
|
472
472
|
end
|
473
473
|
|
474
474
|
def build_effective_user(template_invocation_params)
|
data/app/models/job_template.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
class JobTemplate < ::Template
|
2
|
+
include ForemanRemoteExecution::Exportable
|
2
3
|
|
3
4
|
class NonUniqueInputsError < Foreman::Exception
|
4
5
|
end
|
5
6
|
|
6
7
|
attr_accessible :job_category, :provider_type, :description_format, :effective_user_attributes
|
8
|
+
attr_exportable :name, :job_category, :description_format, :snippet, :template_inputs,
|
9
|
+
:foreign_input_sets, :provider_type, :kind => ->(template) { template.class.name.underscore }
|
7
10
|
|
8
11
|
include Authorizable
|
9
12
|
extend FriendlyId
|
@@ -67,16 +70,17 @@ class JobTemplate < ::Template
|
|
67
70
|
metadata = parse_metadata(contents)
|
68
71
|
return if metadata.blank? || metadata.delete('kind') != 'job_template'
|
69
72
|
|
73
|
+
# Don't look for existing if we should always create a new template
|
74
|
+
existing = self.find_by_name(metadata['name']) unless options.delete(:build_new)
|
70
75
|
# Don't update if the template already exists, unless we're told to
|
71
|
-
existing = self.find_by_name(metadata['name'])
|
72
76
|
return if !options.delete(:update) && existing
|
73
77
|
|
74
78
|
template = existing || self.new
|
75
79
|
template.sync_inputs(metadata.delete('template_inputs'))
|
76
80
|
template.sync_foreign_input_sets(metadata.delete('foreign_input_sets'))
|
77
|
-
template.assign_attributes(metadata.merge(:template => contents.gsub(/<%\#.+?.-?%>\n?/m, '')).merge(options).except('feature'))
|
78
|
-
template.assign_taxonomies if template.new_record?
|
79
81
|
template.sync_feature(metadata.delete('feature'))
|
82
|
+
template.assign_attributes(metadata.merge(:template => contents.gsub(/<%\#.+?.-?%>\n?/m, '').strip).merge(options))
|
83
|
+
template.assign_taxonomies if template.new_record?
|
80
84
|
|
81
85
|
template
|
82
86
|
end
|
@@ -88,6 +92,19 @@ class JobTemplate < ::Template
|
|
88
92
|
template
|
89
93
|
end
|
90
94
|
|
95
|
+
def metadata
|
96
|
+
"<%#\n#{to_export(false).to_yaml.sub(/\A---$/, '').strip}\n%>\n\n"
|
97
|
+
end
|
98
|
+
|
99
|
+
# 'Package Action - SSH Default' => 'package_action_ssh_default.erb'
|
100
|
+
def filename
|
101
|
+
name.downcase.delete('-').gsub(/\s+/, '_') + '.erb'
|
102
|
+
end
|
103
|
+
|
104
|
+
def to_erb
|
105
|
+
metadata + template
|
106
|
+
end
|
107
|
+
|
91
108
|
# Override method in Taxonomix as Template is not used attached to a Host,
|
92
109
|
# and matching a Host does not prevent removing a template from its taxonomy.
|
93
110
|
def used_taxonomy_ids(type)
|
@@ -140,7 +157,7 @@ class JobTemplate < ::Template
|
|
140
157
|
def sync_inputs(inputs)
|
141
158
|
inputs ||= []
|
142
159
|
# Build a hash where keys are input names
|
143
|
-
inputs = inputs.inject({}) { |h, input| h.update(input['name'] => input
|
160
|
+
inputs = inputs.inject({}) { |h, input| h.update(input['name'] => input) }
|
144
161
|
|
145
162
|
# Sync existing inputs
|
146
163
|
template_inputs.each do |existing_input|
|
@@ -180,7 +197,6 @@ class JobTemplate < ::Template
|
|
180
197
|
def sync_feature(feature_name)
|
181
198
|
if feature_name && (feature = RemoteExecutionFeature.feature(feature_name))
|
182
199
|
feature.job_template ||= self
|
183
|
-
feature.save!
|
184
200
|
end
|
185
201
|
end
|
186
202
|
|
@@ -203,4 +219,4 @@ class JobTemplate < ::Template
|
|
203
219
|
errors.add(:base, _('This template is locked. Please clone it to a new template to customize.'))
|
204
220
|
end
|
205
221
|
end
|
206
|
-
end
|
222
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
class TemplateInput < ActiveRecord::Base
|
2
|
+
include ForemanRemoteExecution::Exportable
|
3
|
+
|
2
4
|
class ValueNotReady < ::Foreman::Exception
|
3
5
|
end
|
4
6
|
class UnsatisfiedRequiredInput < ::Foreman::Exception
|
@@ -11,6 +13,8 @@ class TemplateInput < ActiveRecord::Base
|
|
11
13
|
:puppet_class_name, :puppet_parameter_name, :description, :template_id,
|
12
14
|
:options, :advanced
|
13
15
|
|
16
|
+
attr_exportable(*self.accessible_attributes - %w(template_id))
|
17
|
+
|
14
18
|
belongs_to :template
|
15
19
|
has_many :template_invocation_input_values, :dependent => :destroy
|
16
20
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
<% stylesheet 'modal_window' %>
|
2
|
+
|
1
3
|
<!-- modal window -->
|
2
4
|
<div class="modal fade" id="previewHostsModal" role="dialog" aria-hidden="true" data-url="<%= preview_hosts_job_invocations_path %>">
|
3
5
|
<div class="modal-dialog">
|
@@ -6,7 +8,7 @@
|
|
6
8
|
<button type="button" class="close" onclick="close_preview_hosts_modal(); return false;"><span aria-hidden="true">×</span><span class="sr-only"><%= _('Close') %></span></button>
|
7
9
|
<h4 class="modal-title">Preview Hosts</h4>
|
8
10
|
</div>
|
9
|
-
<div class="modal-body"
|
11
|
+
<div class="modal-body">
|
10
12
|
</div>
|
11
13
|
</div>
|
12
14
|
</div>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<% stylesheet 'modal_window' %>
|
2
|
+
|
3
|
+
<!-- modal window -->
|
4
|
+
<div class="modal fade" id="importJobTemplateModal" role="dialog" aria-hidden="true">
|
5
|
+
<div class="modal-dialog">
|
6
|
+
<div class="modal-content">
|
7
|
+
<div class="modal-header">
|
8
|
+
<button type="button" class="close" onclick="close_import_job_template_modal(); return false;"><span aria-hidden="true">×</span><span class="sr-only"><%= _('Close') %></span></button>
|
9
|
+
<h4 class="modal-title">Import Job Template</h4>
|
10
|
+
</div>
|
11
|
+
<div class="modal-body">
|
12
|
+
<%= form_for :imported_template, :url => import_job_templates_path do |f| %>
|
13
|
+
<%= file_field_f f, :template, :size => "col-md-10", :help_block => _("Select an ERB file to upload in order to import a job template. The template must contain metadata in the first ERB comment.") %>
|
14
|
+
<%= checkbox_f(f, :overwrite, :label => _('Overwrite'), :help_block => _("Whether to overwrite the template if it already exists")) %>
|
15
|
+
<%= submit_or_cancel f, false, :cancel_path => 'javascript:close_import_job_template_modal();' %>
|
16
|
+
<% end %>
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
</div>
|
@@ -1,9 +1,11 @@
|
|
1
1
|
<%= include_javascript if SETTINGS[:version].short == '1.9' %>
|
2
|
+
<%= javascript 'job_templates' %>
|
2
3
|
<%= javascript 'lookup_keys' %>
|
3
4
|
<%= javascript 'template_input' %>
|
4
5
|
|
5
6
|
<% title _("Job Templates") %>
|
6
7
|
<% title_actions(documentation_button_rex('3.1JobTemplates'),
|
8
|
+
link_to_function(_('Import'), 'show_import_job_template_modal();', :class => 'btn btn-default'),
|
7
9
|
display_link_if_authorized(_("New Job Template"),
|
8
10
|
hash_for_new_job_template_path)) %>
|
9
11
|
|
@@ -19,7 +21,7 @@
|
|
19
21
|
<tbody>
|
20
22
|
<% for job_template in @templates %>
|
21
23
|
<tr>
|
22
|
-
<td class="display-two-pane"><%= link_to_if_authorized
|
24
|
+
<td class="display-two-pane ellipsis"><%= link_to_if_authorized job_template,
|
23
25
|
hash_for_edit_job_template_path(:id => job_template).merge(:auth_object => job_template, :authorizer => authorizer) %></td>
|
24
26
|
<td align='center'><%= checked_icon job_template.snippet %></td>
|
25
27
|
<td align='center'>
|
@@ -33,3 +35,5 @@
|
|
33
35
|
</tbody>
|
34
36
|
</table>
|
35
37
|
<%= will_paginate_with_info @templates %>
|
38
|
+
|
39
|
+
<%= render :partial => 'import_job_template_modal' %>
|
data/config/routes.rb
CHANGED
@@ -3,11 +3,13 @@ Rails.application.routes.draw do
|
|
3
3
|
member do
|
4
4
|
get 'clone_template'
|
5
5
|
get 'lock'
|
6
|
+
get 'export'
|
6
7
|
get 'unlock'
|
7
8
|
post 'preview'
|
8
9
|
end
|
9
10
|
collection do
|
10
11
|
post 'preview'
|
12
|
+
post 'import'
|
11
13
|
get 'revision'
|
12
14
|
get 'auto_complete_search'
|
13
15
|
get 'auto_complete_job_category'
|
@@ -45,9 +47,11 @@ Rails.application.routes.draw do
|
|
45
47
|
resources :job_templates, :except => [:new, :edit] do
|
46
48
|
(resources :locations, :only => [:index, :show]) if SETTINGS[:locations_enabled]
|
47
49
|
(resources :organizations, :only => [:index, :show]) if SETTINGS[:organizations_enabled]
|
50
|
+
get :export, :on => :member
|
48
51
|
post :clone, :on => :member
|
49
52
|
collection do
|
50
53
|
get 'revision'
|
54
|
+
post 'import'
|
51
55
|
end
|
52
56
|
end
|
53
57
|
|
@@ -35,12 +35,12 @@ module ForemanRemoteExecution
|
|
35
35
|
|
36
36
|
# Add permissions
|
37
37
|
security_block :foreman_remote_execution do
|
38
|
-
permission :view_job_templates, { :job_templates => [:index, :show, :revision, :auto_complete_search, :auto_complete_job_category, :preview],
|
39
|
-
:'api/v2/job_templates' => [:index, :show, :revision],
|
38
|
+
permission :view_job_templates, { :job_templates => [:index, :show, :revision, :auto_complete_search, :auto_complete_job_category, :preview, :export],
|
39
|
+
:'api/v2/job_templates' => [:index, :show, :revision, :export],
|
40
40
|
:'api/v2/template_inputs' => [:index, :show],
|
41
41
|
:'api/v2/foreign_input_sets' => [:index, :show]}, :resource_type => 'JobTemplate'
|
42
|
-
permission :create_job_templates, { :job_templates => [:new, :create, :clone_template],
|
43
|
-
:'api/v2/job_templates' => [:create, :clone] }, :resource_type => 'JobTemplate'
|
42
|
+
permission :create_job_templates, { :job_templates => [:new, :create, :clone_template, :import],
|
43
|
+
:'api/v2/job_templates' => [:create, :clone, :import] }, :resource_type => 'JobTemplate'
|
44
44
|
permission :edit_job_templates, { :job_templates => [:edit, :update],
|
45
45
|
:'api/v2/job_templates' => [:update],
|
46
46
|
:'api/v2/template_inputs' => [:create, :update, :destroy],
|
data/locale/Makefile
CHANGED
@@ -10,9 +10,10 @@ DOMAIN = foreman_remote_execution
|
|
10
10
|
VERSION = $(shell ruby -e 'require "rubygems";spec = Gem::Specification::load(Dir.glob("../*.gemspec")[0]);puts spec.version')
|
11
11
|
POTFILE = $(DOMAIN).pot
|
12
12
|
MOFILE = $(DOMAIN).mo
|
13
|
-
POFILES = $(shell find . -name '
|
13
|
+
POFILES = $(shell find . -name '$(DOMAIN).po')
|
14
14
|
MOFILES = $(patsubst %.po,%.mo,$(POFILES))
|
15
15
|
POXFILES = $(patsubst %.po,%.pox,$(POFILES))
|
16
|
+
EDITFILES = $(patsubst %.po,%.edit.po,$(POFILES))
|
16
17
|
|
17
18
|
%.mo: %.po
|
18
19
|
mkdir -p $(shell dirname $@)/LC_MESSAGES
|
@@ -29,14 +30,10 @@ all-mo: $(MOFILES)
|
|
29
30
|
cat $@
|
30
31
|
! grep -q msgid $@
|
31
32
|
|
32
|
-
|
33
|
-
|
33
|
+
%.edit.po:
|
34
|
+
touch $@
|
34
35
|
|
35
|
-
|
36
|
-
update-po:
|
37
|
-
for f in $(shell find ./ -name "*.po") ; do \
|
38
|
-
msgmerge -N --backup=none -U $$f ${POTFILE} ; \
|
39
|
-
done
|
36
|
+
check: $(POXFILES)
|
40
37
|
|
41
38
|
# Unify duplicate translations
|
42
39
|
uniq-po:
|
@@ -44,19 +41,21 @@ uniq-po:
|
|
44
41
|
msguniq $$f -o $$f ; \
|
45
42
|
done
|
46
43
|
|
47
|
-
tx-pull:
|
44
|
+
tx-pull: $(EDITFILES)
|
48
45
|
tx pull -f
|
49
|
-
for f in $(
|
46
|
+
for f in $(EDITFILES) ; do \
|
50
47
|
sed -i 's/^\("Project-Id-Version: \).*$$/\1$(DOMAIN) $(VERSION)\\n"/' $$f; \
|
51
48
|
done
|
52
|
-
-git commit -a -m "i18n - pulling from tx"
|
53
49
|
|
54
|
-
|
55
|
-
|
56
|
-
|
50
|
+
tx-update: tx-pull
|
51
|
+
@echo
|
52
|
+
@echo Run rake plugin:gettext[$(DOMAIN)] from the Foreman installation, then make -C locale mo-files to finish
|
53
|
+
@echo
|
54
|
+
|
55
|
+
mo-files: $(MOFILES)
|
56
|
+
git add $(POFILES) $(POTFILE) ../locale/*/LC_MESSAGES
|
57
|
+
git commit -m "i18n - pulling from tx"
|
58
|
+
@echo
|
59
|
+
@echo Changes commited!
|
60
|
+
@echo
|
57
61
|
|
58
|
-
tx-update: tx-pull reset-po $(MOFILES)
|
59
|
-
# amend mo files
|
60
|
-
git add ../locale/*/LC_MESSAGES
|
61
|
-
git commit -a --amend -m "i18n - pulling from tx"
|
62
|
-
-echo Changes commited!
|