machinery-tool 1.0.2

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 (157) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +674 -0
  3. data/NEWS +143 -0
  4. data/bin/machinery +29 -0
  5. data/helpers/changed_managed_files.sh +32 -0
  6. data/helpers/filter-packages-for-build.yaml +6 -0
  7. data/html/assets/arrow_down.png +0 -0
  8. data/html/assets/arrow_up.png +0 -0
  9. data/html/assets/bootstrap-popover.js +113 -0
  10. data/html/assets/bootstrap-tooltip.js +457 -0
  11. data/html/assets/bootstrap.min.css +5 -0
  12. data/html/assets/collapse.js +174 -0
  13. data/html/assets/hogan-3.0.2.min.mustache.js +5 -0
  14. data/html/assets/jquery-2.1.1.min.js +4 -0
  15. data/html/assets/logo-changed-managed-files-small.png +0 -0
  16. data/html/assets/logo-changed-managed-files.png +0 -0
  17. data/html/assets/logo-config-files-small.png +0 -0
  18. data/html/assets/logo-config-files.png +0 -0
  19. data/html/assets/logo-groups-small.png +0 -0
  20. data/html/assets/logo-groups.png +0 -0
  21. data/html/assets/logo-os-small.png +0 -0
  22. data/html/assets/logo-os.png +0 -0
  23. data/html/assets/logo-packages-small.png +0 -0
  24. data/html/assets/logo-packages.png +0 -0
  25. data/html/assets/logo-patterns-small.png +0 -0
  26. data/html/assets/logo-patterns.png +0 -0
  27. data/html/assets/logo-repositories-small.png +0 -0
  28. data/html/assets/logo-repositories.png +0 -0
  29. data/html/assets/logo-services-small.png +0 -0
  30. data/html/assets/logo-services.png +0 -0
  31. data/html/assets/logo-unmanaged-files-small.png +0 -0
  32. data/html/assets/logo-unmanaged-files.png +0 -0
  33. data/html/assets/logo-users-small.png +0 -0
  34. data/html/assets/logo-users.png +0 -0
  35. data/html/assets/machinery-base.css +5767 -0
  36. data/html/assets/machinery.css +131 -0
  37. data/html/assets/machinery.js +148 -0
  38. data/html/assets/transition.js +59 -0
  39. data/html/assets/wheels_horizontal.png +0 -0
  40. data/html/index.html.haml +468 -0
  41. data/kiwi_helpers/kiwi_export_readme.md +22 -0
  42. data/kiwi_helpers/merge_users_and_groups.pl.erb +231 -0
  43. data/kiwi_helpers/unmanaged_files_build_excludes +5 -0
  44. data/lib/analyze_config_file_diffs_task.rb +130 -0
  45. data/lib/array.rb +98 -0
  46. data/lib/build_task.rb +124 -0
  47. data/lib/changed_rpm_files_helper.rb +96 -0
  48. data/lib/cli.rb +600 -0
  49. data/lib/compare_task.rb +68 -0
  50. data/lib/config.rb +33 -0
  51. data/lib/config_base.rb +117 -0
  52. data/lib/config_task.rb +56 -0
  53. data/lib/constants.rb +24 -0
  54. data/lib/copy_task.rb +22 -0
  55. data/lib/current_user.rb +23 -0
  56. data/lib/deploy_task.rb +89 -0
  57. data/lib/exceptions.rb +113 -0
  58. data/lib/generate_html_task.rb +22 -0
  59. data/lib/helper.rb +22 -0
  60. data/lib/hint.rb +39 -0
  61. data/lib/html.rb +103 -0
  62. data/lib/inspect_task.rb +93 -0
  63. data/lib/inspector.rb +65 -0
  64. data/lib/kiwi_config.rb +356 -0
  65. data/lib/kiwi_export_task.rb +36 -0
  66. data/lib/list_task.rb +64 -0
  67. data/lib/local_system.rb +127 -0
  68. data/lib/logged_cheetah.rb +25 -0
  69. data/lib/machinery.rb +85 -0
  70. data/lib/machinery_logger.rb +47 -0
  71. data/lib/migration.rb +128 -0
  72. data/lib/mountpoints.rb +72 -0
  73. data/lib/object.rb +138 -0
  74. data/lib/os.rb +78 -0
  75. data/lib/remote_system.rb +114 -0
  76. data/lib/remove_task.rb +43 -0
  77. data/lib/renderer.rb +243 -0
  78. data/lib/renderer_helper.rb +26 -0
  79. data/lib/rpm.rb +52 -0
  80. data/lib/scope_mixin.rb +38 -0
  81. data/lib/show_task.rb +65 -0
  82. data/lib/system.rb +81 -0
  83. data/lib/system_description.rb +228 -0
  84. data/lib/system_description_store.rb +167 -0
  85. data/lib/system_description_validator.rb +216 -0
  86. data/lib/tarball.rb +82 -0
  87. data/lib/ui.rb +74 -0
  88. data/lib/upgrade_format_task.rb +55 -0
  89. data/lib/validate_task.rb +23 -0
  90. data/lib/version.rb +22 -0
  91. data/lib/zypper.rb +70 -0
  92. data/man/generated/machinery.1.gz +0 -0
  93. data/man/generated/machinery.1.html +1056 -0
  94. data/plugins/docs/changed_managed_files.md +2 -0
  95. data/plugins/docs/config_files.md +5 -0
  96. data/plugins/docs/groups.md +2 -0
  97. data/plugins/docs/os.md +2 -0
  98. data/plugins/docs/packages.md +2 -0
  99. data/plugins/docs/patterns.md +5 -0
  100. data/plugins/docs/repositories.md +24 -0
  101. data/plugins/docs/services.md +6 -0
  102. data/plugins/docs/unmanaged_files.md +13 -0
  103. data/plugins/docs/users.md +3 -0
  104. data/plugins/inspect/changed_managed_files_inspector.rb +109 -0
  105. data/plugins/inspect/config_files_inspector.rb +117 -0
  106. data/plugins/inspect/groups_inspector.rb +46 -0
  107. data/plugins/inspect/os_inspector.rb +116 -0
  108. data/plugins/inspect/packages_inspector.rb +46 -0
  109. data/plugins/inspect/patterns_inspector.rb +67 -0
  110. data/plugins/inspect/repositories_inspector.rb +107 -0
  111. data/plugins/inspect/services_inspector.rb +88 -0
  112. data/plugins/inspect/unmanaged_files_inspector.rb +393 -0
  113. data/plugins/inspect/users_inspector.rb +87 -0
  114. data/plugins/model/changed_managed_files_model.rb +29 -0
  115. data/plugins/model/config_files_model.rb +29 -0
  116. data/plugins/model/groups_model.rb +26 -0
  117. data/plugins/model/os_model.rb +20 -0
  118. data/plugins/model/packages_model.rb +26 -0
  119. data/plugins/model/patterns_model.rb +26 -0
  120. data/plugins/model/repositories_model.rb +26 -0
  121. data/plugins/model/services_model.rb +48 -0
  122. data/plugins/model/unmanaged_files_model.rb +29 -0
  123. data/plugins/model/users_model.rb +26 -0
  124. data/plugins/schema/v1/system-description-changed-managed-files.schema.json +83 -0
  125. data/plugins/schema/v1/system-description-config-files.schema.json +83 -0
  126. data/plugins/schema/v1/system-description-groups.schema.json +30 -0
  127. data/plugins/schema/v1/system-description-os.schema.json +21 -0
  128. data/plugins/schema/v1/system-description-packages.schema.json +34 -0
  129. data/plugins/schema/v1/system-description-patterns.schema.json +24 -0
  130. data/plugins/schema/v1/system-description-repositories.schema.json +41 -0
  131. data/plugins/schema/v1/system-description-services.schema.json +30 -0
  132. data/plugins/schema/v1/system-description-unmanaged-files.schema.json +105 -0
  133. data/plugins/schema/v1/system-description-users.schema.json +61 -0
  134. data/plugins/schema/v2/system-description-changed-managed-files.schema.json +92 -0
  135. data/plugins/schema/v2/system-description-config-files.schema.json +92 -0
  136. data/plugins/schema/v2/system-description-groups.schema.json +30 -0
  137. data/plugins/schema/v2/system-description-os.schema.json +21 -0
  138. data/plugins/schema/v2/system-description-packages.schema.json +34 -0
  139. data/plugins/schema/v2/system-description-patterns.schema.json +24 -0
  140. data/plugins/schema/v2/system-description-repositories.schema.json +41 -0
  141. data/plugins/schema/v2/system-description-services.schema.json +30 -0
  142. data/plugins/schema/v2/system-description-unmanaged-files.schema.json +138 -0
  143. data/plugins/schema/v2/system-description-users.schema.json +61 -0
  144. data/plugins/show/changed_managed_files_renderer.rb +46 -0
  145. data/plugins/show/config_files_renderer.rb +62 -0
  146. data/plugins/show/groups_renderer.rb +36 -0
  147. data/plugins/show/os_renderer.rb +31 -0
  148. data/plugins/show/packages_renderer.rb +32 -0
  149. data/plugins/show/patterns_renderer.rb +32 -0
  150. data/plugins/show/repositories_renderer.rb +38 -0
  151. data/plugins/show/services_renderer.rb +32 -0
  152. data/plugins/show/unmanaged_files_renderer.rb +42 -0
  153. data/plugins/show/users_renderer.rb +35 -0
  154. data/schema/migrations/migrate1to2.rb +56 -0
  155. data/schema/v1/system-description-global.schema.json +31 -0
  156. data/schema/v2/system-description-global.schema.json +31 -0
  157. metadata +370 -0
