machinery-tool 1.16.4 → 1.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/.git_revision +1 -1
  3. data/NEWS +10 -0
  4. data/filters/default_filters.json +21 -20
  5. data/html/assets/machinery-base.js +4 -0
  6. data/html/index.html.haml +1 -1
  7. data/html/partials/changed_managed_files.html.haml +2 -2
  8. data/html/partials/compare/changed_managed_file_list.html.haml +2 -2
  9. data/html/partials/compare/changed_managed_files.html.haml +3 -3
  10. data/html/partials/compare/config_file_list.html.haml +2 -2
  11. data/html/partials/compare/config_files.html.haml +3 -3
  12. data/html/partials/compare/packages.html.haml +21 -4
  13. data/html/partials/compare/repositories.html.haml +10 -7
  14. data/html/partials/compare/repository_list_apt.html.haml +15 -0
  15. data/html/partials/compare/repository_list_yum.html.haml +35 -0
  16. data/html/partials/compare/{repository_list.html.haml → repository_list_zypp.html.haml} +0 -0
  17. data/html/partials/compare/service_list.html.haml +1 -1
  18. data/html/partials/compare/services.html.haml +3 -3
  19. data/html/partials/compare/unmanaged_file_list.html.haml +2 -2
  20. data/html/partials/compare/unmanaged_files.html.haml +1 -1
  21. data/html/partials/config_files.html.haml +39 -41
  22. data/html/partials/repositories.html.haml +1 -23
  23. data/html/partials/repositories_apt.html.haml +15 -0
  24. data/html/partials/repositories_yum.html.haml +30 -0
  25. data/html/partials/repositories_zypp.html.haml +24 -0
  26. data/html/partials/services.html.haml +2 -2
  27. data/html/partials/unmanaged_files.html.haml +2 -2
  28. data/inspect_helpers/dpkg_unmanaged_files.sh +47 -0
  29. data/inspect_helpers/yum_repositories.py +3 -5
  30. data/lib/analyze_config_file_diffs_task.rb +11 -1
  31. data/lib/array.rb +97 -35
  32. data/lib/autoyast.rb +13 -2
  33. data/lib/cli.rb +10 -2
  34. data/lib/config.rb +4 -4
  35. data/lib/dpkg_database.rb +68 -0
  36. data/lib/element_filter.rb +2 -0
  37. data/lib/file_diff.rb +2 -2
  38. data/lib/file_scope.rb +10 -49
  39. data/lib/file_validator.rb +10 -4
  40. data/lib/filter.rb +6 -6
  41. data/lib/filter_option_parser.rb +1 -1
  42. data/lib/kiwi_config.rb +13 -10
  43. data/lib/machinery.rb +2 -0
  44. data/lib/machinery_helper.rb +1 -1
  45. data/lib/managed_files_database.rb +200 -0
  46. data/lib/object.rb +5 -3
  47. data/lib/remote_system.rb +43 -10
  48. data/lib/renderer.rb +3 -4
  49. data/lib/rpm_database.rb +7 -183
  50. data/lib/scope_file_access_archive.rb +3 -3
  51. data/lib/scope_file_access_flat.rb +1 -1
  52. data/lib/server.rb +7 -2
  53. data/lib/system.rb +50 -22
  54. data/lib/system_description.rb +3 -3
  55. data/lib/version.rb +1 -1
  56. data/lib/workload_mapper.rb +2 -2
  57. data/machinery-helper/machinery_helper.go +252 -178
  58. data/machinery-helper/machinery_helper_test.go +121 -121
  59. data/machinery-helper/mountpoints.go +28 -28
  60. data/machinery-helper/tar.go +105 -104
  61. data/machinery-helper/version.go +1 -1
  62. data/man/generated/machinery.1.gz +0 -0
  63. data/man/generated/machinery.1.html +19 -8
  64. data/plugins/changed_managed_files/changed_managed_files_inspector.rb +3 -3
  65. data/plugins/changed_managed_files/changed_managed_files_model.rb +3 -1
  66. data/plugins/changed_managed_files/changed_managed_files_renderer.rb +2 -2
  67. data/plugins/changed_managed_files/schema/system-description-changed-managed-files.schema-v6.json +168 -0
  68. data/plugins/config_files/config_files_inspector.rb +4 -4
  69. data/plugins/config_files/config_files_model.rb +3 -1
  70. data/plugins/config_files/config_files_renderer.rb +2 -2
  71. data/plugins/config_files/schema/system-description-config-files.schema-v6.json +160 -0
  72. data/plugins/environment/schema/system-description-environment.schema-v6.json +17 -0
  73. data/plugins/groups/schema/system-description-groups.schema-v6.json +49 -0
  74. data/plugins/os/schema/system-description-os.schema-v6.json +21 -0
  75. data/plugins/packages/packages_inspector.rb +76 -6
  76. data/plugins/packages/packages_model.rb +31 -12
  77. data/plugins/packages/packages_renderer.rb +5 -2
  78. data/plugins/packages/schema/system-description-packages.schema-v6.json +115 -0
  79. data/plugins/patterns/patterns_inspector.rb +26 -2
  80. data/plugins/patterns/schema/system-description-patterns.schema-v6.json +58 -0
  81. data/plugins/repositories/repositories_inspector.rb +41 -14
  82. data/plugins/repositories/repositories_model.rb +55 -12
  83. data/plugins/repositories/repositories_renderer.rb +23 -7
  84. data/plugins/repositories/schema/system-description-repositories.schema-v6.json +165 -0
  85. data/plugins/services/schema/system-description-services.schema-v6.json +93 -0
  86. data/plugins/services/services_inspector.rb +88 -22
  87. data/plugins/services/services_model.rb +9 -15
  88. data/plugins/services/services_renderer.rb +2 -2
  89. data/plugins/unmanaged_files/schema/system-description-unmanaged-files.schema-v6.json +162 -0
  90. data/plugins/unmanaged_files/unmanaged_files_inspector.rb +80 -30
  91. data/plugins/unmanaged_files/unmanaged_files_model.rb +22 -18
  92. data/plugins/unmanaged_files/unmanaged_files_renderer.rb +3 -3
  93. data/plugins/users/schema/system-description-users.schema-v6.json +86 -0
  94. data/schema/migrations/migrate5to6.rb +101 -0
  95. data/schema/system-description-global.schema-v6.json +43 -0
  96. metadata +24 -4
  97. data/html/assets/landing_page/landing_page.js +0 -10
