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
@@ -0,0 +1,2 @@
1
+ Contains the names and contents of all non-configuration files which have
2
+ been changed compared to the files in the package.
@@ -0,0 +1,5 @@
1
+ Contains all configuration files which have been changed since they were
2
+ installed.
3
+ Configuration files are all those files which are marked as such in the
4
+ package which has installed them. A configuration file is considered changed
5
+ if either its content or its Linux permission bits have changed.
@@ -0,0 +1,2 @@
1
+ Contains information about the system groups such as group attributes and the
2
+ list of group members.
@@ -0,0 +1,2 @@
1
+ Contains information about the operating system, name, version, and
2
+ architecture of the inspected system.
@@ -0,0 +1,2 @@
1
+ Contains information on all installed RPM packages installed on the
2
+ inspected system.
@@ -0,0 +1,5 @@
1
+ Contains all patterns installed on the inspected system. A pattern is a
2
+ collection of software packages.
3
+ The meaning of software patterns depends on the package manager of the
4
+ distribution. Therefore, the pattern scope on SUSE based systems uses the
5
+ `zypper` command to obtain the information about installed pattern names.
@@ -0,0 +1,24 @@
1
+ Contains all information about software repositories configured on the
2
+ inspected system. The information about repositories depends on the package
3
+ manager of the distribution. Thus on SUSE-based systems the `zypper` command
4
+ is used. Machinery collects the following information from each configured repository:
5
+
6
+ - The alias name of the repository.
7
+
8
+ - The repository type, rpm-md and YaST types that are used on SUSE systems.
9
+
10
+ - The path to the repository. This could be a local path, a remote location,
11
+ a device, or a file.
12
+
13
+ - A boolean flag that indicates if this repository is in use or not.
14
+
15
+ - A boolean flag that indicates if this repository should update the locally
16
+ stored metadata files with metadata files from the origin automatically or
17
+ not.
18
+
19
+ - A boolean flag that indicates if packages which would be installed from
20
+ this repository should be checked by their gpg key or not.
21
+
22
+ - A numeric value for a priority. The priority of a repository is compared
23
+ to the priorities of all other activated repositories. Values can
24
+ range from 1 (highest) to 99 (lowest, default).
@@ -0,0 +1,6 @@
1
+ Services are applications running in the background doing continuous work
2
+ or waiting for requests to do work.
3
+ The scope determines which services are configured to be started in which
4
+ runlevel. It uses the `chkconfig` command to obtain that information.
5
+ The xinetd services that are also displayed by `chkconfig` are switched
6
+ on/off by editing config files and are ignored in this context.
@@ -0,0 +1,13 @@
1
+ Contains the names and contents of all files which are not part of any RPM
2
+ package. The list of unmanaged files contains only plain files and
3
+ directories. Special files like device nodes, named pipes and Unix domain
4
+ sockets are ignored. The directories `/tmp`, `/var/tmp`, `/sys`, `/dev`,
5
+ `/.snapshots/`, and `/var/run` are ignored, too. If a directory is in this
6
+ list, no file or directory below it belongs to a RPM package.
7
+
8
+ Meta data information of unmanaged files is only available if the files were
9
+ extracted during inspection.
10
+
11
+ Using the `--extract-unmanaged-files` option, the files are transferred from
12
+ the system and stored in the system description. Depending on the content of
13
+ the inspected system, the amount of data stored may be huge.
@@ -0,0 +1,3 @@
1
+ Contains information about the system users including user and group ids,
2
+ login information, such as password hashes and - if available - additional
3
+ password properties.
@@ -0,0 +1,109 @@
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 ChangedManagedFilesInspector < Inspector
19
+ include ChangedRpmFilesHelper
20
+
21
+ def inspect(system, description, options = {})
22
+ @system = system
23
+ store_name = "changed_managed_files"
24
+
25
+ result = changed_files
26
+
27
+ description.remove_file_store(store_name)
28
+ if options[:extract_changed_managed_files]
29
+ description.initialize_file_store(store_name)
30
+ existing_files = changed_files.reject { |f| f.changes.nil? || f.changes.include?("deleted") }
31
+ system.retrieve_files(existing_files.map(&:name), description.file_store(store_name))
32
+ end
33
+
34
+ summary = "#{options[:extract_changed_managed_files] ? "Extracted" : "Found"} #{result.count} changed files."
35
+
36
+ description["changed_managed_files"] = ChangedManagedFilesScope.new(
37
+ extracted: !!options[:extract_changed_managed_files],
38
+ files: ChangedManagedFileList.new(result.sort_by(&:name))
39
+ )
40
+ summary
41
+ end
42
+
43
+ private
44
+
45
+ def amend_file_attributes(changed_files)
46
+ existing_files = changed_files.reject { |f| f.changes.nil? || f.changes.include?("deleted") }
47
+ file_attributes = get_path_data(@system, existing_files.map(&:name))
48
+ changed_files.map do |changed_file|
49
+ if file_attributes[changed_file.name]
50
+ ChangedManagedFile.new(changed_file.attributes.merge(file_attributes[changed_file.name]))
51
+ else
52
+ changed_file
53
+ end
54
+ end
55
+ end
56
+
57
+ def changed_files
58
+ raw_list = @system.run_script("changed_managed_files.sh", stdout: :capture)
59
+
60
+ # The raw list lists each package followed by the changed files, e.g.
61
+ #
62
+ # libpulse0-4.0.git.270.g9490a:
63
+ # S.5...... c /etc/pulse/client.conf
64
+ # ntp-4.2.6p5:
65
+ # S.5...... c /etc/ntp.conf
66
+ #
67
+ # We map this to an array of files like this:
68
+ #
69
+ # [
70
+ # {
71
+ # name: "/etc/pulse/client.conf",
72
+ # package_name: "libpulse0",
73
+ # package_version: "4.0.git.270.g9490a"
74
+ # },
75
+ # ...
76
+ # ]
77
+ changed_files = raw_list.split("\n").slice_before(/(.*):\z/).flat_map do |package, *changed_files|
78
+ package_name, package_version = package.scan(/(.*)-([^-]*):/).first
79
+ changed_files.map do |changed_file|
80
+ if changed_file =~ /\A(\/\S+) (.*)/
81
+ ChangedManagedFile.new(
82
+ name: $1,
83
+ package_name: package_name,
84
+ package_version: package_version,
85
+ status: "error",
86
+ error_message: $2
87
+ )
88
+ else
89
+ file, changes, flag = parse_rpm_changes_line(changed_file)
90
+
91
+ # Config files (flagged as 'c') are handled by the ConfigFilesInspector
92
+ next if flag == "c"
93
+
94
+ ChangedManagedFile.new(
95
+ name: file,
96
+ package_name: package_name,
97
+ package_version: package_version,
98
+ status: "changed",
99
+ changes: changes
100
+ )
101
+ end
102
+ # Since errors are also recognized for config-files we have
103
+ # to filter them
104
+ end.compact.select { |item| item.changes }
105
+ end
106
+ amend_file_attributes(changed_files)
107
+ end
108
+
109
+ end
@@ -0,0 +1,117 @@
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 ConfigFilesInspector < Inspector
19
+ include ChangedRpmFilesHelper
20
+
21
+ # checks if all required binaries are present
22
+ def check_requirements(system, check_rsync)
23
+ system.check_requirement("rpm", "--version")
24
+ system.check_requirement("stat", "--version")
25
+ system.check_requirement("rsync", "--version") if check_rsync
26
+ end
27
+
28
+ # returns list of packages containing configfiles
29
+ def packages_with_config_files(system)
30
+ # first determine packages that have config files at all
31
+ # rpm command provides lines with package names and subsequent
32
+ # lines with pathes of config files for that package
33
+ # e.g.
34
+ # apache2
35
+ # /etc/apache2/charset.conv
36
+ # /etc/apache2/default-server.conf
37
+ #
38
+ output = system.run_command(
39
+ "rpm", "-qa", "--configfiles", "--queryformat",
40
+ "%{NAME}-%{VERSION}\n",
41
+ :stdout => :capture
42
+ )
43
+ # use leading slash to decide between lines containing package names
44
+ # and lines containing config files
45
+ chunks = output.split("\n").slice_before { |l| !l.start_with?("/") }
46
+ chunks.reject { |pkg, *cfiles| cfiles.empty? }.map(&:first)
47
+ end
48
+
49
+ # returns a hash with entries for changed config files
50
+ def config_file_changes(system, pkg)
51
+ begin
52
+ out = system.run_command(
53
+ "rpm", "-V",
54
+ "--nodeps", "--nodigest", "--nosignature", "--nomtime", "--nolinkto",
55
+ pkg,
56
+ :stdout => :capture
57
+ )
58
+ # rpm returns 1 as exit code when modified config files are detected
59
+ # currently cheetah cannot be told to ignore this and throws ExecutionFailed
60
+ rescue Cheetah::ExecutionFailed => e
61
+ out = e.stdout
62
+ end
63
+
64
+ parts = pkg.split("-")
65
+ package_name = parts[0..-2].join("-")
66
+ package_version = parts.last
67
+
68
+ paths_and_changes = out.lines.map { |line| parse_rpm_changes_line(line) }
69
+ paths_and_changes.reject! do |path, changes, type|
70
+ # only consider config files and only those with changes
71
+ type != "c" || changes.empty?
72
+ end
73
+
74
+ paths_and_changes.map do |path, changes|
75
+ ConfigFile.new(
76
+ name: path,
77
+ package_name: package_name,
78
+ package_version: package_version,
79
+ status: "changed",
80
+ changes: changes
81
+ )
82
+ end
83
+ end
84
+
85
+ def inspect(system, description, options = {})
86
+ do_extract = options[:extract_changed_config_files]
87
+ check_requirements(system, do_extract)
88
+
89
+ result = packages_with_config_files(system).flat_map do |package|
90
+ config_file_changes(system, package)
91
+ end
92
+
93
+ paths = result.reject { |f| f.changes == ["deleted"] }.map(&:name)
94
+ path_data = get_path_data(system, paths)
95
+ key_list = [ :user, :group, :mode ]
96
+ result.each do |pkg|
97
+ pname = pkg.name
98
+ if path_data.has_key?(pname)
99
+ key_list.each { |k| pkg[k] = path_data[pname][k] }
100
+ end
101
+ end
102
+
103
+ description.remove_file_store("config_files")
104
+ if do_extract
105
+ description.initialize_file_store("config_files")
106
+ system.retrieve_files(paths, description.file_store("config_files"))
107
+ end
108
+
109
+ summary = "#{do_extract ? "Extracted" : "Found"} #{result.count} changed configuration files."
110
+
111
+ description["config_files"] = ConfigFilesScope.new(
112
+ extracted: !!do_extract,
113
+ files: ConfigFileList.new(result.sort_by(&:name))
114
+ )
115
+ summary
116
+ end
117
+ end
@@ -0,0 +1,46 @@
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 GroupsInspector < Inspector
19
+ def inspect(system, description, options = {})
20
+ group_content = system.read_file("/etc/group")
21
+
22
+ groups = group_content ? parse_groups(group_content) : []
23
+
24
+ description.groups = GroupsScope.new(groups.sort_by(&:name))
25
+ "Found #{groups.size} groups."
26
+ end
27
+
28
+ private
29
+
30
+ def parse_groups(content)
31
+ content.lines.map do |line|
32
+ name, password, gid, users = line.split(":").map(&:chomp)
33
+
34
+ gid = Machinery::is_int?(gid) ? gid.to_i : nil
35
+
36
+ attrs = {
37
+ name: name,
38
+ password: password,
39
+ gid: gid,
40
+ users: users.split(",")
41
+ }
42
+
43
+ Group.new(attrs)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,116 @@
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
+ # Inspect name, version, and other attributes of the operating system
19
+ class OsInspector < Inspector
20
+ # determines the architecture
21
+ def get_arch(system)
22
+ system.run_command("uname", "-m", :stdout => :capture).chomp
23
+ end
24
+
25
+ def strip_arch_from_name(name)
26
+ # architecture information in the name might be misleading
27
+ # information with regards to the real architecture name.
28
+ # in addition the architecture information is not consistently
29
+ # added for all distributions. Thus we strip this part
30
+ name.gsub(/\((i.86|x86_64|s390|ia64|ppc|arm).*\)/, "").strip
31
+ end
32
+
33
+ # checks for additional version information like Beta or RC
34
+ def get_additional_version(system)
35
+ issue = system.read_file("/etc/issue")
36
+ special_version = issue.scan(/Beta\d+|RC\d|GMC\d*/).first if issue
37
+
38
+ special_version ? " #{special_version.gsub(/[0-9]{1,2}/," \\0")}" : ""
39
+ end
40
+
41
+ def inspect(system, description, _options = {})
42
+ system.check_requirement("cat", "--version") if system.is_a?(RemoteSystem)
43
+
44
+ os = get_os(system)
45
+ if os
46
+ os.architecture = get_arch(system)
47
+ os.version += get_additional_version(system)
48
+ summary = "Found operating system '#{os.name}' version '#{os.version}'."
49
+ else
50
+ os = OsScope.new(name: nil, version: nil, architecture: nil)
51
+ summary = "Could not determine the operating system."
52
+ end
53
+
54
+ description.os = os
55
+ summary
56
+ end
57
+
58
+ private
59
+
60
+ def get_os(system)
61
+ # Use os-release file by default
62
+ os = get_os_from_os_release(system)
63
+
64
+ # Fall back to SuSE-release file
65
+ if !os
66
+ os = get_os_from_suse_release(system)
67
+ end
68
+
69
+ os
70
+ end
71
+
72
+ # check for freedesktop standard: /etc/os-release
73
+ def get_os_from_os_release(system)
74
+ os_release = system.read_file("/etc/os-release")
75
+ return if !os_release
76
+
77
+ result = Hash.new
78
+ key_value_pairs = Hash[os_release.split("\n").map { |l| l.split("=") }]
79
+ key_value_pairs.each_pair do |k,v|
80
+ result[k.downcase] = v.strip.gsub(/^"|"$/,"")
81
+ end
82
+ if result["pretty_name"]
83
+ result["pretty_name"] = strip_arch_from_name(result["pretty_name"])
84
+ end
85
+ # return pretty_name as name as it contains the actual full length
86
+ # name instead of an abbreviation
87
+ OsScope.new(
88
+ name: result["pretty_name"],
89
+ version: result["version"]
90
+ )
91
+ end
92
+
93
+ # checks for old suse standard: /etc/SuSE-release
94
+ def get_os_from_suse_release(system)
95
+ suse_release = system.read_file("/etc/SuSE-release")
96
+ return if !suse_release
97
+
98
+ result = Hash.new
99
+ # name is always the first line in /etc/SuSE-release
100
+ result["name"] = strip_arch_from_name(suse_release.split("\n").first)
101
+
102
+ patch = nil
103
+ suse_release.each_line do |l|
104
+ if l.start_with?("VERSION")
105
+ result["version"] = l.split("=").last.strip
106
+ end
107
+ if l.start_with?("PATCHLEVEL")
108
+ patch = l.split("=").last.strip
109
+ end
110
+ end
111
+ if result["version"] && !patch.nil?
112
+ result["version"] = "#{result["version"]} SP#{patch}"
113
+ end
114
+ OsScope.new(result)
115
+ end
116
+ end