machinery-tool 1.4.0 → 1.5.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS +7 -0
  3. data/bin/machinery +3 -1
  4. data/helpers/default_filters.json +24 -0
  5. data/helpers/yum_repositories.py +8 -2
  6. data/lib/autoyast.rb +8 -3
  7. data/lib/changed_rpm_files_helper.rb +34 -7
  8. data/lib/cli.rb +149 -101
  9. data/lib/element_filter.rb +45 -0
  10. data/lib/exceptions.rb +3 -2
  11. data/lib/filter.rb +121 -0
  12. data/lib/inspect_task.rb +25 -4
  13. data/lib/kiwi_config.rb +11 -0
  14. data/lib/list_task.rb +53 -26
  15. data/lib/local_system.rb +1 -1
  16. data/lib/machinery.rb +2 -0
  17. data/lib/manifest.rb +3 -2
  18. data/lib/migration.rb +2 -2
  19. data/lib/system_description.rb +33 -4
  20. data/lib/tarball.rb +5 -5
  21. data/lib/version.rb +1 -1
  22. data/lib/zypper.rb +12 -17
  23. data/man/generated/machinery.1.gz +0 -0
  24. data/man/generated/machinery.1.html +21 -4
  25. data/plugins/docs/changed_managed_files.md +3 -1
  26. data/plugins/docs/config_files.md +3 -2
  27. data/plugins/inspect/changed_managed_files_inspector.rb +8 -2
  28. data/plugins/inspect/config_files_inspector.rb +1 -1
  29. data/plugins/inspect/groups_inspector.rb +3 -1
  30. data/plugins/inspect/os_inspector.rb +2 -2
  31. data/plugins/inspect/packages_inspector.rb +1 -1
  32. data/plugins/inspect/patterns_inspector.rb +1 -1
  33. data/plugins/inspect/repositories_inspector.rb +1 -1
  34. data/plugins/inspect/services_inspector.rb +1 -1
  35. data/plugins/inspect/unmanaged_files_inspector.rb +17 -42
  36. data/plugins/inspect/users_inspector.rb +1 -1
  37. data/plugins/schema/v3/system-description-changed-managed-files.schema.json +1 -1
  38. data/plugins/schema/v3/system-description-config-files.schema.json +1 -1
  39. data/plugins/schema/v3/system-description-repositories.schema.json +1 -1
  40. data/schema/v3/system-description-global.schema.json +12 -0
  41. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 53f3e1829f050fd550e3440debba26aa7a809d02
4
- data.tar.gz: 5826ca3868fbadec1b75b6ecd43b179653818abd
3
+ metadata.gz: 184d1ef94950678ea43a32a035f1b49393fcaa3a
4
+ data.tar.gz: 4e4135549b3a332ae78c453100797d8bcc121ecf
5
5
  SHA512:
6
- metadata.gz: 63953c2f507e6191a4c7bced722aeb749469d4c549efabb1d60709fca0162bb09a807501e001c8ee38167c530cc0095a980f0b8ba8b635d5f82b5ed0fca1b88f
7
- data.tar.gz: d5ea80efa210b5a35ac2d696e065f52fd2749636949ddef90f64fe8ff39ec30e79fe51555a197176d5ea38b619547e7d6176b86bfb8e41e650ed4836e281c67a
6
+ metadata.gz: 19f792e485da42fa7e8dad80d822cd0890f92ffc9cb96a89621bb86b8830388b061b8db39e96fd0afe86d3fe1d3f3a1f7728f8dc9d5788b756619831970b4e65
7
+ data.tar.gz: e692387ddaf55efb16418c5b2db7ff7be53b7d5f0ffb46a2cae6297e0ce4ad090b1455140fef1f4500d7223111f8e1ce9c705b19054cc8ed553f8d8b6e7f1ed1
data/NEWS CHANGED
@@ -1,6 +1,13 @@
1
1
  # Machinery Release Notes
2
2
 
3
3
 
