machinery-tool 1.16.4 → 1.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.git_revision +1 -1
- data/NEWS +10 -0
- data/filters/default_filters.json +21 -20
- data/html/assets/machinery-base.js +4 -0
- data/html/index.html.haml +1 -1
- data/html/partials/changed_managed_files.html.haml +2 -2
- data/html/partials/compare/changed_managed_file_list.html.haml +2 -2
- data/html/partials/compare/changed_managed_files.html.haml +3 -3
- data/html/partials/compare/config_file_list.html.haml +2 -2
- data/html/partials/compare/config_files.html.haml +3 -3
- data/html/partials/compare/packages.html.haml +21 -4
- data/html/partials/compare/repositories.html.haml +10 -7
- data/html/partials/compare/repository_list_apt.html.haml +15 -0
- data/html/partials/compare/repository_list_yum.html.haml +35 -0
- data/html/partials/compare/{repository_list.html.haml → repository_list_zypp.html.haml} +0 -0
- data/html/partials/compare/service_list.html.haml +1 -1
- data/html/partials/compare/services.html.haml +3 -3
- data/html/partials/compare/unmanaged_file_list.html.haml +2 -2
- data/html/partials/compare/unmanaged_files.html.haml +1 -1
- data/html/partials/config_files.html.haml +39 -41
- data/html/partials/repositories.html.haml +1 -23
- data/html/partials/repositories_apt.html.haml +15 -0
- data/html/partials/repositories_yum.html.haml +30 -0
- data/html/partials/repositories_zypp.html.haml +24 -0
- data/html/partials/services.html.haml +2 -2
- data/html/partials/unmanaged_files.html.haml +2 -2
- data/inspect_helpers/dpkg_unmanaged_files.sh +47 -0
- data/inspect_helpers/yum_repositories.py +3 -5
- data/lib/analyze_config_file_diffs_task.rb +11 -1
- data/lib/array.rb +97 -35
- data/lib/autoyast.rb +13 -2
- data/lib/cli.rb +10 -2
- data/lib/config.rb +4 -4
- data/lib/dpkg_database.rb +68 -0
- data/lib/element_filter.rb +2 -0
- data/lib/file_diff.rb +2 -2
- data/lib/file_scope.rb +10 -49
- data/lib/file_validator.rb +10 -4
- data/lib/filter.rb +6 -6
- data/lib/filter_option_parser.rb +1 -1
- data/lib/kiwi_config.rb +13 -10
- data/lib/machinery.rb +2 -0
- data/lib/machinery_helper.rb +1 -1
- data/lib/managed_files_database.rb +200 -0
- data/lib/object.rb +5 -3
- data/lib/remote_system.rb +43 -10
- data/lib/renderer.rb +3 -4
- data/lib/rpm_database.rb +7 -183
- data/lib/scope_file_access_archive.rb +3 -3
- data/lib/scope_file_access_flat.rb +1 -1
- data/lib/server.rb +7 -2
- data/lib/system.rb +50 -22
- data/lib/system_description.rb +3 -3
- data/lib/version.rb +1 -1
- data/lib/workload_mapper.rb +2 -2
- data/machinery-helper/machinery_helper.go +252 -178
- data/machinery-helper/machinery_helper_test.go +121 -121
- data/machinery-helper/mountpoints.go +28 -28
- data/machinery-helper/tar.go +105 -104
- data/machinery-helper/version.go +1 -1
- data/man/generated/machinery.1.gz +0 -0
- data/man/generated/machinery.1.html +19 -8
- data/plugins/changed_managed_files/changed_managed_files_inspector.rb +3 -3
- data/plugins/changed_managed_files/changed_managed_files_model.rb +3 -1
- data/plugins/changed_managed_files/changed_managed_files_renderer.rb +2 -2
- data/plugins/changed_managed_files/schema/system-description-changed-managed-files.schema-v6.json +168 -0
- data/plugins/config_files/config_files_inspector.rb +4 -4
- data/plugins/config_files/config_files_model.rb +3 -1
- data/plugins/config_files/config_files_renderer.rb +2 -2
- data/plugins/config_files/schema/system-description-config-files.schema-v6.json +160 -0
- data/plugins/environment/schema/system-description-environment.schema-v6.json +17 -0
- data/plugins/groups/schema/system-description-groups.schema-v6.json +49 -0
- data/plugins/os/schema/system-description-os.schema-v6.json +21 -0
- data/plugins/packages/packages_inspector.rb +76 -6
- data/plugins/packages/packages_model.rb +31 -12
- data/plugins/packages/packages_renderer.rb +5 -2
- data/plugins/packages/schema/system-description-packages.schema-v6.json +115 -0
- data/plugins/patterns/patterns_inspector.rb +26 -2
- data/plugins/patterns/schema/system-description-patterns.schema-v6.json +58 -0
- data/plugins/repositories/repositories_inspector.rb +41 -14
- data/plugins/repositories/repositories_model.rb +55 -12
- data/plugins/repositories/repositories_renderer.rb +23 -7
- data/plugins/repositories/schema/system-description-repositories.schema-v6.json +165 -0
- data/plugins/services/schema/system-description-services.schema-v6.json +93 -0
- data/plugins/services/services_inspector.rb +88 -22
- data/plugins/services/services_model.rb +9 -15
- data/plugins/services/services_renderer.rb +2 -2
- data/plugins/unmanaged_files/schema/system-description-unmanaged-files.schema-v6.json +162 -0
- data/plugins/unmanaged_files/unmanaged_files_inspector.rb +80 -30
- data/plugins/unmanaged_files/unmanaged_files_model.rb +22 -18
- data/plugins/unmanaged_files/unmanaged_files_renderer.rb +3 -3
- data/plugins/users/schema/system-description-users.schema-v6.json +86 -0
- data/schema/migrations/migrate5to6.rb +101 -0
- data/schema/system-description-global.schema-v6.json +43 -0
- metadata +24 -4
- data/html/assets/landing_page/landing_page.js +0 -10
@@ -24,28 +24,28 @@ class ServicesInspector < Inspector
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def inspect(_filter, _options = {})
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
27
|
+
services, init_system =
|
28
|
+
case
|
29
|
+
when @description.environment.system_type == "docker"
|
30
|
+
then [[], "none"]
|
31
|
+
when @system.has_command?("systemctl")
|
32
|
+
then [inspect_systemd_services, "systemd"]
|
33
|
+
when @system.has_command?("initctl") && @system.has_command?("chkconfig")
|
34
|
+
then [parse_redhat_chkconfig.map { |s| s["legacy_sysv"] = true; s }, "upstart"]
|
35
|
+
when @system.has_command?("initctl") && !@system.has_command?("chkconfig")
|
36
|
+
then [inspect_ubuntu_services, "upstart"]
|
37
|
+
else
|
38
|
+
[inspect_sysvinit_services, "sysvinit"]
|
39
|
+
end
|
40
|
+
|
41
|
+
@description.services = ServicesScope.new(
|
42
|
+
services,
|
43
|
+
init_system: init_system
|
44
|
+
)
|
45
45
|
end
|
46
46
|
|
47
47
|
def summary
|
48
|
-
"Found #{@description.services.
|
48
|
+
"Found #{@description.services.length} services."
|
49
49
|
end
|
50
50
|
|
51
51
|
private
|
@@ -68,7 +68,7 @@ class ServicesInspector < Inspector
|
|
68
68
|
Service.new(name: name, state: state)
|
69
69
|
end
|
70
70
|
|
71
|
-
|
71
|
+
services.sort_by(&:name)
|
72
72
|
end
|
73
73
|
|
74
74
|
def inspect_sysvinit_services
|
@@ -84,7 +84,73 @@ class ServicesInspector < Inspector
|
|
84
84
|
services = parse_suse_chkconfig
|
85
85
|
end
|
86
86
|
|
87
|
-
|
87
|
+
services.sort_by(&:name)
|
88
|
+
end
|
89
|
+
|
90
|
+
def inspect_ubuntu_services
|
91
|
+
# Ubuntu is managing its services using upstart but also has some
|
92
|
+
# services still not handled by that. Therefor we need to scan upstart
|
93
|
+
# and sysV to determine all services and their bootup state
|
94
|
+
services = parse_ubuntu_upstart
|
95
|
+
parse_ubuntu_sysv.each do |service|
|
96
|
+
services << service unless services.find { |s| s.name == service.name }
|
97
|
+
end
|
98
|
+
|
99
|
+
services.sort_by(&:name)
|
100
|
+
end
|
101
|
+
|
102
|
+
def parse_ubuntu_upstart
|
103
|
+
initctl_output = @system.run_command("/sbin/initctl", "show-config", "-e", stdout: :capture)
|
104
|
+
|
105
|
+
servicelist = initctl_output.lines.map(&:chomp).slice_before { |l| !l.start_with?(" ") }
|
106
|
+
enabled, disabled = servicelist.partition do |s|
|
107
|
+
s.find { |e| e.start_with?(" start on runlevel", " start on startup") }
|
108
|
+
end
|
109
|
+
|
110
|
+
services = enabled.map(&:first).each.map do |name|
|
111
|
+
Service.new(name: name, state: "enabled", legacy_sysv: false)
|
112
|
+
end
|
113
|
+
services + disabled.map(&:first).each.map do |name|
|
114
|
+
Service.new(name: name, state: "disabled", legacy_sysv: false)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def parse_ubuntu_sysv
|
119
|
+
# Get all sysV services
|
120
|
+
out, err = @system.run_command(
|
121
|
+
"/usr/sbin/service",
|
122
|
+
"--status-all",
|
123
|
+
stdout: :capture, stderr: :capture)
|
124
|
+
services_output = out + err
|
125
|
+
|
126
|
+
sysv_all = services_output.each_line.map { |line|
|
127
|
+
line.chomp.sub(/^.*\]../, "")
|
128
|
+
}
|
129
|
+
|
130
|
+
# Get all enabled sysV services - default in ubuntu1404 is runlevel 2
|
131
|
+
# and runlevels 3,4 and 5 are considered to be identical to 2.
|
132
|
+
runlevels = ["2", "S"]
|
133
|
+
find_output = runlevels.each.map do |runlevel|
|
134
|
+
@system.run_command(
|
135
|
+
"/usr/bin/find",
|
136
|
+
"/etc/rc#{runlevel}.d",
|
137
|
+
"-name",
|
138
|
+
"S\*",
|
139
|
+
stdout: :capture).split
|
140
|
+
end
|
141
|
+
|
142
|
+
sysv_enabled = find_output.flatten.map { |line|
|
143
|
+
line.chomp.sub(/^\/etc\/rc.\.d\/.../, "")
|
144
|
+
}.uniq
|
145
|
+
sysv_disabled = sysv_all - sysv_enabled
|
146
|
+
|
147
|
+
services = sysv_enabled.map.each do |name|
|
148
|
+
Service.new(name: name, state: "enabled", legacy_sysv: true)
|
149
|
+
end
|
150
|
+
|
151
|
+
services + sysv_disabled.map.each do |name|
|
152
|
+
Service.new(name: name, state: "disabled", legacy_sysv: true)
|
153
|
+
end
|
88
154
|
end
|
89
155
|
|
90
156
|
def parse_suse_chkconfig
|
@@ -97,7 +163,7 @@ class ServicesInspector < Inspector
|
|
97
163
|
:stdout => :capture
|
98
164
|
)
|
99
165
|
|
100
|
-
|
166
|
+
output.lines.map do |line|
|
101
167
|
name, state = line.split(/\s+/)
|
102
168
|
Service.new(name: name, state: state)
|
103
169
|
end
|
@@ -28,21 +28,19 @@ class Service < Machinery::Object
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
class
|
32
|
-
has_elements class: Service
|
33
|
-
end
|
34
|
-
|
35
|
-
class ServicesScope < Machinery::Object
|
31
|
+
class ServicesScope < Machinery::Array
|
36
32
|
include Machinery::Scope
|
37
|
-
|
33
|
+
|
34
|
+
has_attributes :init_system
|
35
|
+
has_elements class: Service
|
38
36
|
|
39
37
|
def compare_with(other)
|
40
38
|
if self.init_system != other.init_system
|
41
39
|
[self, other, nil, nil]
|
42
40
|
else
|
43
|
-
only_self = self
|
44
|
-
only_other = other
|
45
|
-
common = self
|
41
|
+
only_self = self - other
|
42
|
+
only_other = other - self
|
43
|
+
common = self & other
|
46
44
|
changed = Machinery::Scope.extract_changed_elements(only_self, only_other, :name)
|
47
45
|
changed = nil if changed.empty?
|
48
46
|
|
@@ -51,17 +49,13 @@ class ServicesScope < Machinery::Object
|
|
51
49
|
service_list_to_scope(only_other),
|
52
50
|
changed,
|
53
51
|
service_list_to_scope(common)
|
54
|
-
]
|
52
|
+
].map { |e| (e && !e.empty?) ? e : nil }
|
55
53
|
end
|
56
54
|
end
|
57
55
|
|
58
|
-
def length
|
59
|
-
services.try(:length) || 0
|
60
|
-
end
|
61
|
-
|
62
56
|
private
|
63
57
|
|
64
58
|
def service_list_to_scope(services)
|
65
|
-
self.class.new(init_system: init_system
|
59
|
+
self.class.new(services, init_system: init_system) unless services.elements.empty?
|
66
60
|
end
|
67
61
|
end
|
@@ -19,12 +19,12 @@ class ServicesRenderer < Renderer
|
|
19
19
|
def content(description)
|
20
20
|
return unless description["services"]
|
21
21
|
|
22
|
-
if description["services"].
|
22
|
+
if description["services"].elements.empty?
|
23
23
|
puts "There are no services."
|
24
24
|
end
|
25
25
|
|
26
26
|
list do
|
27
|
-
description["services"].
|
27
|
+
description["services"].each do |p|
|
28
28
|
item "#{p.name}: #{p.state}"
|
29
29
|
end
|
30
30
|
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
3
|
+
|
4
|
+
"type": "object",
|
5
|
+
"required": [
|
6
|
+
"_elements"
|
7
|
+
],
|
8
|
+
"properties": {
|
9
|
+
"_attributes": {
|
10
|
+
"type": "object",
|
11
|
+
"required": [
|
12
|
+
"extracted"
|
13
|
+
],
|
14
|
+
"properties": {
|
15
|
+
"extracted": {
|
16
|
+
"type": "boolean"
|
17
|
+
}
|
18
|
+
}
|
19
|
+
},
|
20
|
+
"_elements": {
|
21
|
+
"oneOf": [
|
22
|
+
{
|
23
|
+
"type": "array",
|
24
|
+
"maxItems": 0
|
25
|
+
},
|
26
|
+
{
|
27
|
+
"type": "array",
|
28
|
+
"minItems": 1,
|
29
|
+
"items": {
|
30
|
+
"anyOf": [
|
31
|
+
{
|
32
|
+
"$ref": "#/definitions/file_extracted"
|
33
|
+
},
|
34
|
+
{
|
35
|
+
"$ref": "#/definitions/file_remote_dir"
|
36
|
+
}
|
37
|
+
]
|
38
|
+
}
|
39
|
+
},
|
40
|
+
{
|
41
|
+
"type": "array",
|
42
|
+
"minItems": 1,
|
43
|
+
"items": {
|
44
|
+
"anyOf": [
|
45
|
+
{
|
46
|
+
"$ref": "#/definitions/file_not_extracted"
|
47
|
+
},
|
48
|
+
{
|
49
|
+
"$ref": "#/definitions/file_remote_dir"
|
50
|
+
}
|
51
|
+
]
|
52
|
+
}
|
53
|
+
}
|
54
|
+
]
|
55
|
+
}
|
56
|
+
},
|
57
|
+
"definitions": {
|
58
|
+
"file_common": {
|
59
|
+
"type": "object",
|
60
|
+
"required": ["name"],
|
61
|
+
"properties": {
|
62
|
+
"name": {
|
63
|
+
"type": "string"
|
64
|
+
}
|
65
|
+
}
|
66
|
+
},
|
67
|
+
"file_not_extracted": {
|
68
|
+
"allOf": [
|
69
|
+
{ "$ref": "#/definitions/file_common" },
|
70
|
+
{
|
71
|
+
"required": ["type"],
|
72
|
+
"properties": {
|
73
|
+
"type": {
|
74
|
+
"enum": ["file", "dir", "link", "remote_dir"]
|
75
|
+
}
|
76
|
+
},
|
77
|
+
"not": { "$ref": "#/definitions/file_extracted" }
|
78
|
+
}
|
79
|
+
]
|
80
|
+
},
|
81
|
+
"file_extracted": {
|
82
|
+
"allOf": [
|
83
|
+
{ "$ref": "#/definitions/file_common" },
|
84
|
+
{
|
85
|
+
"required": ["user", "group"],
|
86
|
+
"properties": {
|
87
|
+
"user": {
|
88
|
+
"type": "string",
|
89
|
+
"minLength": 1
|
90
|
+
},
|
91
|
+
"group": {
|
92
|
+
"type": "string",
|
93
|
+
"minLength": 1
|
94
|
+
}
|
95
|
+
},
|
96
|
+
"oneOf": [
|
97
|
+
{ "$ref": "#/definitions/file_extracted_file" },
|
98
|
+
{ "$ref": "#/definitions/file_extracted_dir" },
|
99
|
+
{ "$ref": "#/definitions/file_extracted_link" }
|
100
|
+
]
|
101
|
+
}
|
102
|
+
]
|
103
|
+
},
|
104
|
+
"file_extracted_file": {
|
105
|
+
"required": ["type", "size", "mode"],
|
106
|
+
"properties": {
|
107
|
+
"type": {
|
108
|
+
"enum": ["file"]
|
109
|
+
},
|
110
|
+
"size": {
|
111
|
+
"type": "integer",
|
112
|
+
"minimum": 0
|
113
|
+
},
|
114
|
+
"mode": {
|
115
|
+
"type": "string",
|
116
|
+
"pattern": "^[0-7]{3,4}$"
|
117
|
+
}
|
118
|
+
}
|
119
|
+
},
|
120
|
+
"file_extracted_dir": {
|
121
|
+
"required": ["type", "size", "mode", "files"],
|
122
|
+
"properties": {
|
123
|
+
"type": {
|
124
|
+
"enum": ["dir"]
|
125
|
+
},
|
126
|
+
"size": {
|
127
|
+
"type": "integer",
|
128
|
+
"minimum": 0
|
129
|
+
},
|
130
|
+
"mode": {
|
131
|
+
"type": "string",
|
132
|
+
"pattern": "^[0-4]?[0-7]{3}$"
|
133
|
+
},
|
134
|
+
"files": {
|
135
|
+
"type": "integer",
|
136
|
+
"minimum": 1
|
137
|
+
}
|
138
|
+
}
|
139
|
+
},
|
140
|
+
"file_extracted_link": {
|
141
|
+
"required": ["type"],
|
142
|
+
"properties": {
|
143
|
+
"type": {
|
144
|
+
"enum": ["link"]
|
145
|
+
}
|
146
|
+
}
|
147
|
+
},
|
148
|
+
"file_remote_dir": {
|
149
|
+
"allOf": [
|
150
|
+
{ "$ref": "#/definitions/file_common" },
|
151
|
+
{
|
152
|
+
"required": ["type"],
|
153
|
+
"properties": {
|
154
|
+
"type": {
|
155
|
+
"enum": ["remote_dir"]
|
156
|
+
}
|
157
|
+
}
|
158
|
+
}
|
159
|
+
]
|
160
|
+
}
|
161
|
+
}
|
162
|
+
}
|
@@ -20,7 +20,7 @@ class UnmanagedFilesInspector < Inspector
|
|
20
20
|
|
21
21
|
# checks if all required binaries are present
|
22
22
|
def check_requirements(check_tar)
|
23
|
-
@system.check_requirement("rpm", "--version")
|
23
|
+
@system.check_requirement(["rpm", "dpkg"], "--version")
|
24
24
|
@system.check_requirement("sed", "--version")
|
25
25
|
@system.check_requirement("cat", "--version")
|
26
26
|
@system.check_requirement("find", "--version")
|
@@ -34,6 +34,7 @@ class UnmanagedFilesInspector < Inspector
|
|
34
34
|
["sed", "s/^\\(.\\)[^/]* /\\1 /"],
|
35
35
|
:stdout => :capture
|
36
36
|
)
|
37
|
+
|
37
38
|
files = {}
|
38
39
|
dirh = {}
|
39
40
|
links = {}
|
@@ -52,13 +53,27 @@ class UnmanagedFilesInspector < Inspector
|
|
52
53
|
files[pair.first] = pair[1]
|
53
54
|
end
|
54
55
|
end
|
56
|
+
|
57
|
+
process_managed_files_and_dirs(files, dirh)
|
58
|
+
end
|
59
|
+
|
60
|
+
def extract_dpkg_database
|
61
|
+
out = @system.run_script_with_progress("dpkg_unmanaged_files.sh")
|
62
|
+
parsed_data = parse_dpkg_package_files_output(out)
|
63
|
+
files = parsed_data[:files]
|
64
|
+
dirh = parsed_data[:directories]
|
65
|
+
|
66
|
+
process_managed_files_and_dirs(files, dirh)
|
67
|
+
end
|
68
|
+
|
69
|
+
def process_managed_files_and_dirs(files, dirs)
|
55
70
|
# make sure that all parent directories of managed rpm directories are considered
|
56
71
|
# managed
|
57
|
-
|
72
|
+
dirs.dup.keys.each do |d|
|
58
73
|
dir = d.rpartition("/").first
|
59
74
|
|
60
|
-
while !
|
61
|
-
|
75
|
+
while !dirs.key?(dir) && dir.size > 1
|
76
|
+
dirs[dir] = false
|
62
77
|
dir = dir[0..dir.rindex("/") - 1]
|
63
78
|
end
|
64
79
|
end
|
@@ -68,18 +83,36 @@ class UnmanagedFilesInspector < Inspector
|
|
68
83
|
|
69
84
|
# make sure that dirs leading to a managed file are treated as if they were
|
70
85
|
# in rpm database, otherwise we cannot exclude whole unmanaged trees
|
71
|
-
while
|
72
|
-
|
86
|
+
while !dirs.key?(dir) && dir.size > 1
|
87
|
+
dirs[dir] = false
|
73
88
|
dir=dir[0..dir.rindex("/") - 1]
|
74
89
|
end
|
75
90
|
|
76
91
|
# put links to a managed directory also into directory hash
|
77
|
-
if !e.empty? &&
|
78
|
-
|
92
|
+
if !e.empty? && dirs.key?(e)
|
93
|
+
dirs[f] = false
|
79
94
|
end
|
80
95
|
end
|
81
|
-
|
82
|
-
[files,
|
96
|
+
|
97
|
+
[files, dirs]
|
98
|
+
end
|
99
|
+
|
100
|
+
def parse_dpkg_package_files_output(data)
|
101
|
+
result = { files: {}, directories: {} }
|
102
|
+
|
103
|
+
data.each_line do |line|
|
104
|
+
type, value = line.chomp.split(" ", 2)
|
105
|
+
|
106
|
+
if type == "-" # file
|
107
|
+
result[:files][value] = ""
|
108
|
+
elsif type == "d" && value != "/." # directory
|
109
|
+
result[:directories][value] = true
|
110
|
+
elsif type == "l" # link
|
111
|
+
pair = value.split(" -> ", 2)
|
112
|
+
result[:files][pair[0]] = pair[1]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
result
|
83
116
|
end
|
84
117
|
|
85
118
|
def check_consistency(files, dirh)
|
@@ -219,6 +252,8 @@ class UnmanagedFilesInspector < Inspector
|
|
219
252
|
do_extract = options && options[:extract_unmanaged_files]
|
220
253
|
check_requirements(do_extract)
|
221
254
|
|
255
|
+
determine_package_manager
|
256
|
+
|
222
257
|
scope = UnmanagedFilesScope.new
|
223
258
|
|
224
259
|
file_store_tmp = @description.scope_file_store("unmanaged_files.tmp")
|
@@ -226,8 +261,8 @@ class UnmanagedFilesInspector < Inspector
|
|
226
261
|
|
227
262
|
scope.scope_file_store = file_store_tmp
|
228
263
|
|
229
|
-
file_filter = filter.element_filter_for("/unmanaged_files/
|
230
|
-
file_filter ||= ElementFilter.new("/unmanaged_files/
|
264
|
+
file_filter = filter.element_filter_for("/unmanaged_files/name").dup if filter
|
265
|
+
file_filter ||= ElementFilter.new("/unmanaged_files/name")
|
231
266
|
file_filter.add_matchers("=", @description.store.base_path)
|
232
267
|
|
233
268
|
# Add a recursive pendant to each ignored element
|
@@ -244,6 +279,14 @@ class UnmanagedFilesInspector < Inspector
|
|
244
279
|
end
|
245
280
|
end
|
246
281
|
|
282
|
+
def determine_package_manager
|
283
|
+
if @system.has_command?("rpm")
|
284
|
+
@package_manager = "rpm"
|
285
|
+
elsif @system.has_command?("dpkg")
|
286
|
+
@package_manager = "dpkg"
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
247
290
|
def helper_usable?(helper)
|
248
291
|
if !helper.can_help?
|
249
292
|
Machinery::Ui.puts(
|
@@ -254,7 +297,7 @@ class UnmanagedFilesInspector < Inspector
|
|
254
297
|
Machinery::Ui.puts(
|
255
298
|
"Note: Using traditional inspection because only 'root' is supported as remote user."
|
256
299
|
)
|
257
|
-
|
300
|
+
elsif ["rpm", "dpkg"].include?(@package_manager)
|
258
301
|
return true
|
259
302
|
end
|
260
303
|
|
@@ -272,8 +315,7 @@ class UnmanagedFilesInspector < Inspector
|
|
272
315
|
end
|
273
316
|
|
274
317
|
helper.run_helper(scope)
|
275
|
-
|
276
|
-
scope.files.delete_if { |f| filter.matches?(f.name) }
|
318
|
+
scope.delete_if { |f| filter.matches?(f.name) }
|
277
319
|
|
278
320
|
if do_extract
|
279
321
|
mount_points = MountPoints.new(@system)
|
@@ -282,16 +324,16 @@ class UnmanagedFilesInspector < Inspector
|
|
282
324
|
file_store_tmp.remove
|
283
325
|
file_store_tmp.create
|
284
326
|
|
285
|
-
files = scope.
|
327
|
+
files = scope.select { |f| f.file? || f.link? }.map(&:name)
|
286
328
|
scope.retrieve_files_from_system_as_archive(@system, files, [])
|
287
329
|
show_extraction_progress(files.count)
|
288
330
|
|
289
331
|
scope.retrieve_trees_from_system_as_archive(@system,
|
290
|
-
scope.
|
332
|
+
scope.select(&:directory?).map(&:name), excluded_trees) do |count|
|
291
333
|
show_extraction_progress(files.count + count)
|
292
334
|
end
|
293
335
|
|
294
|
-
scope
|
336
|
+
scope = extract_tar_metadata(scope, file_store_tmp.path)
|
295
337
|
file_store_final.remove
|
296
338
|
file_store_tmp.rename(file_store_final.store_name)
|
297
339
|
scope.scope_file_store = file_store_final
|
@@ -310,7 +352,11 @@ class UnmanagedFilesInspector < Inspector
|
|
310
352
|
def run_inspection(file_filter, options, do_extract, file_store_tmp, file_store_final, scope)
|
311
353
|
mount_points = MountPoints.new(@system)
|
312
354
|
|
313
|
-
|
355
|
+
if @package_manager == "rpm"
|
356
|
+
inspected_files, inspected_dirs = extract_rpm_database
|
357
|
+
elsif @package_manager == "dpkg"
|
358
|
+
inspected_files, inspected_dirs = extract_dpkg_database
|
359
|
+
end
|
314
360
|
|
315
361
|
# Btrfs subvolumes and local mounts need to be inspected separately because
|
316
362
|
# they are not part of the `get_find_data` return data
|
@@ -359,7 +405,8 @@ class UnmanagedFilesInspector < Inspector
|
|
359
405
|
if !local_filesystems.empty?
|
360
406
|
# force all mount points to be non-leave directories (find is called with -xdev)
|
361
407
|
local_filesystems.each do |mp|
|
362
|
-
|
408
|
+
path = mp.sub(/^\//, "")
|
409
|
+
dirs[path] = true if dirs.key?(path)
|
363
410
|
end
|
364
411
|
local_filesystems.reject! { |mp| dirs.has_key?(mp) }
|
365
412
|
end
|
@@ -372,7 +419,7 @@ class UnmanagedFilesInspector < Inspector
|
|
372
419
|
file_filter.matches?("/" + dir)
|
373
420
|
end
|
374
421
|
end
|
375
|
-
managed, unmanaged = dirs.keys.partition{ |d|
|
422
|
+
managed, unmanaged = dirs.keys.partition { |d| inspected_dirs.key?(find_dir + d) }
|
376
423
|
|
377
424
|
# unmanaged dirs lead to removal of files and dirs below that dir
|
378
425
|
while !unmanaged.empty?
|
@@ -408,7 +455,7 @@ class UnmanagedFilesInspector < Inspector
|
|
408
455
|
dirs_todo.push(*managed)
|
409
456
|
|
410
457
|
# unmanaged files are simply stored
|
411
|
-
managed, unmanaged = files.keys.partition{ |d|
|
458
|
+
managed, unmanaged = files.keys.partition { |d| inspected_files.key?(find_dir + d) }
|
412
459
|
links = unmanaged.reject { |d| files[d].empty? }
|
413
460
|
unmanaged.map!{ |d| find_dir + d }
|
414
461
|
unmanaged_files.push(*unmanaged)
|
@@ -426,8 +473,7 @@ class UnmanagedFilesInspector < Inspector
|
|
426
473
|
excluded_files, remote_dirs, do_extract, file_store_tmp, file_store_final, scope)
|
427
474
|
|
428
475
|
scope.extracted = !!do_extract
|
429
|
-
scope
|
430
|
-
|
476
|
+
scope += processed_files.sort_by(&:name)
|
431
477
|
@description["unmanaged_files"] = scope
|
432
478
|
end
|
433
479
|
|
@@ -477,7 +523,7 @@ class UnmanagedFilesInspector < Inspector
|
|
477
523
|
|
478
524
|
def summary
|
479
525
|
"#{@description.unmanaged_files.extracted ? "Extracted" : "Found"} " +
|
480
|
-
"#{@description.unmanaged_files.
|
526
|
+
"#{@description.unmanaged_files.count} unmanaged files and trees."
|
481
527
|
end
|
482
528
|
|
483
529
|
private
|
@@ -490,10 +536,14 @@ class UnmanagedFilesInspector < Inspector
|
|
490
536
|
end
|
491
537
|
|
492
538
|
def btrfs_subvolumes
|
493
|
-
@system.
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
539
|
+
if @system.has_command?("/sbin/btrfs")
|
540
|
+
@system.run_command(
|
541
|
+
["/sbin/btrfs", "subvolume", "list", "/"],
|
542
|
+
["awk", "{print $NF}"],
|
543
|
+
stdout: :capture
|
544
|
+
).split
|
545
|
+
else
|
546
|
+
[]
|
547
|
+
end
|
498
548
|
end
|
499
549
|
end
|