data/lib/renderer.rb ADDED
@@ -0,0 +1,243 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ # Renderer is the base class for all text renderer plugins
19
+ #
20
+ # It defines methods for rendering data which will be called from the
21
+ # specialized `do_render` methods in the subclasses.
22
+ #
23
+ # The names of the subclasses are 1:1 mappings of the scope areas, e.g.
24
+ # the PackagesRenderer class would be used for rendering when the user
25
+ # specifies "--scope=packages".
26
+ #
27
+ # The rendering methods are:
28
+ # def heading(s) - Render a heading
29
+ # def puts(s) - Print one line
30
+ # def list(name) - Start a list. This method takes a block where the items are
31
+ # created.
32
+ # def item(s) - Print a list item
33
+ #
34
+ # Accordingly a simple renderer for the "packages" scope could look like this:
35
+ #
36
+ # class PackagesRenderer < Renderer
37
+ # def do_render
38
+ # return if @system_description.packages.empty?
39
+ #
40
+ # list "Packages" do
41
+ # @system_description.packages.each do |p|
42
+ # item "#{p.name} (#{p.version})"
43
+ # end
44
+ # end
45
+ # end
46
+ # end
47
+ class Renderer
48
+
49
+ class InvalidStructureError < StandardError; end
50
+
51
+ attr_accessor :system_description
52
+ attr_accessor :buffer
53
+
54
+ abstract_method :do_render
55
+
56
+ @@renderers = []
57
+
58
+ class << self
59
+ def inherited(klass)
60
+ @@renderers << klass
61
+ end
62
+
63
+ def all
64
+ @@renderers.map { |renderer| renderer.new }
65
+ end
66
+
67
+ def for(scope)
68
+ class_name = "#{scope.split("_").map(&:capitalize).join}Renderer"
69
+
70
+ if Object.const_defined?(class_name)
71
+ Object.const_get(class_name).new
72
+ end
73
+ end
74
+ end
75
+
76
+ def render(system_description, options = {})
77
+ @system_description = system_description
78
+ @options = options
79
+ @buffer = ""
80
+ @indent = 2
81
+ @stack = []
82
+
83
+ if system_description[scope]
84
+ header = display_name
85
+ meta = system_description[scope].meta
86
+
87
+ if system_description[scope].is_extractable?
88
+ if @system_description.scope_extracted?(scope)
89
+ header += " (extracted)"
90
+ else
91
+ header += " (not extracted)"
92
+ end
93
+ end
94
+ if meta
95
+ header += " [#{meta.hostname}]"
96
+ date = Time.parse(meta.modified).localtime
97
+ date_human = date.strftime "%Y-%m-%d %H:%M:%S"
98
+ header += " (#{date_human})"
99
+ end
100
+
101
+ heading(header)
102
+ end
103
+
104
+ do_render
105
+
106
+ @buffer += "\n" unless @buffer.empty? || @buffer.end_with?("\n\n")
107
+
108
+ @buffer
109
+ end
110
+
111
+ def render_comparison_section(description)
112
+ @system_description = description
113
+ indent { do_render }
114
+ @buffer += "\n" unless @buffer.empty? || @buffer.end_with?("\n\n")
115
+ end
116
+
117
+ def render_comparison_only_in(description, scope)
118
+ if description[scope]
119
+ puts "Only in '#{description.name}':"
120
+ render_comparison_section(description)
121
+ end
122
+ end
123
+
124
+ def render_comparison_common(description, scope)
125
+ if description[scope]
126
+ puts "Common to both systems:"
127
+ render_comparison_section(description)
128
+ end
129
+ end
130
+
131
+ def render_comparison(description1, description2, description_common, options = {})
132
+ @options = options
133
+ @buffer = ""
134
+ @indent = 0
135
+ @stack = []
136
+
137
+ show_heading = if options[:show_all]
138
+ description1[scope] || description2[scope] || description_common[scope]
139
+ else
140
+ description1[scope] || description2[scope]
141
+ end
142
+
143
+ heading(display_name) if show_heading
144
+
145
+ render_comparison_only_in(description1, scope)
146
+ render_comparison_only_in(description2, scope)
147
+ render_comparison_common(description_common, scope) if options[:show_all]
148
+
149
+ @buffer
150
+ end
151
+
152
+ def render_comparison_missing_scope(description1, description2)
153
+ @buffer = ""
154
+ @indent = 0
155
+ @stack = []
156
+ missing_descriptions = Array.new
157
+
158
+ @buffer += "# #{display_name}\n"
159
+
160
+ if !description1[scope]
161
+ missing_descriptions << description1.name
162
+ end
163
+ if !description2[scope]
164
+ missing_descriptions << description2.name
165
+ end
166
+
167
+ indent { puts "Unable to compare, no data in '#{missing_descriptions.join("', '")}'" }
168
+ @buffer += "\n" unless @buffer.empty? || @buffer.end_with?("\n\n")
169
+
170
+ @buffer
171
+ end
172
+
173
+ def heading(s)
174
+ @buffer += "# #{s}\n\n"
175
+ end
176
+
177
+ def puts(s)
178
+ print_indented "#{s}"
179
+ end
180
+
181
+ def list(name = nil, &block)
182
+ unless block_given?
183
+ raise InvalidStructureError.new(
184
+ "'list' was called without a block"
185
+ )
186
+ end
187
+
188
+ @stack << :list
189
+
190
+
191
+ if name && !name.empty?
192
+ print_indented "#{name}:"
193
+ indent do
194
+ block.call
195
+ end
196
+ else
197
+ block.call
198
+ end
199
+ @buffer += "\n" unless @buffer.end_with?("\n\n")
200
+
201
+ @stack.pop
202
+ end
203
+
204
+ def item(s, &block)
205
+ unless @stack.last == :list
206
+ raise InvalidStructureError.new(
207
+ "'item' was called outside of a list block"
208
+ )
209
+ end
210
+
211
+ print_indented "* #{s}"
212
+
213
+ if block_given?
214
+ @stack << :item
215
+ indent do
216
+ block.call
217
+ end
218
+ @buffer += "\n"
219
+ @stack.pop
220
+ end
221
+ end
222
+
223
+ def scope
224
+ # Return the un-camelcased name of the inspector,
225
+ # e.g. "foo_bar" for "FooBarInspector"
226
+ scope = self.class.name.match(/^(.*)Renderer$/)[1]
227
+ scope.gsub(/([^A-Z])([A-Z])/, "\\1_\\2").downcase
228
+ end
229
+
230
+ private
231
+
232
+ def print_indented(s)
233
+ s.split("\n").each do |line|
234
+ @buffer += " " * @indent + line + "\n"
235
+ end
236
+ end
237
+
238
+ def indent
239
+ @indent += 2
240
+ yield
241
+ @indent -= 2
242
+ end
243
+ end
@@ -0,0 +1,26 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ def number_to_human_size(s)
19
+ unit = %W(B KiB MiB GiB TiB)
20
+ i = s.to_i
21
+
22
+ exp = i != 0 ? Math.log(i, 1024).floor : 0
23
+ value = (i / 1024.0 ** exp).round(1)
24
+
25
+ "#{"%g" % value} #{unit[exp]}"
26
+ end
data/lib/rpm.rb ADDED
@@ -0,0 +1,52 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ # Rpm represents an RPM package on the disk.
19
+ class Rpm
20
+ def initialize(path)
21
+ @path = path
22
+ end
23
+
24
+ def diff(file, local_file)
25
+ begin
26
+ cpio = LoggedCheetah.run("rpm2cpio", @path, stdout: :capture)
27
+ original_config = LoggedCheetah.run(
28
+ "cpio", "-iv", "--to-stdout", ".#{file}", stdin: cpio, stdout: :capture
29
+ )
30
+ rescue Cheetah::ExecutionFailed => e
31
+ Machinery.logger.error(e.stderr)
32
+ return nil
33
+ end
34
+
35
+ begin
36
+ LoggedCheetah.run(
37
+ "diff", "-u", "--label", "#{File.join("a", file)}", "--from-file=-",
38
+ "--label", "#{File.join("b", file)}", local_file,
39
+ stdin: original_config,
40
+ stdout: :capture
41
+ )
42
+ rescue Cheetah::ExecutionFailed => e
43
+ # diff exits with 1 when there are changes
44
+ if e.status.exitstatus == 1
45
+ e.stdout
46
+ else
47
+ Machinery.logger.error(e.stderr)
48
+ return nil
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,38 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ module Machinery
19
+ module ScopeMixin
20
+ attr_accessor :meta
21
+
22
+ def set_metadata(timestring, host)
23
+ self.meta = Machinery::Object.new(
24
+ modified: timestring,
25
+ hostname: host
26
+ )
27
+ end
28
+
29
+ def scope_name
30
+ scope = self.class.name.match(/^(.*)Scope$/)[1]
31
+ scope.gsub(/([^A-Z])([A-Z])/, "\\1_\\2").downcase
32
+ end
33
+
34
+ def is_extractable?
35
+ SystemDescription::EXTRACTABLE_SCOPES.include?(self.scope_name)
36
+ end
37
+ end
38
+ end
data/lib/show_task.rb ADDED
@@ -0,0 +1,65 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ class ShowTask
19
+ def show(description, scopes, options = {})
20
+ if options[:show_html]
21
+ show_html(description)
22
+ else
23
+ show_console(description, scopes, options )
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def show_html(description)
30
+ begin
31
+ LocalSystem.validate_existence_of_package("xdg-utils")
32
+ Html.generate(description)
33
+ html_path = SystemDescriptionStore.new.html_path(description.name)
34
+ LoggedCheetah.run("xdg-open", html_path)
35
+ rescue Cheetah::ExecutionFailed => e
36
+ raise Machinery::Errors::OpenInBrowserFailed.new(
37
+ "Could not open system description \"#{description.name}\" in the web browser.\n" \
38
+ "Error: #{e}\n"
39
+ )
40
+ end
41
+ end
42
+
43
+ def show_console(description, scopes, options)
44
+ missing_scopes = []
45
+ output = ""
46
+
47
+ scopes.map { |s| Renderer.for(s) }.each do |renderer|
48
+ section = renderer.render(description, options)
49
+ unless section.empty?
50
+ output += section
51
+ else
52
+ missing_scopes << renderer.scope
53
+ end
54
+ end
55
+
56
+ if missing_scopes.length > 0
57
+ output += "# The following requested scopes were not inspected\n\n"
58
+ missing_scopes.each do |scope|
59
+ output += " * #{Machinery::Ui.internal_scope_list_to_string(scope)}\n"
60
+ end
61
+ end
62
+
63
+ Machinery::Ui.print_output(output, :no_pager => options[:no_pager])
64
+ end
65
+ end
data/lib/system.rb ADDED
@@ -0,0 +1,81 @@
1
+ # Copyright (c) 2013-2014 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ # System and its subclasses are used to represent systems that are to be
19
+ # inspected.
20
+ #
21
+ # It abstracts common inspection tasks that need to be run, like executing
22
+ # commands or running "kiwi --describe". Different implementations, e.g. for
23
+ # local or ssh-accessed systems are done in the according subclasses.
24
+ class System
25
+ abstract_method :requires_root?
26
+ abstract_method :run_command
27
+ abstract_method :kiwi_describe
28
+ abstract_method :retrieve_files
29
+ abstract_method :read_file
30
+
31
+ def self.for(host)
32
+ if host && host != "localhost"
33
+ RemoteSystem.new(host)
34
+ else
35
+ LocalSystem.new
36
+ end
37
+ end
38
+
39
+ # checks if the required command can be executed on the target system
40
+ def check_requirement(command, *args)
41
+ begin
42
+ run_command(command, *args)
43
+ rescue Cheetah::ExecutionFailed
44
+ raise Machinery::Errors::MissingRequirement.new(
45
+ "Need binary '#{command}' to be available on the inspected system."
46
+ )
47
+ end
48
+ end
49
+
50
+ # Retrieves files specified in filelist from the remote system and create an archive.
51
+ # To be able to deal with arbitrary filenames we use zero-terminated
52
+ # filelist and the --null option of tar
53
+ def create_archive(filelist, archive, exclude = [])
54
+ created = !File.exists?(archive)
55
+ out = File.open(archive, "w")
56
+ begin
57
+ run_command(
58
+ "tar", "--directory=/", "--create", "--gzip", "--null", "--files-from=-",
59
+ *exclude.flat_map { |f| ["--exclude", f]},
60
+ :stdout => out,
61
+ :stdin => filelist
62
+ )
63
+ rescue Cheetah::ExecutionFailed => e
64
+ if e.status.exitstatus == 1
65
+ # The tarball has been created successfully but some files were changed
66
+ # on disk while being archived, so we just log the warning and go on
67
+ Machinery.logger.info e.stderr
68
+ else
69
+ raise
70
+ end
71
+ end
72
+ out.close
73
+ File.chmod(0600, archive) if created
74
+ end
75
+
76
+ def run_script(*args)
77
+ script = File.read(File.join(Machinery::ROOT, "helpers", args.shift))
78
+
79
+ run_command("bash", "-c", script, *args)
80
+ end
81
+ end