4
+ ## Version 1.5.0 - Fri Mar 13 13:03:47 CET 2015 - thardeck@suse.de
5
+
6
+ * Fix issue with changes of managed files on RHEL (gh#SUSE/machinery#636)
7
+ * Add `--short` option to list command for showing a short list of all descriptions
8
+ * Improve error output for system descriptions which have outdated formats
9
+ * Add `--skip-files` option to `inspect` command for unmanaged files
10
+
4
11
  ## Version 1.4.0 - Wed Feb 18 16:51:43 CET 2015 - thardeck@suse.de
5
12
 
6
13
  * Support inspection of Red Hat Enterprise Linux 6 systems
@@ -22,7 +22,9 @@ require_relative '../lib/machinery'
22
22
  begin
23
23
  LocalSystem.validate_machinery_compatibility
24
24
  Machinery.initialize_logger(ENV["MACHINERY_LOG_FILE"] || Machinery::DEFAULT_LOG_FILE)
25
- Machinery.logger.info "Executing '#{$0} #{ARGV.join(" ")}'"
25
+ command_log = "Executing (Version #{Machinery::VERSION}) '#{$0} #{ARGV.join(" ")}'"
26
+ command_log += " (store: #{ENV["MACHINERY_DIR"]})" if ENV["MACHINERY_DIR"]
27
+ Machinery.logger.info command_log
26
28
  Cli.run(ARGV)
27
29
  rescue Machinery::Errors::IncompatibleHost => e
28
30
  puts e
@@ -0,0 +1,24 @@
1
+ {
2
+ "inspect": [
3
+ "/unmanaged_files/files/name=/etc/passwd",
4
+ "/unmanaged_files/files/name=/etc/shadow",
5
+ "/unmanaged_files/files/name=/etc/group",
6
+ "/unmanaged_files/files/name=/tmp",
7
+ "/unmanaged_files/files/name=/var/tmp",
8
+ "/unmanaged_files/files/name=/lost+found",
9
+ "/unmanaged_files/files/name=/var/run",
10
+ "/unmanaged_files/files/name=/var/lib/rpm",
11
+ "/unmanaged_files/files/name=/.snapshots",
12
+ "/unmanaged_files/files/name=/proc",
13
+ "/unmanaged_files/files/name=/boot",
14
+ "/unmanaged_files/files/name=/etc/init.d/boot.d",
15
+ "/unmanaged_files/files/name=/etc/init.d/rc0.d",
16
+ "/unmanaged_files/files/name=/etc/init.d/rc1.d",
17
+ "/unmanaged_files/files/name=/etc/init.d/rc2.d",
18
+ "/unmanaged_files/files/name=/etc/init.d/rc3.d",
19
+ "/unmanaged_files/files/name=/etc/init.d/rc4.d",
20
+ "/unmanaged_files/files/name=/etc/init.d/rc5.d",
21
+ "/unmanaged_files/files/name=/etc/init.d/rc6.d",
22
+ "/unmanaged_files/files/name=/etc/init.d/rcS.d"
23
+ ]
24
+ }
@@ -17,7 +17,10 @@
17
17
  # you may find current contact information at www.suse.com
18
18
 
19
19
  import yum
20
- import json
20
+ try:
21
+ import json
22
+ except:
23
+ import simplejson as json
21
24
 
22
25
  yb = yum.YumBase()
23
26
 
@@ -28,7 +31,10 @@ for repo in yb.repos.sort():
28
31
  repo_dict["alias"] = repo.id
29
32
  repo_dict["name"] = repo.name
30
33
  repo_dict["type"] = "rpm-md"
31
- repo_dict["url"] = repo.baseurl[0] if repo.baseurl else ""
34
+ if repo.baseurl:
35
+ repo_dict["url"] = repo.baseurl[0]
36
+ else:
37
+ repo_dict["url"] = ""
32
38
  repo_dict["enabled"] = repo.enabled
33
39
  repo_dict["gpgcheck"] = repo.gpgcheck
34
40
  repo_dict["package_manager"] = "yum"
@@ -74,6 +74,7 @@ class Autoyast < Exporter
74
74
  apply_basic_network(xml)
75
75
  apply_repositories(xml)
76
76
  xml.software do
77
+ apply_software_settings(xml)
77
78
  apply_packages(xml)
78
79
  apply_patterns(xml)
79
80
  end
@@ -102,6 +103,10 @@ class Autoyast < Exporter
102
103
 
103
104
  private
104
105
 
106
+ def apply_software_settings(xml)
107
+ xml.install_recommended "false", "config:type" => "boolean"
108
+ end
109
+
105
110
  def apply_non_interactive_mode(xml)
106
111
  xml.general do
107
112
  xml.mode do
@@ -250,7 +255,7 @@ class Autoyast < Exporter
250
255
  xml.send("pre-scripts", "config:type" => "list") do
251
256
  xml.script do
252
257
  xml.source do
253
- xml.cdata 'sed -n \'/.*autoyast2\?=\(.*\)\/.*[^\s]*/s//\1/p\'' \
258
+ xml.cdata 'sed -n \'/.*autoyast2\?=\([^ ]*\)\/.*[^\s]*/s//\1/p\'' \
254
259
  ' /proc/cmdline > /tmp/description_url'
255
260
  end
256
261
  end
@@ -286,7 +291,7 @@ class Autoyast < Exporter
286
291
  !@system_description.unmanaged_files.extracted
287
292
 
288
293
  base = Pathname(@system_description.scope_file_store("unmanaged_files").path)
289
- @chroot_scripts << <<-EOF
294
+ @chroot_scripts << <<-EOF.chomp.gsub(/^\s+/, "")
290
295
  curl -o '/mnt/tmp/filter' "`cat /tmp/description_url`/unmanaged_files_#{@name}_excludes"
291
296
  EOF
292
297
 
@@ -297,7 +302,7 @@ class Autoyast < Exporter
297
302
  tarball_name = File.basename(path)
298
303
  url = "`cat /tmp/description_url`#{URI.escape(File.join("/unmanaged_files", relative_path))}"
299
304
 
300
- @chroot_scripts << <<-EOF
305
+ @chroot_scripts << <<-EOF.chomp.gsub(/^\s+/, "")
301
306
  curl -o '/mnt/tmp/#{tarball_name}' "#{url}"
302
307
  tar -C /mnt/ -X '/mnt/tmp/filter' -xf '#{File.join("/mnt/tmp", tarball_name)}'
303
308
  rm '#{File.join("/mnt/tmp", tarball_name)}'
@@ -16,10 +16,21 @@
16
16
  # you may find current contact information at www.suse.com
17
17
 
18
18
  module ChangedRpmFilesHelper
19
+ def expected_tag?(character, position)
20
+ if @rpm_changes[position] == character
21
+ true
22
+ else
23
+ @unknown_tag ||= ![".", "?"].include?(@rpm_changes[position])
24
+ false
25
+ end
26
+ end
27
+
19
28
  def parse_rpm_changes_line(line)
20
29
  # rpm provides lines per config file where first 9 characters indicate which
21
30
  # properties of the file are modified
22
- rpm_changes, *fields = line.split(" ")
31
+ @rpm_changes, *fields = line.split(" ")
32
+ # nine rpm changes are known
33
+ @unknown_tag = @rpm_changes.size > 9
23
34
 
24
35
  # For config or documentation files there's an additional field which
25
36
  # contains "c" or "d"
@@ -27,17 +38,33 @@ module ChangedRpmFilesHelper
27
38
  path = fields.join(" ")
28
39
 
29
40
  changes = []
30
- if rpm_changes == "missing"
41
+ if @rpm_changes == "missing"
31
42
  changes << "deleted"
32
- elsif rpm_changes == "........." && path.end_with?(" (replaced)")
43
+ elsif @rpm_changes == "........." && path.end_with?(" (replaced)")
33
44
  changes << "replaced"
34
45
  path.slice!(/ \(replaced\)$/)
35
46
  else
36
- changes << "mode" if rpm_changes[1] == "M"
37
- changes << "md5" if rpm_changes[2] == "5"
38
- changes << "user" if rpm_changes[5] == "U"
39
- changes << "group" if rpm_changes[6] == "G"
47
+ changes << "size" if expected_tag?("S", 0)
48
+ changes << "mode" if expected_tag?("M", 1)
49
+ changes << "md5" if expected_tag?("5", 2)
50
+ changes << "device_number" if expected_tag?("D", 3)
51
+ changes << "link_path" if expected_tag?("L", 4)
52
+ changes << "user" if expected_tag?("U", 5)
53
+ changes << "group" if expected_tag?("G", 6)
54
+ changes << "time" if expected_tag?("T", 7)
55
+ changes << "capabilities" if @rpm_changes.size > 8 && expected_tag?("P", 8)
40
56
  end
57
+
58
+ if @unknown_tag
59
+ changes << "other_rpm_changes"
60
+ end
61
+
62
+ if @rpm_changes.include?("?")
63
+ message = "Could not perform all tests on rpm changes for file '#{path}'."
64
+ Machinery.logger.warn(message)
65
+ Machinery::Ui.warn("Warning: #{message}")
66
+ end
67
+
41
68
  [path, changes, type]
42
69
  end
43
70
 
data/lib/cli.rb CHANGED
@@ -22,9 +22,9 @@ class Cli
22
22
  preserve_argv(true)
23
23
  @version = Machinery::VERSION + " (system description format version " +
24
24
  "#{SystemDescription::CURRENT_FORMAT_VERSION})"
25
- switch :version, :negatable => false, :desc => "Show version"
26
- switch :debug, :negatable => false, :desc => "Enable debug mode"
27
- switch [:help, :h], :negatable => false, :desc => "Show help"
25
+ switch :version, negatable: false, desc: "Show version"
26
+ switch :debug, negatable: false, desc: "Enable debug mode"
27
+ switch [:help, :h], negatable: false, desc: "Show help"
28
28
 
29
29
  sort_help :manually
30
30
  pre do |global_options,command,options,args|
@@ -197,13 +197,12 @@ class Cli
197
197
  LONGDESC
198
198
  arg "NAME"
199
199
  command :analyze do |c|
200
- c.flag [:operation, :o], :type => String, :required => true,
201
- :desc => "The analyze operation to perform", :arg_name => "OPERATION"
200
+ c.flag [:operation, :o], type: String, required: true,
201
+ desc: "The analyze operation to perform", arg_name: "OPERATION"
202
202
 
203
203
  c.action do |global_options,options,args|
204
204
  name = shift_arg(args, "NAME")
205
- store = SystemDescriptionStore.new
206
- description = SystemDescription.load(name, store)
205
+ description = SystemDescription.load(name, system_description_store)
207
206
 
208
207
  case options[:operation]
209
208
  when "config-file-diffs"
@@ -228,20 +227,22 @@ class Cli
228
227
  LONGDESC
229
228
  arg "NAME"
230
229
  command :build do |c|
231
- c.flag ["image-dir", :i], :type => String, :required => true,
232
- :desc => "Store the image under the specified path", :arg_name => "DIRECTORY"
233
- c.switch ["enable-dhcp", :d], :required => false, :negatable => false,
234
- :desc => "Enable DCHP client on first network card of built image"
235
- c.switch ["enable-ssh", :s], :required => false, :negatable => false,
236
- :desc => "Enable SSH service in built image"
230
+ c.flag ["image-dir", :i], type: String, required: true,
231
+ desc: "Store the image under the specified path", arg_name: "DIRECTORY"
232
+ c.switch ["enable-dhcp", :d], required: false, negatable: false,
233
+ desc: "Enable DCHP client on first network card of built image"
234
+ c.switch ["enable-ssh", :s], required: false, negatable: false,
235
+ desc: "Enable SSH service in built image"
237
236
 
238
237
  c.action do |global_options,options,args|
239
238
  name = shift_arg(args, "NAME")
240
- store = SystemDescriptionStore.new
241
- description = SystemDescription.load(name, store)
239
+ description = SystemDescription.load(name, system_description_store)
242
240
 
243
241
  task = BuildTask.new
244
- task.build(description, File.expand_path(options["image-dir"]), {:enable_dhcp => options["enable-dhcp"], :enable_ssh => options["enable-ssh"]})
242
+ task.build(
243
+ description, File.expand_path(options["image-dir"]),
244
+ enable_dhcp: options["enable-dhcp"], enable_ssh: options["enable-ssh"]
245
+ )
245
246
  end
246
247
  end
247
248
 
@@ -259,19 +260,19 @@ class Cli
259
260
  arg "NAME1"
260
261
  arg "NAME2"
261
262
  command :compare do |c|
262
- c.flag [:scope, :s], :type => String, :required => false,
263
- :desc => "Compare specified scopes", :arg_name => "SCOPE_LIST"
264
- c.flag ["exclude-scope", :e], :type => String, :required => false,
265
- :desc => "Exclude specified scopes", :arg_name => "SCOPE_LIST"
266
- c.switch "show-all", :required => false, :negatable => false,
267
- :desc => "Show also common properties"
268
- c.switch "pager", :required => false, :default_value => true,
269
- :desc => "Pipe output into a pager"
263
+ c.flag [:scope, :s], type: String, required: false,
264
+ desc: "Compare specified scopes", arg_name: "SCOPE_LIST"
265
+ c.flag ["exclude-scope", :e], type: String, required: false,
266
+ desc: "Exclude specified scopes", arg_name: "SCOPE_LIST"
267
+ c.switch "show-all", required: false, negatable: false,
268
+ desc: "Show also common properties"
269
+ c.switch "pager", required: false, default_value: true,
270
+ desc: "Pipe output into a pager"
270
271
 
271
272
  c.action do |global_options,options,args|
272
273
  name1 = shift_arg(args, "NAME1")
273
274
  name2 = shift_arg(args, "NAME2")
274
- store = SystemDescriptionStore.new
275
+ store = system_description_store
275
276
  description1 = SystemDescription.load(name1, store)
276
277
  description2 = SystemDescription.load(name2, store)
277
278
  scope_list = process_scope_option(options[:scope], options["exclude-scope"])
@@ -298,9 +299,8 @@ class Cli
298
299
  c.action do |global_options,options,args|
299
300
  from = shift_arg(args, "FROM_NAME")
300
301
  to = shift_arg(args, "TO_NAME")
301
- store = SystemDescriptionStore.new
302
302
  task = CopyTask.new
303
- task.copy(store, from, to)
303
+ task.copy(system_description_store, from, to)
304
304
  end
305
305
  end
306
306
 
@@ -315,19 +315,18 @@ class Cli
315
315
  LONGDESC
316
316
  arg "NAME"
317
317
  command :deploy do |c|
318
- c.flag ["cloud-config", :c], :type => String, :required => true, :arg_name => "FILE",
319
- :desc => "Path to file where the cloud config (openrc.sh) is located"
320
- c.flag ["image-dir", :i], :type => String, :required => false,
321
- :desc => "Directory where the image is located", :arg_name => "DIRECTORY"
322
- c.switch [:insecure, :s], :required => false, :negatable => false,
323
- :desc => "Explicitly allow glanceclient to perform 'insecure SSL' (https) requests."
324
- c.flag ["cloud-image-name", :n], :type => String, :required => false,
325
- :desc => "Name of the image in the cloud", :arg_name => "NAME"
318
+ c.flag ["cloud-config", :c], type: String, required: true, arg_name: "FILE",
319
+ desc: "Path to file where the cloud config (openrc.sh) is located"
320
+ c.flag ["image-dir", :i], type: String, required: false,
321
+ desc: "Directory where the image is located", arg_name: "DIRECTORY"
322
+ c.switch [:insecure, :s], required: false, negatable: false,
323
+ desc: "Explicitly allow glanceclient to perform 'insecure SSL' (https) requests."
324
+ c.flag ["cloud-image-name", :n], type: String, required: false,
325
+ desc: "Name of the image in the cloud", arg_name: "NAME"
326
326
 
327
327
  c.action do |global_options,options,args|
328
328
  name = shift_arg(args, "NAME")
329
- store = SystemDescriptionStore.new
330
- description = SystemDescription.load(name, store)
329
+ description = SystemDescription.load(name, system_description_store)
331
330
 
332
331
  task = DeployTask.new
333
332
  opts = {
@@ -350,15 +349,14 @@ class Cli
350
349
  LONGDESC
351
350
  arg "NAME"
352
351
  command "export-kiwi" do |c|
353
- c.flag ["kiwi-dir", :k], :type => String, :required => true,
354
- :desc => "Location where the description will be stored", :arg_name => "DIRECTORY"
355
- c.switch :force, :default_value => false, :required => false, :negatable => false,
356
- :desc => "Overwrite existing description"
352
+ c.flag ["kiwi-dir", :k], type: String, required: true,
353
+ desc: "Location where the description will be stored", arg_name: "DIRECTORY"
354
+ c.switch :force, default_value: false, required: false, negatable: false,
355
+ desc: "Overwrite existing description"
357
356
 
358
357
  c.action do |global_options,options,args|
359
358
  name = shift_arg(args, "NAME")
360
- store = SystemDescriptionStore.new
361
- description = SystemDescription.load(name, store)
359
+ description = SystemDescription.load(name, system_description_store)
362
360
  exporter = KiwiConfig.new(description)
363
361
 
364
362
  task = ExportTask.new(exporter)
@@ -387,8 +385,7 @@ class Cli
387
385
 
388
386
  c.action do |_global_options, options, args|
389
387
  name = shift_arg(args, "NAME")
390
- store = SystemDescriptionStore.new
391
- description = SystemDescription.load(name, store)
388
+ description = SystemDescription.load(name, system_description_store)
392
389
  exporter = Autoyast.new(description)
393
390
 
394
391
  task = ExportTask.new(exporter)
@@ -412,26 +409,28 @@ class Cli
412
409
  LONGDESC
413
410
  arg "HOSTNAME"
414
411
  command :inspect do |c|
415
- c.flag [:name, :n], :type => String, :required => false, :arg_name => "NAME",
416
- :desc => "Store system description under the specified name"
417
- c.flag [:scope, :s], :type => String, :required => false,
418
- :desc => "Show specified scopes", :arg_name => "SCOPE_LIST"
419
- c.flag ["exclude-scope", :e], :type => String, :required => false,
420
- :desc => "Exclude specified scopes", :arg_name => "SCOPE_LIST"
421
- c.switch ["extract-files", :x], :required => false, :negatable => false,
422
- :desc => "Extract changed configuration files and unmanaged files from inspected system"
423
- c.switch "extract-changed-config-files", :required => false, :negatable => false,
424
- :desc => "Extract changed configuration files from inspected system"
425
- c.switch "extract-unmanaged-files", :required => false, :negatable => false,
426
- :desc => "Extract unmanaged files from inspected system"
427
- c.switch "extract-changed-managed-files", :required => false, :negatable => false,
428
- :desc => "Extract changed managed files from inspected system"
429
- c.switch :show, :required => false, :negatable => false,
430
- :desc => "Print inspection result"
412
+ c.flag [:name, :n], type: String, required: false, arg_name: "NAME",
413
+ desc: "Store system description under the specified name"
414
+ c.flag [:scope, :s], type: String, required: false,
415
+ desc: "Show specified scopes", arg_name: "SCOPE_LIST"
416
+ c.flag ["exclude-scope", :e], type: String, required: false,
417
+ desc: "Exclude specified scopes", arg_name: "SCOPE_LIST"
418
+ c.flag "skip-files", required: false, negatable: false,
419
+ desc: "Do not consider given files or directories during inspection. " \
420
+ "Either provide one file or directory name or a list of names separated by commas."
421
+ c.switch ["extract-files", :x], required: false, negatable: false,
422
+ desc: "Extract changed configuration files and unmanaged files from inspected system"
423
+ c.switch "extract-changed-config-files", required: false, negatable: false,
424
+ desc: "Extract changed configuration files from inspected system"
425
+ c.switch "extract-unmanaged-files", required: false, negatable: false,
426
+ desc: "Extract unmanaged files from inspected system"
427
+ c.switch "extract-changed-managed-files", required: false, negatable: false,
428
+ desc: "Extract changed managed files from inspected system"
429
+ c.switch :show, required: false, negatable: false,
430
+ desc: "Print inspection result"
431
431
 
432
432
  c.action do |global_options,options,args|
433
433
  host = shift_arg(args, "HOSTNAME")
434
- store = SystemDescriptionStore.new
435
434
  inspector_task = InspectTask.new
436
435
  scope_list = process_scope_option(options[:scope], options["exclude-scope"])
437
436
  name = options[:name] || host
@@ -456,14 +455,27 @@ class Cli
456
455
  inspect_options[:extract_unmanaged_files] = true
457
456
  end
458
457
 
458
+ if options["skip-files"] && !(scope_list & ["config_files", "changed_managed_files"]).empty?
459
+ Machinery::Ui.warn("Warning: The --skip-files option is currently only supported for the " \
460
+ "\"unmanaged-files\" scope")
461
+ end
462
+
463
+ filter = prepare_filter("inspect", options)
464
+
459
465
  inspector_task.inspect_system(
460
- store, host, name, CurrentUser.new, scope_list, inspect_options
466
+ system_description_store,
467
+ host,
468
+ name,
469
+ CurrentUser.new,
470
+ scope_list,
471
+ filter,
472
+ inspect_options
461
473
  )
462
474
 
463
- Hint.show_data(:name => name)
475
+ Hint.show_data(name: name)
464
476
 
465
477
  if !options["extract-files"] || Inspector.all_scopes.count != scope_list.count
466
- Hint.do_complete_inspection(:name => name, :host => host)
478
+ Hint.do_complete_inspection(name: name, host: host)
467
479
  end
468
480
  end
469
481
  end
@@ -478,13 +490,14 @@ class Cli
478
490
  option.
479
491
  LONGDESC
480
492
  command :list do |c|
481
- c.switch :verbose, :required => false, :negatable => false,
482
- :desc => "Display additional information about origin of scopes"
493
+ c.switch :verbose, required: false, negatable: false,
494
+ desc: "Display additional information about origin of scopes"
495
+ c.switch :short, required: false, negatable: false,
496
+ desc: "List only description names"
483
497
 
484
498
  c.action do |global_options,options,args|
485
- store = SystemDescriptionStore.new
486
499
  task = ListTask.new
487
- task.list(store, options)
500
+ task.list(system_description_store, options)
488
501
  end
489
502
  end
490
503
 
@@ -498,16 +511,14 @@ class Cli
498
511
  LONGDESC
499
512
  arg "NAME..."
500
513
  command :remove do |c|
501
- c.switch :all, :negatable => false,
502
- :desc => "Remove all system descriptions"
503
- c.switch :verbose, :required => false, :negatable => false,
504
- :desc => "Explain what is being done"
514
+ c.switch :all, negatable: false,
515
+ desc: "Remove all system descriptions"
516
+ c.switch :verbose, required: false, negatable: false,
517
+ desc: "Explain what is being done"
505
518
 
506
519
  c.action do |global_options,options,args|
507
-
508
- store = SystemDescriptionStore.new
509
520
  task = RemoveTask.new
510
- task.remove(store, args, :verbose => options[:verbose], :all => options[:all])
521
+ task.remove(system_description_store, args, verbose: options[:verbose], all: options[:all])
511
522
  end
512
523
  end
513
524
 
@@ -524,25 +535,23 @@ class Cli
524
535
  LONGDESC
525
536
  arg "NAME"
526
537
  command :show do |c|
527
- c.flag [:scope, :s], :type => String, :required => false,
528
- :desc => "Show specified scopes", :arg_name => "SCOPE_LIST"
529
- c.flag ["exclude-scope", :e], :type => String, :required => false,
530
- :desc => "Exclude specified scopes", :arg_name => "SCOPE_LIST"
531
- c.switch "pager", :required => false, :default_value => true,
532
- :desc => "Pipe output into a pager"
533
- c.switch "show-diffs", :required => false, :negatable => false,
534
- :desc => "Show diffs of configuration files changes."
535
- c.switch "html", :required => false, :negatable => false,
536
- :desc => "Open system description in HTML format in your web browser."
538
+ c.flag [:scope, :s], type: String, required: false,
539
+ desc: "Show specified scopes", arg_name: "SCOPE_LIST"
540
+ c.flag ["exclude-scope", :e], type: String, required: false,
541
+ desc: "Exclude specified scopes", arg_name: "SCOPE_LIST"
542
+ c.switch "pager", required: false, default_value: true,
543
+ desc: "Pipe output into a pager"
544
+ c.switch "show-diffs", required: false, negatable: false,
545
+ desc: "Show diffs of configuration files changes."
546
+ c.switch "html", required: false, negatable: false,
547
+ desc: "Open system description in HTML format in your web browser."
537
548
 
538
549
  c.action do |global_options,options,args|
539
550
  name = shift_arg(args, "NAME")
540
551
  if name == "localhost" && !CurrentUser.new.is_root?
541
552
  Machinery::Ui.puts "You need root rights to access the system description of your locally inspected system."
542
553
  end
543
-
544
- store = SystemDescriptionStore.new
545
- description = SystemDescription.load(name, store)
554
+ description = SystemDescription.load(name, system_description_store)
546
555
  scope_list = process_scope_option(options[:scope], options["exclude-scope"])
547
556
 
548
557
 
@@ -569,9 +578,8 @@ class Cli
569
578
  Machinery::Ui.puts "You need root rights to access the system description of your locally inspected system."
570
579
  end
571
580
 
572
- store = SystemDescriptionStore.new
573
581
  task = ValidateTask.new
574
- task.validate(store, name)
582
+ task.validate(system_description_store, name)
575
583
  end
576
584
  end
577
585
 
@@ -581,21 +589,20 @@ class Cli
581
589
  LONGDESC
582
590
  arg "NAME"
583
591
  command "upgrade-format" do |c|
584
- c.switch :all, :negatable => false,
585
- :desc => "Upgrade all system descriptions"
586
- c.switch :force, :default_value => false, :required => false, :negatable => false,
587
- :desc => "Keep backup after migration and ingnore validation errors"
592
+ c.switch :all, negatable: false,
593
+ desc: "Upgrade all system descriptions"
594
+ c.switch :force, default_value: false, required: false, negatable: false,
595
+ desc: "Keep backup after migration and ingnore validation errors"
588
596
 
589
597
  c.action do |global_options,options,args|
590
598
  name = shift_arg(args, "NAME") if !options[:all]
591
599
 
592
- store = SystemDescriptionStore.new
593
600
  task = UpgradeFormatTask.new
594
601
  task.upgrade(
595
- store,
602
+ system_description_store,
596
603
  name,
597
- :all => options[:all],
598
- :force => options[:force]
604
+ all: options[:all],
605
+ force: options[:force]
599
606
  )
600
607
  end
601
608
  end
@@ -609,8 +616,7 @@ class Cli
609
616
  c.action do |global_options,options,args|
610
617
  name = shift_arg(args, "NAME")
611
618
 
612
- store = SystemDescriptionStore.new
613
- description = SystemDescription.load(name, store)
619
+ description = SystemDescription.load(name, system_description_store)
614
620
  task = GenerateHtmlTask.new
615
621
  task.generate(description)
616
622
  end
@@ -638,4 +644,46 @@ class Cli
638
644
  end
639
645
  end
640
646
  end
647
+
648
+ def self.system_description_store
649
+ if ENV.has_key?("MACHINERY_DIR")
650
+ SystemDescriptionStore.new(ENV["MACHINERY_DIR"])
651
+ else
652
+ SystemDescriptionStore.new
653
+ end
654
+ end
655
+
656
+
657
+ def self.prepare_filter(command, options)
658
+ filter = Filter.from_default_definition(command)
659
+
660
+ skip_files = options.delete("skip-files")
661
+ if skip_files
662
+ files = skip_files.split(/(?<!\\),/) # Do not split on escaped commas
663
+ files = files.flat_map do |file|
664
+ if file.start_with?("@")
665
+ filename = File.expand_path(file[1..-1])
666
+
667
+ if !File.exists?(filename)
668
+ raise Machinery::Errors::MachineryError.new(
669
+ "The filter file '#{filename}' does not exist."
670
+ )
671
+ end
672
+ File.read(filename).lines.map(&:strip)
673
+ else
674
+ file
675
+ end
676
+ end
677
+
678
+ files.reject!(&:empty?) # Ignore empty filters
679
+ files.map! { |file| file.gsub("\\@", "@") } # Unescape escaped @s
680
+ files.map! { |file| file.chomp("/") } # List directories without the trailing /, in order to
681
+ # not confuse the unmanaged files inspector
682
+ files.each do |file|
683
+ filter.add_element_filter_from_definition("/unmanaged_files/files/name=#{file}")
684
+ end
685
+ end
686
+
687
+ filter
688
+ end
641
689
  end