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
|
@@ -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.
|
data/plugins/docs/os.md
ADDED
|
@@ -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,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
|