machinery-tool 1.6.0 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/NEWS +11 -0
- data/helpers/changed_managed_files.sh +6 -1
- data/html/assets/angular-sanitize.min.js +16 -0
- data/html/assets/angular.min.js +251 -0
- data/html/assets/compare/machinery-compare.js +36 -0
- data/html/assets/compare/machinery.js +53 -0
- data/html/assets/machinery.css +30 -1
- data/html/assets/show/machinery-show.js +65 -0
- data/html/assets/{machinery.js → show/machinery.js} +10 -83
- data/html/comparison.html.haml +613 -0
- data/html/index.html.haml +353 -414
- data/lib/cli.rb +36 -2
- data/lib/compare_task.rb +29 -2
- data/lib/config.rb +5 -1
- data/lib/config_task.rb +4 -1
- data/lib/export_task.rb +6 -1
- data/{plugins/model → lib}/file_scope.rb +0 -0
- data/lib/filter.rb +1 -0
- data/lib/filter_option_parser.rb +4 -7
- data/lib/helper.rb +12 -0
- data/lib/html.rb +25 -2
- data/lib/inspect_task.rb +1 -1
- data/lib/inspector.rb +21 -1
- data/lib/json_validator.rb +7 -6
- data/lib/machinery.rb +2 -1
- data/lib/manifest.rb +1 -1
- data/lib/migration.rb +1 -1
- data/lib/remote_system.rb +29 -8
- data/lib/{scope_mixin.rb → scope.rb} +1 -1
- data/lib/show_task.rb +1 -0
- data/lib/system.rb +5 -4
- data/lib/system_description.rb +3 -3
- data/lib/version.rb +1 -1
- data/man/generated/machinery.1.gz +0 -0
- data/man/generated/machinery.1.html +38 -36
- data/plugins/{docs → changed_managed_files}/changed_managed_files.md +0 -0
- data/plugins/{inspect → changed_managed_files}/changed_managed_files_inspector.rb +2 -1
- data/plugins/{model → changed_managed_files}/changed_managed_files_model.rb +1 -3
- data/plugins/{show → changed_managed_files}/changed_managed_files_renderer.rb +0 -0
- data/plugins/{schema/v1/system-description-changed-managed-files.schema.json → changed_managed_files/schema/system-description-changed-managed-files.schema-v1.json} +0 -0
- data/plugins/{schema/v2/system-description-changed-managed-files.schema.json → changed_managed_files/schema/system-description-changed-managed-files.schema-v2.json} +0 -0
- data/plugins/{schema/v3/system-description-changed-managed-files.schema.json → changed_managed_files/schema/system-description-changed-managed-files.schema-v3.json} +0 -0
- data/plugins/{docs → config_files}/config_files.md +0 -0
- data/plugins/{inspect → config_files}/config_files_inspector.rb +5 -3
- data/plugins/{model → config_files}/config_files_model.rb +1 -3
- data/plugins/{show → config_files}/config_files_renderer.rb +0 -0
- data/plugins/{schema/v1/system-description-config-files.schema.json → config_files/schema/system-description-config-files.schema-v1.json} +0 -0
- data/plugins/{schema/v2/system-description-config-files.schema.json → config_files/schema/system-description-config-files.schema-v2.json} +0 -0
- data/plugins/{schema/v3/system-description-config-files.schema.json → config_files/schema/system-description-config-files.schema-v3.json} +0 -0
- data/plugins/{docs → groups}/groups.md +0 -0
- data/plugins/{inspect → groups}/groups_inspector.rb +2 -0
- data/plugins/{model → groups}/groups_model.rb +1 -1
- data/plugins/{show → groups}/groups_renderer.rb +0 -0
- data/plugins/{schema/v1/system-description-groups.schema.json → groups/schema/system-description-groups.schema-v1.json} +0 -0
- data/plugins/{schema/v2/system-description-groups.schema.json → groups/schema/system-description-groups.schema-v2.json} +0 -0
- data/plugins/{schema/v3/system-description-groups.schema.json → groups/schema/system-description-groups.schema-v3.json} +0 -0
- data/plugins/{docs → os}/os.md +0 -0
- data/plugins/{inspect → os}/os_inspector.rb +6 -0
- data/plugins/{model → os}/os_model.rb +15 -1
- data/plugins/{show → os}/os_renderer.rb +0 -0
- data/plugins/{schema/v1/system-description-os.schema.json → os/schema/system-description-os.schema-v1.json} +0 -0
- data/plugins/{schema/v2/system-description-os.schema.json → os/schema/system-description-os.schema-v2.json} +0 -0
- data/plugins/{schema/v3/system-description-os.schema.json → os/schema/system-description-os.schema-v3.json} +0 -0
- data/plugins/{docs → packages}/packages.md +0 -0
- data/plugins/{inspect → packages}/packages_inspector.rb +1 -0
- data/plugins/{model → packages}/packages_model.rb +1 -1
- data/plugins/{show → packages}/packages_renderer.rb +0 -0
- data/plugins/{schema/v1/system-description-packages.schema.json → packages/schema/system-description-packages.schema-v1.json} +0 -0
- data/plugins/{schema/v2/system-description-packages.schema.json → packages/schema/system-description-packages.schema-v2.json} +0 -0
- data/plugins/{schema/v3/system-description-packages.schema.json → packages/schema/system-description-packages.schema-v3.json} +0 -0
- data/plugins/{docs → patterns}/patterns.md +0 -0
- data/plugins/{inspect → patterns}/patterns_inspector.rb +1 -0
- data/plugins/{model → patterns}/patterns_model.rb +1 -1
- data/plugins/{show → patterns}/patterns_renderer.rb +0 -0
- data/plugins/{schema/v1/system-description-patterns.schema.json → patterns/schema/system-description-patterns.schema-v1.json} +0 -0
- data/plugins/{schema/v2/system-description-patterns.schema.json → patterns/schema/system-description-patterns.schema-v2.json} +0 -0
- data/plugins/{schema/v3/system-description-patterns.schema.json → patterns/schema/system-description-patterns.schema-v3.json} +0 -0
- data/plugins/{docs → repositories}/repositories.md +0 -0
- data/plugins/{inspect → repositories}/repositories_inspector.rb +1 -0
- data/plugins/{model → repositories}/repositories_model.rb +1 -1
- data/plugins/{show → repositories}/repositories_renderer.rb +0 -0
- data/plugins/{schema/v1/system-description-repositories.schema.json → repositories/schema/system-description-repositories.schema-v1.json} +0 -0
- data/plugins/{schema/v2/system-description-repositories.schema.json → repositories/schema/system-description-repositories.schema-v2.json} +0 -0
- data/plugins/{schema/v3/system-description-repositories.schema.json → repositories/schema/system-description-repositories.schema-v3.json} +0 -0
- data/plugins/{schema/v1/system-description-services.schema.json → services/schema/system-description-services.schema-v1.json} +0 -0
- data/plugins/{schema/v2/system-description-services.schema.json → services/schema/system-description-services.schema-v2.json} +0 -0
- data/plugins/{schema/v3/system-description-services.schema.json → services/schema/system-description-services.schema-v3.json} +0 -0
- data/plugins/{docs → services}/services.md +0 -0
- data/plugins/{inspect → services}/services_inspector.rb +13 -1
- data/plugins/{model → services}/services_model.rb +1 -1
- data/plugins/{show → services}/services_renderer.rb +0 -0
- data/plugins/{schema/v1/system-description-unmanaged-files.schema.json → unmanaged_files/schema/system-description-unmanaged-files.schema-v1.json} +0 -0
- data/plugins/{schema/v2/system-description-unmanaged-files.schema.json → unmanaged_files/schema/system-description-unmanaged-files.schema-v2.json} +0 -0
- data/plugins/{schema/v3/system-description-unmanaged-files.schema.json → unmanaged_files/schema/system-description-unmanaged-files.schema-v3.json} +6 -0
- data/plugins/{docs → unmanaged_files}/unmanaged_files.md +0 -0
- data/plugins/{inspect → unmanaged_files}/unmanaged_files_inspector.rb +19 -32
- data/plugins/{model → unmanaged_files}/unmanaged_files_model.rb +1 -3
- data/plugins/{show → unmanaged_files}/unmanaged_files_renderer.rb +0 -0
- data/plugins/{schema/v1/system-description-users.schema.json → users/schema/system-description-users.schema-v1.json} +0 -0
- data/plugins/{schema/v2/system-description-users.schema.json → users/schema/system-description-users.schema-v2.json} +0 -0
- data/plugins/{schema/v3/system-description-users.schema.json → users/schema/system-description-users.schema-v3.json} +0 -0
- data/plugins/{docs → users}/users.md +0 -0
- data/plugins/{inspect → users}/users_inspector.rb +2 -0
- data/plugins/{model → users}/users_model.rb +1 -1
- data/plugins/{show → users}/users_renderer.rb +0 -0
- data/schema/{v1/system-description-global.schema.json → system-description-global.schema-v1.json} +0 -0
- data/schema/{v2/system-description-global.schema.json → system-description-global.schema-v2.json} +0 -0
- data/schema/{v3/system-description-global.schema.json → system-description-global.schema-v3.json} +0 -0
- metadata +158 -153
- data/html/assets/hogan-3.0.2.min.mustache.js +0 -5
data/lib/cli.rb
CHANGED
@@ -56,6 +56,16 @@ class Cli
|
|
56
56
|
|
57
57
|
GLI::Commands::Help.skips_post = false
|
58
58
|
|
59
|
+
def self.buildable_distributions
|
60
|
+
distribution_string = ""
|
61
|
+
Os.supported_host_systems.each do |distribution|
|
62
|
+
distribution_string += "* #{distribution.canonical_name}\n\n"
|
63
|
+
distribution_string += distribution.buildable_systems.map(&:canonical_name).join(", ")
|
64
|
+
distribution_string += "\n\n"
|
65
|
+
end
|
66
|
+
distribution_string
|
67
|
+
end
|
68
|
+
|
59
69
|
def self.handle_error(e)
|
60
70
|
case e
|
61
71
|
when GLI::UnknownCommandArgument, GLI::UnknownGlobalArgument,
|
@@ -116,6 +126,12 @@ class Cli
|
|
116
126
|
Cli.handle_error(e)
|
117
127
|
end
|
118
128
|
|
129
|
+
def self.show_filter_note(scopes, filter)
|
130
|
+
if scopes.any? { |scope| !filter.element_filters_for_scope(scope).empty? }
|
131
|
+
Machinery::Ui.puts "\nFilters are applied during inspection.\n\n"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
119
135
|
def self.shift_arg(args, name)
|
120
136
|
if !res = args.shift
|
121
137
|
raise GLI::BadCommandLine.new("You need to provide the required argument #{name}.")
|
@@ -187,7 +203,7 @@ class Cli
|
|
187
203
|
)
|
188
204
|
end
|
189
205
|
|
190
|
-
scopes.uniq
|
206
|
+
Inspector.sort_scopes(scopes.uniq)
|
191
207
|
end
|
192
208
|
|
193
209
|
AVAILABLE_SCOPE_LIST = Machinery::Ui.internal_scope_list_to_string(
|
@@ -232,6 +248,10 @@ class Cli
|
|
232
248
|
long_desc <<-LONGDESC
|
233
249
|
Build image from a given system description and store it to the given
|
234
250
|
location.
|
251
|
+
|
252
|
+
The following combinations of build hosts and targets are supported:
|
253
|
+
|
254
|
+
#{buildable_distributions}
|
235
255
|
LONGDESC
|
236
256
|
arg "NAME"
|
237
257
|
command :build do |c|
|
@@ -274,6 +294,10 @@ class Cli
|
|
274
294
|
desc: "Exclude specified scopes", arg_name: "SCOPE_LIST"
|
275
295
|
c.switch "show-all", required: false, negatable: false,
|
276
296
|
desc: "Show also common properties"
|
297
|
+
if @config.experimental_features
|
298
|
+
c.switch "html", required: false, negatable: false,
|
299
|
+
desc: "Open comparison in HTML format in your web browser."
|
300
|
+
end
|
277
301
|
c.switch "pager", required: false, default_value: true,
|
278
302
|
desc: "Pipe output into a pager"
|
279
303
|
|
@@ -289,6 +313,7 @@ class Cli
|
|
289
313
|
|
290
314
|
task = CompareTask.new
|
291
315
|
opts = {
|
316
|
+
show_html: options["html"],
|
292
317
|
show_all: options["show-all"]
|
293
318
|
}
|
294
319
|
task.compare(description1, description2, scope_list, opts)
|
@@ -427,6 +452,9 @@ class Cli
|
|
427
452
|
c.flag "skip-files", required: false, negatable: false,
|
428
453
|
desc: "Do not consider given files or directories during inspection. " \
|
429
454
|
"Either provide one file or directory name or a list of names separated by commas."
|
455
|
+
c.flag ["remote-user", :r], type: String, required: false, default_value: @config.remote_user,
|
456
|
+
desc: "Defines the user which is used to access the inspected system via SSH."\
|
457
|
+
"This user needs sudo access on the remote machine or be root.", arg_name: "USER"
|
430
458
|
c.switch ["extract-files", :x], required: false, negatable: false,
|
431
459
|
desc: "Extract changed configuration files and unmanaged files from inspected system"
|
432
460
|
c.switch "extract-changed-config-files", required: false, negatable: false,
|
@@ -456,6 +484,9 @@ class Cli
|
|
456
484
|
if options["show"]
|
457
485
|
inspect_options[:show] = true
|
458
486
|
end
|
487
|
+
if options["verbose"]
|
488
|
+
inspect_options[:verbose] = true
|
489
|
+
end
|
459
490
|
if options["extract-files"] || options["extract-changed-config-files"]
|
460
491
|
inspect_options[:extract_changed_config_files] = true
|
461
492
|
end
|
@@ -465,12 +496,15 @@ class Cli
|
|
465
496
|
if options["extract-files"] || options["extract-unmanaged-files"]
|
466
497
|
inspect_options[:extract_unmanaged_files] = true
|
467
498
|
end
|
499
|
+
inspect_options[:remote_user] = options["remote-user"]
|
468
500
|
|
469
501
|
filter = FilterOptionParser.parse("inspect", options, global_options)
|
470
502
|
|
471
503
|
if options["verbose"] && !filter.empty?
|
472
504
|
Machinery::Ui.puts "\nThe following filters are applied during inspection:"
|
473
505
|
Machinery::Ui.puts filter.to_array.join("\n") + "\n\n"
|
506
|
+
else
|
507
|
+
show_filter_note(scope_list, filter)
|
474
508
|
end
|
475
509
|
|
476
510
|
inspector_task.inspect_system(
|
@@ -573,7 +607,7 @@ class Cli
|
|
573
607
|
|
574
608
|
inspected_filters = description.filter_definitions("inspect")
|
575
609
|
|
576
|
-
if options[
|
610
|
+
if options[:verbose]
|
577
611
|
if !inspected_filters.empty?
|
578
612
|
Machinery::Ui.puts "\nThe following filters were applied during inspection:"
|
579
613
|
Machinery::Ui.puts inspected_filters.join("\n") + "\n\n"
|
data/lib/compare_task.rb
CHANGED
@@ -17,9 +17,36 @@
|
|
17
17
|
|
18
18
|
class CompareTask
|
19
19
|
def compare(description1, description2, scopes, options = {})
|
20
|
-
|
20
|
+
if options[:show_html]
|
21
|
+
render_html_comparison(description1, description2, scopes, options)
|
22
|
+
else
|
23
|
+
output = render_comparison(description1, description2, scopes, options)
|
21
24
|
|
22
|
-
|
25
|
+
Machinery::Ui.puts output
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def render_html_comparison(description1, description2, scopes, options)
|
30
|
+
diff = {
|
31
|
+
meta: {
|
32
|
+
description_a: description1.name,
|
33
|
+
description_b: description2.name,
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
scopes.each do |scope|
|
38
|
+
if description1[scope] && description2[scope]
|
39
|
+
comparison = description1[scope].compare_with(description2[scope])
|
40
|
+
diff[scope] = comparison.map { |scope| scope.as_json if scope }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
target = "/tmp/machinery-html-comparison"
|
45
|
+
FileUtils.rm_r(target) if Dir.exists?(target)
|
46
|
+
FileUtils.mkdir_p(target)
|
47
|
+
|
48
|
+
Html.generate_comparison(diff, target)
|
49
|
+
LoggedCheetah.run("xdg-open", File.join(target, "index.html"))
|
23
50
|
end
|
24
51
|
|
25
52
|
def render_comparison(description1, description2, scopes, options = {})
|
data/lib/config.rb
CHANGED
@@ -29,10 +29,14 @@ module Machinery
|
|
29
29
|
description: "Show hints about usage of Machinery in the context of the commands ran by" \
|
30
30
|
" the user"
|
31
31
|
)
|
32
|
+
entry("remote-user",
|
33
|
+
default: "root",
|
34
|
+
description: "Defines the user which is used to access the inspected system via SSH"
|
35
|
+
)
|
32
36
|
entry("experimental-features",
|
33
37
|
default: false,
|
34
38
|
description: "Enable experimental features. See " \
|
35
|
-
"https://github.com/SUSE/machinery/wiki/Experimental-Features for more details
|
39
|
+
"https://github.com/SUSE/machinery/wiki/Experimental-Features for more details"
|
36
40
|
)
|
37
41
|
end
|
38
42
|
end
|
data/lib/config_task.rb
CHANGED
@@ -45,7 +45,10 @@ class ConfigTask
|
|
45
45
|
elsif value_string == "false" || value_string == "off"
|
46
46
|
return false
|
47
47
|
else
|
48
|
-
raise Machinery::Errors::MachineryError.new(
|
48
|
+
raise Machinery::Errors::MachineryError.new(
|
49
|
+
"The value '#{value_string}' is not valid for key '#{key}'." \
|
50
|
+
" Please enter a valid variable of type boolean."
|
51
|
+
)
|
49
52
|
end
|
50
53
|
elsif current_value.kind_of?(Integer)
|
51
54
|
return value_string.to_i
|
data/lib/export_task.rb
CHANGED
@@ -36,7 +36,12 @@ class ExportTask
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
|
39
|
+
begin
|
40
|
+
FileUtils.mkdir_p(output_dir, mode: 0700) if !Dir.exists?(output_dir)
|
41
|
+
rescue Errno::EACCES
|
42
|
+
raise(Machinery::Errors::ExportFailed, \
|
43
|
+
"Permission denied. Directory '#{output_dir}' is not writable")
|
44
|
+
end
|
40
45
|
|
41
46
|
if @exporter.system_description["unmanaged_files"]
|
42
47
|
filters = File.read(
|
File without changes
|
data/lib/filter.rb
CHANGED
@@ -54,6 +54,7 @@ class Filter
|
|
54
54
|
Array(filter_definitions).each do |definition|
|
55
55
|
path, operator, matcher_definition = definition.scan(/([a-zA-Z_\/]+)(.*=)(.*)/)[0]
|
56
56
|
|
57
|
+
raise Machinery::Errors::InvalidFilter.new("Invalid filter: '#{definition}'") if !operator
|
57
58
|
element_filters[path] ||= ElementFilter.new(path)
|
58
59
|
if matcher_definition.index(",")
|
59
60
|
matchers = matcher_definition.split(/(?<!\\),/)
|
data/lib/filter_option_parser.rb
CHANGED
@@ -38,13 +38,10 @@ class FilterOptionParser
|
|
38
38
|
def exclude_definitions(exclude)
|
39
39
|
return [] if !exclude
|
40
40
|
|
41
|
-
filters = exclude.
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
else
|
46
|
-
filter_definition
|
47
|
-
end
|
41
|
+
filters = if exclude.start_with?("@")
|
42
|
+
expand_filter_file(exclude)
|
43
|
+
else
|
44
|
+
[exclude]
|
48
45
|
end
|
49
46
|
|
50
47
|
filters.reject!(&:empty?) # Ignore empty filters
|
data/lib/helper.rb
CHANGED
@@ -19,6 +19,18 @@ module Machinery
|
|
19
19
|
def self.is_int?(string)
|
20
20
|
(string =~ /^\d+$/) != nil
|
21
21
|
end
|
22
|
+
|
23
|
+
# Implementation of String#scrub for Ruby < 2.1. Assumes the string is in
|
24
|
+
# UTF-8.
|
25
|
+
def self.scrub(s)
|
26
|
+
# We have a string in UTF-8 with possible invalid byte sequences. It turns
|
27
|
+
# out that String#encode can remove these sequences when given appropriate
|
28
|
+
# options, but just converting into UTF-8 would be a no-op. So let's convert
|
29
|
+
# into UTF-16 (which has the same character set as UTF-8) and back.
|
30
|
+
#
|
31
|
+
# See also: http://stackoverflow.com/a/21315619
|
32
|
+
s.dup.force_encoding("UTF-8").encode("UTF-16", invalid: :replace).encode("UTF-8")
|
33
|
+
end
|
22
34
|
end
|
23
35
|
|
24
36
|
def with_c_locale(&block)
|
data/lib/html.rb
CHANGED
@@ -16,6 +16,10 @@
|
|
16
16
|
# you may find current contact information at www.suse.com
|
17
17
|
|
18
18
|
class Html
|
19
|
+
def self.escape_javascript(object)
|
20
|
+
object.gsub(/([\\'"])/, "\\\\\\1")
|
21
|
+
end
|
22
|
+
|
19
23
|
def self.generate(description)
|
20
24
|
template = Haml::Engine.new(
|
21
25
|
File.read(File.join(Machinery::ROOT, "html", "index.html.haml"))
|
@@ -36,7 +40,7 @@ class Html
|
|
36
40
|
|
37
41
|
# Generate JSON and escape the 's and "s in order to not break the JSON
|
38
42
|
# string in javascript.
|
39
|
-
json = description.to_hash.to_json
|
43
|
+
json = escape_javascript(description.to_hash.to_json)
|
40
44
|
File.write(File.join(target, "assets/description.js"),<<-EOT
|
41
45
|
function getDescription() {
|
42
46
|
return JSON.parse('#{json}'
|
@@ -47,14 +51,33 @@ class Html
|
|
47
51
|
target
|
48
52
|
end
|
49
53
|
|
54
|
+
def self.generate_comparison(diff, target)
|
55
|
+
FileUtils.mkdir_p(File.join(target, "assets"))
|
56
|
+
template = Haml::Engine.new(
|
57
|
+
File.read(File.join(Machinery::ROOT, "html", "comparison.html.haml"))
|
58
|
+
)
|
59
|
+
|
60
|
+
FileUtils.cp_r(File.join(Machinery::ROOT, "html", "assets"), target)
|
61
|
+
File.write(File.join(target, "index.html"), template.render(binding))
|
62
|
+
json = diff.to_json.gsub("'", "\\\\'").gsub("\"", "\\\\\"")
|
63
|
+
File.write(File.join(target, "assets/diff.js"),<<-EOT
|
64
|
+
function getDiff() {
|
65
|
+
return JSON.parse('#{json}'
|
66
|
+
)
|
67
|
+
}
|
68
|
+
EOT
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
50
72
|
# Template helpers
|
51
73
|
|
52
74
|
def self.scope_help(scope)
|
53
|
-
text = File.read(File.join(Machinery::ROOT, "plugins", "
|
75
|
+
text = File.read(File.join(Machinery::ROOT, "plugins", "#{scope}/#{scope}.md"))
|
54
76
|
Kramdown::Document.new(text).to_html
|
55
77
|
end
|
56
78
|
|
57
79
|
def self.diff_to_object(diff)
|
80
|
+
diff = Machinery.scrub(diff)
|
58
81
|
lines = diff.lines[2..-1]
|
59
82
|
diff_object = {
|
60
83
|
file: diff[/--- a(.*)/, 1],
|
data/lib/inspect_task.rb
CHANGED
@@ -17,7 +17,7 @@
|
|
17
17
|
|
18
18
|
class InspectTask
|
19
19
|
def inspect_system(store, host, name, current_user, scopes, filter, options = {})
|
20
|
-
system = System.for(host)
|
20
|
+
system = System.for(host, options[:remote_user])
|
21
21
|
check_root(system, current_user)
|
22
22
|
|
23
23
|
description, failed_inspections = build_description(store, name, system,
|
data/lib/inspector.rb
CHANGED
@@ -38,6 +38,14 @@ class Inspector
|
|
38
38
|
@inspectors = []
|
39
39
|
|
40
40
|
class << self
|
41
|
+
def priority
|
42
|
+
@priority || 1000
|
43
|
+
end
|
44
|
+
|
45
|
+
def has_priority(value)
|
46
|
+
@priority = value
|
47
|
+
end
|
48
|
+
|
41
49
|
def inherited(klass)
|
42
50
|
@inspectors << klass
|
43
51
|
end
|
@@ -53,7 +61,19 @@ class Inspector
|
|
53
61
|
end
|
54
62
|
|
55
63
|
def all_scopes
|
56
|
-
all.map(&:scope)
|
64
|
+
sort_scopes(all.map(&:scope))
|
65
|
+
end
|
66
|
+
|
67
|
+
def sort_scopes(scope_list)
|
68
|
+
scope_priority = {}
|
69
|
+
|
70
|
+
scope_list.each do |scope|
|
71
|
+
scope_priority[self.for(scope).priority] = scope
|
72
|
+
end
|
73
|
+
|
74
|
+
scope_priority.sort.map do |key, value|
|
75
|
+
scope_priority[key] = value
|
76
|
+
end
|
57
77
|
end
|
58
78
|
|
59
79
|
def scope
|
data/lib/json_validator.rb
CHANGED
@@ -61,22 +61,23 @@ class JsonValidator
|
|
61
61
|
JSON.parse(File.read(File.join(
|
62
62
|
Machinery::ROOT,
|
63
63
|
"schema",
|
64
|
-
"v#{format_version}"
|
65
|
-
"system-description-global.schema.json"
|
64
|
+
"system-description-global.schema-v#{format_version}.json"
|
66
65
|
)))
|
67
66
|
end
|
68
67
|
|
69
68
|
def scope_schemas(format_version = SystemDescription::CURRENT_FORMAT_VERSION)
|
70
|
-
|
69
|
+
schema_path = File.join(
|
71
70
|
Machinery::ROOT,
|
72
71
|
"plugins",
|
72
|
+
"**",
|
73
73
|
"schema",
|
74
|
-
"v#{format_version}"
|
74
|
+
"*.schema-v#{format_version}.json"
|
75
75
|
)
|
76
76
|
|
77
77
|
Hash[
|
78
|
-
Dir[
|
79
|
-
scope = file.match(/system-description-(.*)\.schema\.json$/)[1].
|
78
|
+
Dir[schema_path].map do |file|
|
79
|
+
scope = file.match(/system-description-(.*)\.schema-v#{format_version}\.json$/)[1].
|
80
|
+
tr("-", "_")
|
80
81
|
schema = JSON.parse(File.read(file))
|
81
82
|
|
82
83
|
[scope, schema]
|
data/lib/machinery.rb
CHANGED
@@ -69,7 +69,7 @@ require_relative "helper"
|
|
69
69
|
require_relative "deploy_task"
|
70
70
|
require_relative "analyze_config_file_diffs_task"
|
71
71
|
require_relative "copy_task"
|
72
|
-
require_relative "
|
72
|
+
require_relative "scope"
|
73
73
|
require_relative "ui"
|
74
74
|
require_relative "validate_task"
|
75
75
|
require_relative "migration"
|
@@ -90,6 +90,7 @@ require_relative "file_validator"
|
|
90
90
|
require_relative "element_filter"
|
91
91
|
require_relative "filter"
|
92
92
|
require_relative "filter_option_parser"
|
93
|
+
require_relative "file_scope"
|
93
94
|
|
94
95
|
Dir[File.join(Machinery::ROOT, "plugins", "**", "*.rb")].each { |f| require(f) }
|
95
96
|
|
data/lib/manifest.rb
CHANGED
data/lib/migration.rb
CHANGED
@@ -73,7 +73,7 @@ class Migration
|
|
73
73
|
if !errors.empty?
|
74
74
|
if options[:force]
|
75
75
|
Machinery::Ui.warn("Warning: System Description validation errors:")
|
76
|
-
Machinery::Ui.warn(errors)
|
76
|
+
Machinery::Ui.warn(errors.join(", "))
|
77
77
|
else
|
78
78
|
raise Machinery::Errors::SystemDescriptionValidationFailed.new(errors)
|
79
79
|
end
|
data/lib/remote_system.rb
CHANGED
@@ -17,9 +17,11 @@
|
|
17
17
|
|
18
18
|
class RemoteSystem < System
|
19
19
|
attr_accessor :host
|
20
|
+
attr_accessor :remote_user
|
20
21
|
|
21
|
-
def initialize(host)
|
22
|
+
def initialize(host, remote_user = "root")
|
22
23
|
@host = host
|
24
|
+
@remote_user = remote_user
|
23
25
|
|
24
26
|
connect
|
25
27
|
end
|
@@ -70,19 +72,21 @@ class RemoteSystem < System
|
|
70
72
|
cheetah_class = LoggedCheetah
|
71
73
|
end
|
72
74
|
|
73
|
-
|
75
|
+
sudo = "sudo" if options[:privileged] && remote_user != "root"
|
76
|
+
cmds = ["ssh", "#{remote_user}@#{host}", sudo, "LC_ALL=C", *piped_args, options].compact
|
77
|
+
cheetah_class.run(*cmds)
|
74
78
|
end
|
75
79
|
|
76
80
|
# Tries to connect to the remote system as root (without a password or passphrase)
|
77
81
|
# and raises an Machinery::Errors::SshConnectionFailed exception when it's not successful.
|
78
82
|
def connect
|
79
|
-
LoggedCheetah.run "ssh", "-q", "-o", "BatchMode=yes", "
|
83
|
+
LoggedCheetah.run "ssh", "-q", "-o", "BatchMode=yes", "#{remote_user}@#{host}"
|
80
84
|
rescue Cheetah::ExecutionFailed
|
81
85
|
raise Machinery::Errors::SshConnectionFailed.new(
|
82
86
|
"Could not establish SSH connection to host '#{host}'. Please make sure that " \
|
83
|
-
"you can connect non-interactively as
|
87
|
+
"you can connect non-interactively as #{remote_user}, e.g. using ssh-agent.\n\n" \
|
84
88
|
"To copy your default ssh key to the machine run:\n" \
|
85
|
-
"ssh-copy-id
|
89
|
+
"ssh-copy-id #{remote_user}@#{host}"
|
86
90
|
)
|
87
91
|
end
|
88
92
|
|
@@ -91,9 +95,26 @@ class RemoteSystem < System
|
|
91
95
|
# Machinery::Errors::RsyncFailed exception when it's not successful. Destination is
|
92
96
|
# the directory where to put the files.
|
93
97
|
def retrieve_files(filelist, destination)
|
94
|
-
source="
|
98
|
+
source = "#{remote_user}@#{host}:/"
|
99
|
+
if remote_user != "root"
|
100
|
+
rsync_path = "sudo rsync"
|
101
|
+
else
|
102
|
+
rsync_path = "rsync"
|
103
|
+
end
|
104
|
+
|
105
|
+
cmd = [
|
106
|
+
"rsync",
|
107
|
+
"-e", "ssh",
|
108
|
+
"--chmod=go-rwx",
|
109
|
+
"--files-from=-",
|
110
|
+
"--rsync-path=#{rsync_path}",
|
111
|
+
source,
|
112
|
+
destination,
|
113
|
+
stdout: :capture,
|
114
|
+
stdin: filelist.join("\n")
|
115
|
+
]
|
95
116
|
begin
|
96
|
-
LoggedCheetah.run(
|
117
|
+
LoggedCheetah.run(*cmd)
|
97
118
|
rescue Cheetah::ExecutionFailed => e
|
98
119
|
raise Machinery::Errors::RsyncFailed.new(
|
99
120
|
"Could not rsync files from host '#{host}'.\n" \
|
@@ -104,7 +125,7 @@ class RemoteSystem < System
|
|
104
125
|
|
105
126
|
# Reads a file from the System. Returns nil if it does not exist.
|
106
127
|
def read_file(file)
|
107
|
-
run_command("cat", file, stdout: :capture)
|
128
|
+
run_command("cat", file, stdout: :capture, privileged: true)
|
108
129
|
rescue Cheetah::ExecutionFailed => e
|
109
130
|
if e.status.exitstatus == 1
|
110
131
|
# File not found, return nil
|