@@ -13,26 +13,4 @@
13
13
  - if count == 0
14
14
  There are no repositories.
15
15
  - if count > 0
16
- %table.table.table-striped.table-hover.table-condensed.filterable
17
- %thead
18
- %tr
19
- %th Name
20
- %th Alias
21
- %th.small Type
22
- %th URL
23
- %th.small Enabled
24
- %th.small Autorefresh
25
- %th.small GPG Check
26
- %th.small Priority
27
- %tbody
28
- - repositories.each do |repo|
29
- %tr
30
- %td= repo.name
31
- %td= repo.alias
32
- %td= repo.type
33
- %td
34
- %a{ href: repo.url }= repo.url
35
- %td= repo.enabled
36
- %td= repo.autorefresh
37
- %td= repo.gpgcheck
38
- %td= repo.priority
16
+ = render_partial "repositories_#{repositories.repository_system}", repositories: repositories
@@ -0,0 +1,15 @@
1
+ %table.table.table-striped.table-hover.table-condensed.filterable
2
+ %thead
3
+ %tr
4
+ %th.small Type
5
+ %th URL
6
+ %th Distribution
7
+ %th Components
8
+ %tbody
9
+ - repositories.each do |repo|
10
+ %tr
11
+ %td= repo.type
12
+ %td
13
+ %a{ href: repo.url }= repo.url
14
+ %td= repo.distribution
15
+ %td= repo.components.join(", ")
@@ -0,0 +1,30 @@
1
+ %table.table.table-striped.table-hover.table-condensed.filterable
2
+ %thead
3
+ %tr
4
+ %th Name
5
+ %th Alias
6
+ %th.small Type
7
+ %th URL
8
+ %th Mirrorlist
9
+ %th.small Enabled
10
+ %th.small GPG Check
11
+ %th GPG Keys
12
+ %tbody
13
+ - repositories.each do |repo|
14
+ %tr
15
+ %td= repo.name
16
+ %td= repo.alias
17
+ %td= repo.type
18
+ %td
19
+ - repo.url.each do |url|
20
+ %a{ href: url }= url
21
+ %br
22
+ %td
23
+ - unless repo.mirrorlist.empty?
24
+ %a{ href: repo.mirrorlist }= repo.mirrorlist
25
+ %td= repo.enabled
26
+ %td= repo.gpgcheck
27
+ %td
28
+ - repo.gpgkey.each do |url|
29
+ %a{ href: url }= url
30
+ %br
@@ -0,0 +1,24 @@
1
+ %table.table.table-striped.table-hover.table-condensed.filterable
2
+ %thead
3
+ %tr
4
+ %th Name
5
+ %th Alias
6
+ %th.small Type
7
+ %th URL
8
+ %th.small Enabled
9
+ %th.small Autorefresh
10
+ %th.small GPG Check
11
+ %th.small Priority
12
+ %tbody
13
+ - repositories.each do |repo|
14
+ %tr
15
+ %td= repo.name
16
+ %td= repo.alias
17
+ %td= repo.type
18
+ %td
19
+ %a{ href: repo.url }= repo.url
20
+ %td= repo.enabled
21
+ %td= repo.autorefresh
22
+ %td= repo.gpgcheck
23
+ %td= repo.priority
24
+
@@ -2,7 +2,7 @@
2
2
  %div
