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.
- checksums.yaml +7 -0
- data/COPYING +674 -0
- data/NEWS +143 -0
- data/bin/machinery +29 -0
- data/helpers/changed_managed_files.sh +32 -0
- data/helpers/filter-packages-for-build.yaml +6 -0
- data/html/assets/arrow_down.png +0 -0
- data/html/assets/arrow_up.png +0 -0
- data/html/assets/bootstrap-popover.js +113 -0
- data/html/assets/bootstrap-tooltip.js +457 -0
- data/html/assets/bootstrap.min.css +5 -0
- data/html/assets/collapse.js +174 -0
- data/html/assets/hogan-3.0.2.min.mustache.js +5 -0
- data/html/assets/jquery-2.1.1.min.js +4 -0
- data/html/assets/logo-changed-managed-files-small.png +0 -0
- data/html/assets/logo-changed-managed-files.png +0 -0
- data/html/assets/logo-config-files-small.png +0 -0
- data/html/assets/logo-config-files.png +0 -0
- data/html/assets/logo-groups-small.png +0 -0
- data/html/assets/logo-groups.png +0 -0
- data/html/assets/logo-os-small.png +0 -0
- data/html/assets/logo-os.png +0 -0
- data/html/assets/logo-packages-small.png +0 -0
- data/html/assets/logo-packages.png +0 -0
- data/html/assets/logo-patterns-small.png +0 -0
- data/html/assets/logo-patterns.png +0 -0
- data/html/assets/logo-repositories-small.png +0 -0
- data/html/assets/logo-repositories.png +0 -0
- data/html/assets/logo-services-small.png +0 -0
- data/html/assets/logo-services.png +0 -0
- data/html/assets/logo-unmanaged-files-small.png +0 -0
- data/html/assets/logo-unmanaged-files.png +0 -0
- data/html/assets/logo-users-small.png +0 -0
- data/html/assets/logo-users.png +0 -0
- data/html/assets/machinery-base.css +5767 -0
- data/html/assets/machinery.css +131 -0
- data/html/assets/machinery.js +148 -0
- data/html/assets/transition.js +59 -0
- data/html/assets/wheels_horizontal.png +0 -0
- data/html/index.html.haml +468 -0
- data/kiwi_helpers/kiwi_export_readme.md +22 -0
- data/kiwi_helpers/merge_users_and_groups.pl.erb +231 -0
- data/kiwi_helpers/unmanaged_files_build_excludes +5 -0
- data/lib/analyze_config_file_diffs_task.rb +130 -0
- data/lib/array.rb +98 -0
- data/lib/build_task.rb +124 -0
- data/lib/changed_rpm_files_helper.rb +96 -0
- data/lib/cli.rb +600 -0
- data/lib/compare_task.rb +68 -0
- data/lib/config.rb +33 -0
- data/lib/config_base.rb +117 -0
- data/lib/config_task.rb +56 -0
- data/lib/constants.rb +24 -0
- data/lib/copy_task.rb +22 -0
- data/lib/current_user.rb +23 -0
- data/lib/deploy_task.rb +89 -0
- data/lib/exceptions.rb +113 -0
- data/lib/generate_html_task.rb +22 -0
- data/lib/helper.rb +22 -0
- data/lib/hint.rb +39 -0
- data/lib/html.rb +103 -0
- data/lib/inspect_task.rb +93 -0
- data/lib/inspector.rb +65 -0
- data/lib/kiwi_config.rb +356 -0
- data/lib/kiwi_export_task.rb +36 -0
- data/lib/list_task.rb +64 -0
- data/lib/local_system.rb +127 -0
- data/lib/logged_cheetah.rb +25 -0
- data/lib/machinery.rb +85 -0
- data/lib/machinery_logger.rb +47 -0
- data/lib/migration.rb +128 -0
- data/lib/mountpoints.rb +72 -0
- data/lib/object.rb +138 -0
- data/lib/os.rb +78 -0
- data/lib/remote_system.rb +114 -0
- data/lib/remove_task.rb +43 -0
- data/lib/renderer.rb +243 -0
- data/lib/renderer_helper.rb +26 -0
- data/lib/rpm.rb +52 -0
- data/lib/scope_mixin.rb +38 -0
- data/lib/show_task.rb +65 -0
- data/lib/system.rb +81 -0
- data/lib/system_description.rb +228 -0
- data/lib/system_description_store.rb +167 -0
- data/lib/system_description_validator.rb +216 -0
- data/lib/tarball.rb +82 -0
- data/lib/ui.rb +74 -0
- data/lib/upgrade_format_task.rb +55 -0
- data/lib/validate_task.rb +23 -0
- data/lib/version.rb +22 -0
- data/lib/zypper.rb +70 -0
- data/man/generated/machinery.1.gz +0 -0
- data/man/generated/machinery.1.html +1056 -0
- data/plugins/docs/changed_managed_files.md +2 -0
- data/plugins/docs/config_files.md +5 -0
- data/plugins/docs/groups.md +2 -0
- data/plugins/docs/os.md +2 -0
- data/plugins/docs/packages.md +2 -0
- data/plugins/docs/patterns.md +5 -0
- data/plugins/docs/repositories.md +24 -0
- data/plugins/docs/services.md +6 -0
- data/plugins/docs/unmanaged_files.md +13 -0
- data/plugins/docs/users.md +3 -0
- data/plugins/inspect/changed_managed_files_inspector.rb +109 -0
- data/plugins/inspect/config_files_inspector.rb +117 -0
- data/plugins/inspect/groups_inspector.rb +46 -0
- data/plugins/inspect/os_inspector.rb +116 -0
- data/plugins/inspect/packages_inspector.rb +46 -0
- data/plugins/inspect/patterns_inspector.rb +67 -0
- data/plugins/inspect/repositories_inspector.rb +107 -0
- data/plugins/inspect/services_inspector.rb +88 -0
- data/plugins/inspect/unmanaged_files_inspector.rb +393 -0
- data/plugins/inspect/users_inspector.rb +87 -0
- data/plugins/model/changed_managed_files_model.rb +29 -0
- data/plugins/model/config_files_model.rb +29 -0
- data/plugins/model/groups_model.rb +26 -0
- data/plugins/model/os_model.rb +20 -0
- data/plugins/model/packages_model.rb +26 -0
- data/plugins/model/patterns_model.rb +26 -0
- data/plugins/model/repositories_model.rb +26 -0
- data/plugins/model/services_model.rb +48 -0
- data/plugins/model/unmanaged_files_model.rb +29 -0
- data/plugins/model/users_model.rb +26 -0
- data/plugins/schema/v1/system-description-changed-managed-files.schema.json +83 -0
- data/plugins/schema/v1/system-description-config-files.schema.json +83 -0
- data/plugins/schema/v1/system-description-groups.schema.json +30 -0
- data/plugins/schema/v1/system-description-os.schema.json +21 -0
- data/plugins/schema/v1/system-description-packages.schema.json +34 -0
- data/plugins/schema/v1/system-description-patterns.schema.json +24 -0
- data/plugins/schema/v1/system-description-repositories.schema.json +41 -0
- data/plugins/schema/v1/system-description-services.schema.json +30 -0
- data/plugins/schema/v1/system-description-unmanaged-files.schema.json +105 -0
- data/plugins/schema/v1/system-description-users.schema.json +61 -0
- data/plugins/schema/v2/system-description-changed-managed-files.schema.json +92 -0
- data/plugins/schema/v2/system-description-config-files.schema.json +92 -0
- data/plugins/schema/v2/system-description-groups.schema.json +30 -0
- data/plugins/schema/v2/system-description-os.schema.json +21 -0
- data/plugins/schema/v2/system-description-packages.schema.json +34 -0
- data/plugins/schema/v2/system-description-patterns.schema.json +24 -0
- data/plugins/schema/v2/system-description-repositories.schema.json +41 -0
- data/plugins/schema/v2/system-description-services.schema.json +30 -0
- data/plugins/schema/v2/system-description-unmanaged-files.schema.json +138 -0
- data/plugins/schema/v2/system-description-users.schema.json +61 -0
- data/plugins/show/changed_managed_files_renderer.rb +46 -0
- data/plugins/show/config_files_renderer.rb +62 -0
- data/plugins/show/groups_renderer.rb +36 -0
- data/plugins/show/os_renderer.rb +31 -0
- data/plugins/show/packages_renderer.rb +32 -0
- data/plugins/show/patterns_renderer.rb +32 -0
- data/plugins/show/repositories_renderer.rb +38 -0
- data/plugins/show/services_renderer.rb +32 -0
- data/plugins/show/unmanaged_files_renderer.rb +42 -0
- data/plugins/show/users_renderer.rb +35 -0
- data/schema/migrations/migrate1to2.rb +56 -0
- data/schema/v1/system-description-global.schema.json +31 -0
- data/schema/v2/system-description-global.schema.json +31 -0
- 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
|
data/lib/scope_mixin.rb
ADDED
|
@@ -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
|