machinery-tool 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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