3
3
  %a.scope_anchor{ id: "services" }
4
4
  .scope#services_container
5
- - count = services.services.length
5
+ - count = services.elements.length
6
6
  = render_partial "scope_header",
7
7
  :scope => "services",
8
8
  :title => "Services",
@@ -19,7 +19,7 @@
19
19
  %th Name
20
20
  %th.medium State
21
21
  %tbody
22
- - services.services.each do |service|
22
+ - services.each do |service|
23
23
  %tr
24
24
  %td= service.name
25
25
  %td{ class: "#{services.init_system}_#{service.state}" }
@@ -2,7 +2,7 @@
2
2
  %div
3
3
  %a.scope_anchor{ id: "unmanaged_files" }
4
4
  .scope#unmanaged_files_container{ "data-scope" => "unmanaged_files" }
5
- - count = unmanaged_files.files.length
5
+ - count = unmanaged_files.length
6
6
  = render_partial "scope_header",
7
7
  :scope => "unmanaged_files",
8
8
  :title => "Unmanaged Files",
@@ -19,7 +19,7 @@
19
19
  %th Name
20
20
  %th.medium Type
21
21
  %tbody
22
- - unmanaged_files.files.each do |file|
22
+ - unmanaged_files.each do |file|
23
23
  %tr
24
24
  %td
25
25
  - if file.on_disk?
