@@ -60,36 +60,69 @@ type packageFilesRef struct {
60
60
// Validate runs the check of whether any Red Hat files were modified
61
61
func (p * HasModifiedFilesCheck ) Validate (ctx context.Context , imgRef image.ImageReference ) (bool , error ) {
62
62
fs := afero .NewOsFs ()
63
- layerIDs , packageFiles , packageDist , err := p .gatherDataToValidate (ctx , imgRef , fs )
63
+ layerIDs , packageFiles , err := p .gatherDataToValidate (ctx , imgRef , fs )
64
+ if err != nil {
65
+ return false , fmt .Errorf ("could not generate modified files list: %v" , err )
66
+ }
67
+
68
+ packageDist , err := p .parsePackageDist (ctx , imgRef .ImageFSPath , fs )
64
69
if err != nil {
65
70
return false , fmt .Errorf ("could not generate modified files list: %v" , err )
66
71
}
67
72
68
73
return p .validate (ctx , layerIDs , packageFiles , packageDist )
69
74
}
70
75
76
+ // parsePackageDist returns the platform's distribution value from the
77
+ // os-release contents in the extracted image.
78
+ func (p * HasModifiedFilesCheck ) parsePackageDist (_ context.Context , extractedImageFSPath string , fs afero.Fs ) (string , error ) {
79
+ osRelease , err := fs .Open (filepath .Join (extractedImageFSPath , "etc" , "os-release" ))
80
+ if err != nil {
81
+ return "" , fmt .Errorf ("could not open os-release: %v" , err )
82
+ }
83
+ defer osRelease .Close ()
84
+ scanner := bufio .NewScanner (osRelease )
85
+ packageDist := "unknown"
86
+ for scanner .Scan () {
87
+ line := scanner .Text ()
88
+ r , _ := regexp .Compile (`PLATFORM_ID="platform:([[:alnum:]]+)"` )
89
+ m := r .FindStringSubmatch (line )
90
+ if m == nil {
91
+ continue
92
+ }
93
+ packageDist = m [1 ]
94
+ break
95
+ }
96
+
97
+ if err := scanner .Err (); err != nil {
98
+ return "" , fmt .Errorf ("error while scanning for package dist: %v" , err )
99
+ }
100
+
101
+ return packageDist , nil
102
+ }
103
+
71
104
// gatherDataToValidate returns a map from layer digest to a struct containing the list of files
72
105
// (packageFilesRef.LayerPackageFiles) installed via packages (packageFilesRef.LayerPackages)
73
106
// from the container image, and the list of files (packageFilesRef.LayerFiles) modified/added
74
107
// via layers in the image.
75
- func (p * HasModifiedFilesCheck ) gatherDataToValidate (ctx context.Context , imgRef image.ImageReference , fs afero.Fs ) ([]string , map [string ]packageFilesRef , string , error ) {
108
+ func (p * HasModifiedFilesCheck ) gatherDataToValidate (ctx context.Context , imgRef image.ImageReference , fs afero.Fs ) ([]string , map [string ]packageFilesRef , error ) {
76
109
logger := logr .FromContextOrDiscard (ctx )
77
110
78
111
layerDir , err := afero .TempDir (fs , "" , "rpm-layers-" )
79
112
if err != nil {
80
- return nil , nil , "" , err
113
+ return nil , nil , err
81
114
}
82
115
defer func () {
83
116
_ = fs .RemoveAll (layerDir )
84
117
}()
85
118
86
119
if imgRef .ImageInfo == nil {
87
- return nil , nil , "" , fmt .Errorf ("image reference invalid" )
120
+ return nil , nil , fmt .Errorf ("image reference invalid" )
88
121
}
89
122
90
123
layers , err := imgRef .ImageInfo .Layers ()
91
124
if err != nil {
92
- return nil , nil , "" , err
125
+ return nil , nil , err
93
126
}
94
127
95
128
layerIDs := make ([]string , 0 , len (layers ))
@@ -102,21 +135,36 @@ func (p *HasModifiedFilesCheck) gatherDataToValidate(ctx context.Context, imgRef
102
135
for idx , layer := range layers {
103
136
layerIDHash , err := layer .Digest ()
104
137
if err != nil {
105
- return nil , nil , "" , fmt .Errorf ("unable to retrieve diff id for layer: %w" , err )
138
+ return nil , nil , fmt .Errorf ("unable to retrieve diff id for layer: %w" , err )
139
+ }
140
+
141
+ // Capture the diff ID to aid in debugging. We don't technically care if
142
+ // there's an error returned here because we don't use the layerDiffID
143
+ // value for anything meaningful.
144
+ layerDiffID := "unknown"
145
+ layerDiffHash , err := layer .DiffID ()
146
+ if err == nil && layerDiffHash .String () != "" {
147
+ layerDiffID = layerDiffHash .String ()
106
148
}
107
- layerID := layerIDHash .String ()
108
149
109
- layerDir := filepath .Join (layerDir , fmt .Sprintf ("%02d-%s" , idx , layerID ))
150
+ rawLayerID := layerIDHash .String ()
151
+ // Map everything using a combination of the layer index and the layer
152
+ // ID to avoid problems when images have multiple scattered layers with
153
+ // the same ID.
154
+ layerID := fmt .Sprintf ("%02d-%s" , idx , rawLayerID )
155
+ logger .V (log .TRC ).Info ("generating unique layer ID" , "uniqueLayerID" , layerID , "layerID" , rawLayerID , "layerDiffID" , layerDiffID )
156
+
157
+ layerDir := filepath .Join (layerDir , layerID )
110
158
err = fs .Mkdir (layerDir , 0o755 )
111
159
if err != nil {
112
- return nil , nil , "" , fmt .Errorf ("could not create layer directory: %w" , err )
160
+ return nil , nil , fmt .Errorf ("could not create layer directory: %w" , err )
113
161
}
114
162
115
163
layerIDs = append (layerIDs , layerID )
116
164
117
165
files , err := generateChangesFor (ctx , layer )
118
166
if err != nil {
119
- return nil , nil , "" , err
167
+ return nil , nil , err
120
168
}
121
169
122
170
found , pkgList := findRPMDB (ctx , layer )
@@ -142,7 +190,7 @@ func (p *HasModifiedFilesCheck) gatherDataToValidate(ctx context.Context, imgRef
142
190
143
191
packageFiles , err := installedFileMapWithExclusions (ctx , pkgList )
144
192
if err != nil {
145
- return nil , nil , "" , err
193
+ return nil , nil , err
146
194
}
147
195
148
196
layerRefs [layerID ] = packageFilesRef {
@@ -153,29 +201,7 @@ func (p *HasModifiedFilesCheck) gatherDataToValidate(ctx context.Context, imgRef
153
201
}
154
202
}
155
203
156
- osRelease , err := fs .Open (filepath .Join (imgRef .ImageFSPath , "etc" , "os-release" ))
157
- if err != nil {
158
- return nil , nil , "" , fmt .Errorf ("could not open os-release: %v" , err )
159
- }
160
- defer osRelease .Close ()
161
- scanner := bufio .NewScanner (osRelease )
162
- packageDist := "unknown"
163
- for scanner .Scan () {
164
- line := scanner .Text ()
165
- r , _ := regexp .Compile (`PLATFORM_ID="platform:([[:alnum:]]+)"` )
166
- m := r .FindStringSubmatch (line )
167
- if m == nil {
168
- continue
169
- }
170
- packageDist = m [1 ]
171
- break
172
- }
173
-
174
- if err := scanner .Err (); err != nil {
175
- return nil , nil , "" , fmt .Errorf ("error while scanning for package dist: %v" , err )
176
- }
177
-
178
- return layerIDs , layerRefs , packageDist , nil
204
+ return layerIDs , layerRefs , nil
179
205
}
180
206
181
207
// validate compares the list of LayerFiles and PackageFiles to see what PackageFiles
0 commit comments