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,22 @@
|
|
|
1
|
+
# README for Kiwi export from Machinery
|
|
2
|
+
|
|
3
|
+
This directory contains a Kiwi configuration that was exported by
|
|
4
|
+
Machinery.
|
|
5
|
+
|
|
6
|
+
The user is expected to be familiar with using Kiwi, otherwise
|
|
7
|
+
`machinery build` is recommended.
|
|
8
|
+
Details on Kiwi can be found at http://opensuse.github.com/kiwi
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## Creating the image
|
|
12
|
+
|
|
13
|
+
The following command builds the image:
|
|
14
|
+
|
|
15
|
+
`sudo /usr/sbin/kiwi --build EXPORTED_DIRECTORY --destdir OUTPUT_DIRECTORY`
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
For example if the exported kiwi description is stored under "/tmp/export"
|
|
19
|
+
and the image should be saved under "/tmp/image" the command would look like
|
|
20
|
+
this:
|
|
21
|
+
|
|
22
|
+
`sudo /usr/sbin/kiwi --build /tmp/export --destdir /tmp/image`
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/usr/bin/env perl
|
|
2
|
+
|
|
3
|
+
# Copyright (c) 2013-2014 SUSE LLC
|
|
4
|
+
#
|
|
5
|
+
# This program is free software; you can redistribute it and/or
|
|
6
|
+
# modify it under the terms of version 3 of the GNU General Public License as
|
|
7
|
+
# published by the Free Software Foundation.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program; if not, contact SUSE LLC.
|
|
16
|
+
#
|
|
17
|
+
# To contact SUSE about this file by physical or electronic mail,
|
|
18
|
+
# you may find current contact information at www.suse.com
|
|
19
|
+
|
|
20
|
+
use strict;
|
|
21
|
+
use warnings;
|
|
22
|
+
use FileHandle;
|
|
23
|
+
|
|
24
|
+
my $local_passwd_path = shift;
|
|
25
|
+
my $local_shadow_path = shift;
|
|
26
|
+
my $local_group_path = shift;
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
my $fh = FileHandle->new;
|
|
30
|
+
my @existing_passwd_entries = [];
|
|
31
|
+
if($fh->open("< $local_passwd_path")) {
|
|
32
|
+
@existing_passwd_entries = <$fh>;
|
|
33
|
+
$fh->close;
|
|
34
|
+
}
|
|
35
|
+
my @existing_shadow_entries = [];
|
|
36
|
+
if($fh->open("< $local_shadow_path")) {
|
|
37
|
+
@existing_shadow_entries = <$fh>;
|
|
38
|
+
$fh->close;
|
|
39
|
+
}
|
|
40
|
+
my @existing_group_entries = [];
|
|
41
|
+
if($fh->open("< $local_group_path")) {
|
|
42
|
+
@existing_group_entries = <$fh>;
|
|
43
|
+
$fh->close;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# This array contains arrays of the new passwd and shadow entries, e.g.
|
|
47
|
+
# (
|
|
48
|
+
# ["svn:x:482:476:user for Apache Subversion svnserve:/srv/svn:/sbin/nologin", "svn:!:16058::::::"],
|
|
49
|
+
# ["nscd:x:484:478:User for nscd:/var/run/nscd:/sbin/nologin", "nscd:!:16058::::::"]
|
|
50
|
+
# )
|
|
51
|
+
my @new_passwd_entries = (
|
|
52
|
+
<%= passwd_entries %>
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
# This array contains the new group entries, e.g.:
|
|
56
|
+
# (
|
|
57
|
+
# "ntp:x:102:",
|
|
58
|
+
# "at:x:103:"
|
|
59
|
+
# )
|
|
60
|
+
my @new_group_entries = (
|
|
61
|
+
<%= group_entries %>
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
# Takes a passwd entry as the argument and replaces the uid with an id that is
|
|
65
|
+
# not already used in the existing passwd file
|
|
66
|
+
sub fix_ids {
|
|
67
|
+
my $passwd_entry = shift;
|
|
68
|
+
my @fields = split(/:/x, $passwd_entry);
|
|
69
|
+
my $uid = $fields[2];
|
|
70
|
+
my $gid = $fields[3];
|
|
71
|
+
|
|
72
|
+
while(grep { /^[^:]*:[^:]*:$uid:/x } @existing_passwd_entries) {
|
|
73
|
+
$uid = $uid + 1;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
$passwd_entry =~ s/^([^:]*:[^:]*):\d+:/$1:$uid:/x;
|
|
77
|
+
|
|
78
|
+
return $passwd_entry;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# Takes a group entry as the argument and replaces the uid with an id that is
|
|
82
|
+
# not already used in the existing group file
|
|
83
|
+
sub fix_group_id {
|
|
84
|
+
my $group = shift;
|
|
85
|
+
my @fields = split(/:/x, $group);
|
|
86
|
+
my $original_gid = $fields[2];
|
|
87
|
+
my $gid = $original_gid;
|
|
88
|
+
|
|
89
|
+
while(grep { /^[^:]*:[^:]*:$gid:/x } @existing_group_entries) {
|
|
90
|
+
$gid = $gid + 1;
|
|
91
|
+
}
|
|
92
|
+
$group =~ s/^([^:]*:[^:]*):$original_gid:/$1:$gid:/x;
|
|
93
|
+
|
|
94
|
+
# Also update the gid in the list of new passwd entries
|
|
95
|
+
foreach my $entry_ref (@new_passwd_entries) {
|
|
96
|
+
$entry_ref->[0] =~ s/^([^:]*:[^:]*:[^:]*):$original_gid:/$1:$gid:/x;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return $group;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# Takes two comma-separated lists and merges them. Duplicates are removed.
|
|
103
|
+
sub merge_group_users {
|
|
104
|
+
my $a = $_[0] // "";
|
|
105
|
+
my $b = $_[1] // "";
|
|
106
|
+
chomp($a);
|
|
107
|
+
chomp($b);
|
|
108
|
+
my @users = (split(",", $a), split(",", $b));
|
|
109
|
+
|
|
110
|
+
#remove duplicate entries
|
|
111
|
+
my %hash = ();
|
|
112
|
+
foreach my $item (@users) {
|
|
113
|
+
$hash{$item} = '';
|
|
114
|
+
}
|
|
115
|
+
@users = sort keys %hash;
|
|
116
|
+
|
|
117
|
+
return join(",", @users);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# Iterate over the new group entries and fix ids where necessary.
|
|
121
|
+
#
|
|
122
|
+
# If the group already exists on the system the group is not added again, but the
|
|
123
|
+
# new passwd entries that reference this group are adjusted to the other gid.
|
|
124
|
+
#
|
|
125
|
+
# If the group does not exist yet, the group is appended to /etc/group. If
|
|
126
|
+
# necessary, the gid will be adjusted to not conflict with the existing ones.
|
|
127
|
+
my %gid_changes = ();
|
|
128
|
+
foreach my $entry (@new_group_entries) {
|
|
129
|
+
my @fields = split(/:/x, $entry);
|
|
130
|
+
my $id = $fields[0];
|
|
131
|
+
my $gid = $fields[2];
|
|
132
|
+
|
|
133
|
+
my @match = grep { /^$id:.*/x } @existing_group_entries;
|
|
134
|
+
if(scalar @match > 0) {
|
|
135
|
+
print "Group match: $match[0]\n";
|
|
136
|
+
|
|
137
|
+
my @original_fields = split(/:/x, $match[0]);
|
|
138
|
+
my $original_gid = $original_fields[2];
|
|
139
|
+
|
|
140
|
+
# Store all gid transformations in the %gid_changes hash
|
|
141
|
+
$gid_changes{$gid} = $original_gid;
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# Update existing entry with the new attributes
|
|
145
|
+
$fields[2] = $original_gid;
|
|
146
|
+
my $users = merge_group_users($original_fields[3], $fields[3]);
|
|
147
|
+
$entry =~ s/^([^:]*:[^:]*):.*/$1:$original_gid:$users/x;
|
|
148
|
+
foreach my $group_ref (@existing_group_entries) {
|
|
149
|
+
$group_ref =~ s/\Q$match[0]\E/$entry/x;
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
print "No match for group ", $id, " (", $entry,")\n";
|
|
153
|
+
|
|
154
|
+
my $fixed_entry = fix_group_id($entry);
|
|
155
|
+
print " -> Writing: ", $fixed_entry, "\n";
|
|
156
|
+
|
|
157
|
+
push(@existing_group_entries, $fixed_entry);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
# Apply all gid transformations to the list of new passwd entries
|
|
162
|
+
foreach my $entry_ref (@new_passwd_entries) {
|
|
163
|
+
my @fields = split(/:/x, $entry_ref->[0]);
|
|
164
|
+
my $gid = $fields[3];
|
|
165
|
+
|
|
166
|
+
if($gid_changes{$gid}) {
|
|
167
|
+
$entry_ref->[0] =~ s/^([^:]*:[^:]*:[^:]*):$gid:/$1:$gid_changes{$gid}:/x;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
# Iterate over the new passwd and shadow entries and fix ids where necessary.
|
|
172
|
+
#
|
|
173
|
+
# If the user already exists on the system the existing uid/gid is reused.
|
|
174
|
+
#
|
|
175
|
+
# If the user does not exist yet it is appended to /etc/passwd and /etc/shadow
|
|
176
|
+
# with a uid that does not conflict.
|
|
177
|
+
foreach my $entry (@new_passwd_entries) {
|
|
178
|
+
my @fields = split(/:/x, @$entry[0]);
|
|
179
|
+
my $id = $fields[0];
|
|
180
|
+
|
|
181
|
+
my @match = grep { /^$id:.*/x } @existing_passwd_entries;
|
|
182
|
+
if(scalar @match > 0) {
|
|
183
|
+
my @original_fields = split(/:/x, $match[0]);
|
|
184
|
+
my $uid = $original_fields[2];
|
|
185
|
+
|
|
186
|
+
$fields[2] = $uid;
|
|
187
|
+
my $new_entry = join(":", @fields);
|
|
188
|
+
|
|
189
|
+
foreach my $passwd_ref (@existing_passwd_entries) {
|
|
190
|
+
$passwd_ref =~ s/\Q$match[0]\E/$new_entry/x;
|
|
191
|
+
}
|
|
192
|
+
if(@$entry[1]) {
|
|
193
|
+
foreach my $shadow_ref (@existing_shadow_entries) {
|
|
194
|
+
$shadow_ref =~ s/^$id.*/@$entry[1]/x;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
print "No match for user $id (@$entry[0])\n";
|
|
199
|
+
|
|
200
|
+
my $fixed_entry = fix_ids(@$entry[0]);
|
|
201
|
+
print " ->Writing: ", $fixed_entry, "\n";
|
|
202
|
+
|
|
203
|
+
push(@existing_passwd_entries, $fixed_entry);
|
|
204
|
+
if(@$entry[1]) {
|
|
205
|
+
push(@existing_shadow_entries, @$entry[1]);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
# Write final lists to files
|
|
211
|
+
if($fh->open("> $local_passwd_path")) {
|
|
212
|
+
foreach(@existing_passwd_entries) {
|
|
213
|
+
chomp;
|
|
214
|
+
$fh->print("$_\n");
|
|
215
|
+
}
|
|
216
|
+
$fh->close;
|
|
217
|
+
}
|
|
218
|
+
if($fh->open("> $local_shadow_path")) {
|
|
219
|
+
foreach(@existing_shadow_entries) {
|
|
220
|
+
chomp;
|
|
221
|
+
$fh->print("$_\n");
|
|
222
|
+
}
|
|
223
|
+
$fh->close;
|
|
224
|
+
}
|
|
225
|
+
if($fh->open("> $local_group_path")) {
|
|
226
|
+
foreach(@existing_group_entries) {
|
|
227
|
+
chomp;
|
|
228
|
+
$fh->print("$_\n");
|
|
229
|
+
}
|
|
230
|
+
$fh->close;
|
|
231
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
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 AnalyzeConfigFileDiffsTask
|
|
19
|
+
def analyze(description)
|
|
20
|
+
description.assert_scopes("repositories", "config_files")
|
|
21
|
+
if !description.scope_extracted?("config_files")
|
|
22
|
+
raise Machinery::Errors::MissingExtractedFiles.new(description, ["config_files"])
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
with_repositories(description) do |zypper|
|
|
26
|
+
description.initialize_file_store("config-file-diffs")
|
|
27
|
+
diffs_path = description.file_store("config-file-diffs")
|
|
28
|
+
extracted_files_path = description.file_store("config_files")
|
|
29
|
+
|
|
30
|
+
Machinery::Ui.puts "Generating diffs..."
|
|
31
|
+
cnt = 1
|
|
32
|
+
list = files_by_package(description)
|
|
33
|
+
total = list.map(&:files).flatten.length.to_s
|
|
34
|
+
list.each do |package|
|
|
35
|
+
path = zypper.download_package("#{package.name}-#{package.version}")
|
|
36
|
+
|
|
37
|
+
if !path || path.empty?
|
|
38
|
+
Machinery::Ui.warn "Warning: Could not download package #{package.name}-#{package.version}."
|
|
39
|
+
cnt += package.files.length
|
|
40
|
+
next
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
package.files.each do |file|
|
|
44
|
+
diff = Rpm.new(path).diff(file, File.join(extracted_files_path, file))
|
|
45
|
+
|
|
46
|
+
if !diff || diff.empty?
|
|
47
|
+
Machinery::Ui.warn "Warning: Could not generate diff for #{file}."
|
|
48
|
+
else
|
|
49
|
+
diff_path = File.join(diffs_path, file + ".diff")
|
|
50
|
+
FileUtils.mkdir_p(File.dirname(diff_path))
|
|
51
|
+
File.write(diff_path, diff)
|
|
52
|
+
Machinery::Ui.puts "[#{cnt.to_s.rjust(total.length)}/#{total}] #{file}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
cnt += 1
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
Machinery::Ui.puts "done"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
# Creates an array of hashes with the RPM names, version and the list of
|
|
65
|
+
# changed file paths, e.g.
|
|
66
|
+
#
|
|
67
|
+
# [
|
|
68
|
+
# {
|
|
69
|
+
# "name" => "aaa_base",
|
|
70
|
+
# "version" => "3.11.1",
|
|
71
|
+
# "files" => ["/etc/modprobe.d/unsupported-modules", "/etc/inittab"]
|
|
72
|
+
# }
|
|
73
|
+
# ]
|
|
74
|
+
def files_by_package(description)
|
|
75
|
+
files = description["config_files"].files.
|
|
76
|
+
select { |f| f.changes.include?("md5") }
|
|
77
|
+
|
|
78
|
+
files.inject({}) do |result, file|
|
|
79
|
+
key = "#{file.package_name}-#{file.package_version}"
|
|
80
|
+
result[key] ||= Package.new(
|
|
81
|
+
"name" => file["package_name"],
|
|
82
|
+
"version" => file["package_version"],
|
|
83
|
+
"files" => []
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
result[key]["files"] << file.name
|
|
87
|
+
result
|
|
88
|
+
end.values
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def with_repositories(description, &block)
|
|
92
|
+
Machinery::Ui.puts "Setting up repository access..."
|
|
93
|
+
Zypper.isolated do |zypper|
|
|
94
|
+
begin
|
|
95
|
+
remote_repos = description.repositories.reject do |repo|
|
|
96
|
+
repo.url.start_with?("cd://") || repo.url.start_with?("dvd://")
|
|
97
|
+
end
|
|
98
|
+
remote_repos.each do |repo|
|
|
99
|
+
uri = URI.parse(repo.url)
|
|
100
|
+
|
|
101
|
+
if repo.username && repo.password
|
|
102
|
+
uri.user = repo.username
|
|
103
|
+
uri.password = repo.password
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
zypper.add_repo(uri.to_s, repo.alias)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
begin
|
|
110
|
+
zypper.refresh
|
|
111
|
+
rescue Cheetah::ExecutionFailed => e
|
|
112
|
+
# If zypper is locked (exit code 7) we're doomed. Bail out completeley.
|
|
113
|
+
raise if e.status.exitstatus == 7
|
|
114
|
+
|
|
115
|
+
# Refreshing repositories might fail for various other reasons, but we
|
|
116
|
+
# still stick to the plan because the relevant config files might be
|
|
117
|
+
# available from the other repositories.
|
|
118
|
+
# If they aren't an error message will then be generated for each of
|
|
119
|
+
# the actually missing files instead.
|
|
120
|
+
Machinery.logger.error(e.message)
|
|
121
|
+
Machinery.logger.debug(e.backtrace.join("\n"))
|
|
122
|
+
Machinery.logger.debug("Standard output:\n #{e.stdout}")
|
|
123
|
+
Machinery.logger.debug("Error output:\n #{e.stderr}")
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
block.call(zypper)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
data/lib/array.rb
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
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
|
+
class Array
|
|
20
|
+
class << self
|
|
21
|
+
def has_elements(options)
|
|
22
|
+
@element_class = options[:class]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def from_json(json)
|
|
26
|
+
elements = json.map do |element|
|
|
27
|
+
if @element_class
|
|
28
|
+
@element_class.from_json(element)
|
|
29
|
+
else
|
|
30
|
+
case element
|
|
31
|
+
when ::Array
|
|
32
|
+
Machinery::Array.from_json(element)
|
|
33
|
+
when Hash
|
|
34
|
+
Machinery::Object.from_json(element)
|
|
35
|
+
else
|
|
36
|
+
element
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
new(elements)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
attr_reader :elements
|
|
46
|
+
|
|
47
|
+
def initialize(elements = [])
|
|
48
|
+
@elements = elements
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def ==(other)
|
|
52
|
+
self.class == other.class && @elements == other.elements
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Various Array operators such as "-" and "&" use #eql? and #hash to compare
|
|
56
|
+
# array elements, which is why we need to make sure they work properly.
|
|
57
|
+
|
|
58
|
+
alias eql? ==
|
|
59
|
+
|
|
60
|
+
def hash
|
|
61
|
+
@elements.hash
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def -(other)
|
|
65
|
+
self.class.new(@elements - other.elements)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def &(other)
|
|
69
|
+
self.class.new(@elements & other.elements)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def as_json
|
|
73
|
+
@elements.map do |element|
|
|
74
|
+
if element.is_a?(Machinery::Array) || element.is_a?(Machinery::Object)
|
|
75
|
+
element.as_json
|
|
76
|
+
else
|
|
77
|
+
element
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def compare_with(other)
|
|
83
|
+
[
|
|
84
|
+
self - other,
|
|
85
|
+
other - self,
|
|
86
|
+
self & other
|
|
87
|
+
].map { |e| !e.empty? ? e : nil }
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def method_missing(name, *args, &block)
|
|
91
|
+
@elements.send(name, *args, &block)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def respond_to?(name, include_all = false)
|
|
95
|
+
super || @elements.respond_to?(name, include_all)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|