@@ -0,0 +1,47 @@
1
+ #!/bin/bash
2
+ # Copyright (c) 2013-2015 SUSE LLC
3
+ #
4
+ # This program is free software; you can redistribute it and/or
5
+ # modify it under the terms of version 3 of the GNU General Public License as
6
+ # published by the Free Software Foundation.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program; if not, contact SUSE LLC.
15
+ #
16
+ # To contact SUSE about this file by physical or electronic mail,
17
+ # you may find current contact information at www.suse.com
18
+
19
+ if [ $UID -ne "0" ]; then
20
+ sudoprefix="sudo -n"
21
+ fi
22
+
23
+ for i in $($sudoprefix dpkg --get-selections | grep -v deinstall | awk '{print $1}'); do
24
+ while read f; do
25
+ type=""
26
+ link=""
27
+ path=${f#*:}
28
+ case "$f" in
29
+ directory:*)
30
+ type="d"
31
+ ;;
32
+ symbolic\ link:*)
33
+ type="l"
34
+ link=" -> $($sudoprefix readlink "$path")"
35
+ ;;
36
+ regular*\ file:*)
37
+ type="-"
38
+ ;;
39
+ *)
40
+ ;;
41
+ esac
42
+ echo "$type $path$link"
43
+ done <<< "$($sudoprefix dpkg -L $i | \
44
+ sed -e 's/^package diverts others to: //' \
45
+ -e 's/^diverted by .* to: //' \
46
+ -e 's/^locally diverted to: //' | xargs -n100 -d'\n' $sudoprefix stat -c "%F:%n")"
47
+ done
@@ -31,13 +31,11 @@ for repo in yb.repos.sort():
31
31
  repo_dict["alias"] = repo.id
32
32
  repo_dict["name"] = repo.name
33
33
  repo_dict["type"] = "rpm-md"
34
- if repo.baseurl:
35
- repo_dict["url"] = repo.baseurl[0]
36
- else:
37
- repo_dict["url"] = ""
34
+ repo_dict["url"] = repo.baseurl or []
35
+ repo_dict["mirrorlist"] = repo.mirrorlist or ""
38
36
  repo_dict["enabled"] = repo.enabled
39
37
  repo_dict["gpgcheck"] = repo.gpgcheck
40
- repo_dict["package_manager"] = "yum"
38
+ repo_dict["gpgkey"] = repo.gpgkey
41
39
  repositories.append(repo_dict)
42
40
 
43
41
  print(json.dumps(repositories))
@@ -18,6 +18,7 @@
18
18
  class AnalyzeConfigFileDiffsTask
19
19
  def analyze(description)
20
20
  description.assert_scopes("os")
21
+ check_os(description)
21
22
  LocalSystem.validate_existence_of_packages(["zypper"])
22
23
  description.validate_analysis_compatibility
23
24
  description.assert_scopes(
@@ -74,6 +75,15 @@ class AnalyzeConfigFileDiffsTask
74
75
 
75
76
  private
76
77
 
78
+ def check_os(description)
79
+ unless description.os.is_a?(OsSuse)
80
+ raise Machinery::Errors::AnalysisFailed.new(
81
+ "Can not analyze the system description because its operating system" \
82
+ " '#{description.os.display_name}' is not supported."
83
+ )
84
+ end
85
+ end
86
+
77
87
  # Creates an array of hashes with the RPM names, version and the list of
78
88
  # changed file paths, e.g.
79
89
  #
@@ -85,7 +95,7 @@ class AnalyzeConfigFileDiffsTask
85
95
  # }
86
96
  # ]
87
97
  def files_by_package(description)
88
- files = description["config_files"].files.
98
+ files = description["config_files"].
89
99
  select { |f| f.changes.include?("md5") }
90
100
 
91
101
  files.inject({}) do |result, file|
data/lib/array.rb CHANGED
@@ -18,41 +18,75 @@
18
18
  module Machinery
19
19
  class Array
20
20
  class << self
21
+ attr_reader :attribute_keys, :element_classes
22
+
23
+ def has_attributes(*keys)
24
+ @attribute_keys = keys.map(&:to_s)
25
+ end
26
+
21
27
  def has_elements(options)
22
- @element_class = options[:class]
28
+ @element_classes ||= []
29
+ @element_classes << options
23
30
  end
24
31
 
25
- def convert_element(element)
26
- if @element_class
27
- element.is_a?(@element_class) ? element : @element_class.from_json(element)
32
+ def from_json(json_object)
33
+ if json_object.is_a?(::Array)
34
+ new(json_object)
28
35
  else
29
- case element
30
- when ::Array
31
- Machinery::Array.from_json(element)
32
- when Hash
33
- Machinery::Object.from_json(element)
34
- else
35
- element
36
- end
36
+ new(json_object["_elements"], json_object["_attributes"])
37
37
  end
38
38
  end
39
+ end
39
40
 
40
- def convert_raw_array(array)
41
- array.map do |element|
42
- convert_element(element)
43
- end
41
+ attr_reader :elements
42
+ attr_accessor :attributes
43
+ attr_accessor :scope
44
+
45
+ def initialize(elements = [], attributes = {})
46
+ attributes ||= {}
47
+ @attribute_keys = self.class.attribute_keys || []
48
+
49
+ unknown_attributes = attributes.keys.map(&:to_s) - @attribute_keys
50
+ if unknown_attributes.length > 0
51
+ raise RuntimeError, "Unknown properties: #{unknown_attributes.join(",")}"
44
52
  end
45
53
 
46
- def from_json(json_object)
47
- new(json_object)
54
+ @attributes = {}
55
+ attributes.each do |k, v|
56
+ @attributes[k.to_s] = v
48
57
  end
58
+ @elements = convert_raw_array(elements)
49
59
  end
50
60
 
51
- attr_reader :elements
52
- attr_accessor :scope
61
+ def convert_element(element)
62
+ (self.class.element_classes || []).each do |definition|
63
+ condition = definition[:if]
64
+ klass = definition[:class]
65
+ if condition
66
+ next if condition.any? do |key, value|
67
+ @attributes[key.to_s] != value
68
+ end
69
+ end
53
70
 
54
- def initialize(elements = [])
55
- @elements = self.class.convert_raw_array(elements)
71
+ return element.is_a?(klass) ? element : klass.from_json(element)
72
+ end
73
+
74
+ case element
75
+ when Hash
76
+ if element.keys.include?("_elements")
77
+ Machinery::Array.from_json(element)
78
+ else
79
+ Machinery::Object.from_json(element)
80
+ end
81
+ else
82
+ element
83
+ end
84
+ end
85
+
86
+ def convert_raw_array(array)
87
+ array.map do |element|
88
+ convert_element(element)
89
+ end
56
90
  end
57
91
 
58
92
  def scope=(scope)
@@ -67,7 +101,7 @@ module Machinery
67
101
  end
68
102
 
69
103
  def ==(other)
70
- self.class == other.class && @elements == other.elements
104
+ self.class == other.class && @elements == other.elements && @attributes == other.attributes
71
105
  end
72
106
 
73
107
  # Various Array operators such as "-" and "&" use #eql? and #hash to compare
@@ -80,50 +114,78 @@ module Machinery
80
114
  end
81
115
 
82
116
  def -(other)
83
- self.class.new(@elements - other.elements)
117
+ self.class.new(@elements - other.elements, @attributes)
84
118
  end
85
119
 
86
120
  def &(other)
87
- self.class.new(@elements & other.elements)
121
+ self.class.new(@elements & other.elements, @attributes)
88
122
  end
89
123
 
90
124
  def push(element)
91
- @elements.push(self.class.convert_element(element))
125
+ @elements.push(convert_element(element))
92
126
  end
93
127
 
94
128
  def <<(element)
95
- @elements << self.class.convert_element(element)
129
+ @elements << convert_element(element)
96
130
  end
97
131
 
98
132
  def +(array)
99
- self.class.new(@elements + self.class.new(array).elements)
133
+ self.class.new(@elements + self.class.new(array).elements, @attributes)
100
134
  end
101
135
 
102
136
  def insert(index, *elements)
103
137
  @elements.insert(index, *self.class.new(elements).elements)
104
138
  end
105
139
 
140
+ def empty?
141
+ @elements.empty?
142
+ end
143
+
106
144
  def as_json
107
- @elements.map do |element|
145
+ object = {}
146
+
147
+ object["_attributes"] = @attributes unless @attributes.empty?
148
+ object["_elements"] = @elements.map do |element|
108
149
  if element.is_a?(Machinery::Array) || element.is_a?(Machinery::Object)
109
150
  element.as_json
110
151
  else
111
152
  element
112
153
  end
113
154
  end
155
+
156
+ object
114
157
  end
115
158
 
116
159
  def compare_with(other)
160
+ only_self = self.class.new(self.elements - other.elements)
161
+ only_other = self.class.new(other.elements - self.elements)
162
+ common = self.class.new(self.elements & other.elements)
163
+
164
+ if self.attributes == other.attributes
165
+ common.attributes = self.attributes
166
+ else
167
+ only_self.attributes = self.attributes
168
+ only_other.attributes = other.attributes
169
+ end
170
+
117
171
  [
118
- self - other,
119
- other - self,
120
- [],
121
- self & other
122
- ].map { |e| e.empty? ? nil : e }
172
+ only_self,
173
+ only_other,
174
+ Machinery::Array.new,
175
+ common
176
+ ].map { |e| (e.empty? && (e.is_a?(Machinery::Array) && e.attributes.empty?)) ? nil : e }
123
177
  end
124
178
 
125
179
  def method_missing(name, *args, &block)
126
- @elements.send(name, *args, &block)
180
+ name = name.to_s
181
+
182
+ if @attribute_keys.include?(name)
183
+ @attributes[name]
184
+ elsif name.end_with?("=") and @attribute_keys.include?(name[0..-2])
185
+ @attributes[name[0..-2]] = args.first
186
+ else
187
+ @elements.send(name, *args, &block)
188
+ end
127
189
  end
128
190
 
129
191
  def respond_to?(name, include_all = false)
data/lib/autoyast.rb CHANGED
@@ -23,9 +23,11 @@ class Autoyast < Exporter
23
23
  @chroot_scripts = []
24
24
  @system_description = description
25
25
  @system_description.assert_scopes(
26
+ "os",
26
27
  "repositories",
27
28
  "packages"
28
29
  )
30
+ check_exported_os
29
31
  if !description.users
30
32
  Machinery::Ui.puts(
31
33
  "\nWarning: Exporting a description without the scope 'users' as AutoYaST" \
@@ -108,6 +110,15 @@ class Autoyast < Exporter
108
110
 
109
111
  private
110
112
 
113
+ def check_exported_os
114
+ unless @system_description.os.is_a?(OsSuse)
115
+ raise Machinery::Errors::ExportFailed.new(
116
+ "Export is not possible because the operating system " \
117
+ "'#{@system_description.os.display_name}' is not supported."
118
+ )
119
+ end
120
+ end
121
+
111
122
  def apply_software_settings(xml)
112
123
  xml.install_recommended "false", "config:type" => "boolean"
113
124
  end
@@ -230,7 +241,7 @@ class Autoyast < Exporter
230
241
 
231
242
  xml.send("services-manager") do
232
243
  xml.services("config:type" => "list") do
233
- @system_description.services.services.each do |service|
244
+ @system_description.services.each do |service|
234
245
  name = service.name
235
246
  if @system_description.services.init_system == "systemd"
236
247
  # Yast can only handle services right now
@@ -270,7 +281,7 @@ class Autoyast < Exporter
270
281
  def apply_changed_files(scope)
271
282
  return if !@system_description.scope_extracted?(scope)
272
283
 
273
- @system_description[scope].files.each do |file|
284
+ @system_description[scope].each do |file|
274
285
  if file.deleted?
275
286
  @chroot_scripts << "rm -rf '#{quote(file.name)}'"
276
287
  elsif file.directory?