@@ -15,6 +15,7 @@ import (
15
15
"github.com/quay/zlog"
16
16
17
17
"github.com/quay/claircore"
18
+ "github.com/quay/claircore/datastore"
18
19
"github.com/quay/claircore/libvuln/driver"
19
20
"github.com/quay/claircore/pkg/microbatch"
20
21
)
@@ -45,14 +46,27 @@ var (
45
46
)
46
47
)
47
48
49
+ // UpdateVulnerabilitiesIter implements vulnstore.Updater.
50
+ func (s * MatcherStore ) UpdateVulnerabilitiesIter (ctx context.Context , updater string , fp driver.Fingerprint , it datastore.VulnerabilityIter ) (uuid.UUID , error ) {
51
+ ctx = zlog .ContextWithValues (ctx , "component" , "datastore/postgres/MatcherStore.UpdateVulnerabilitiesIter" )
52
+ return s .updateVulnerabilities (ctx , updater , fp , it , nil )
53
+ }
54
+
48
55
// UpdateVulnerabilities implements vulnstore.Updater.
49
56
//
50
57
// It creates a new UpdateOperation for this update call, inserts the
51
58
// provided vulnerabilities and computes a diff comprising the removed
52
59
// and added vulnerabilities for this UpdateOperation.
53
- func (s * MatcherStore ) UpdateVulnerabilities (ctx context.Context , updater string , fingerprint driver.Fingerprint , vulns []* claircore.Vulnerability ) (uuid.UUID , error ) {
60
+ func (s * MatcherStore ) UpdateVulnerabilities (ctx context.Context , updater string , fp driver.Fingerprint , vulns []* claircore.Vulnerability ) (uuid.UUID , error ) {
54
61
ctx = zlog .ContextWithValues (ctx , "component" , "datastore/postgres/MatcherStore.UpdateVulnerabilities" )
55
- return s .updateVulnerabilities (ctx , updater , fingerprint , vulns , nil , false )
62
+ iterVulns := func (yield func (* claircore.Vulnerability , error ) bool ) {
63
+ for i := range vulns {
64
+ if ! yield (vulns [i ], nil ) {
65
+ break
66
+ }
67
+ }
68
+ }
69
+ return s .updateVulnerabilities (ctx , updater , fp , iterVulns , nil )
56
70
}
57
71
58
72
// DeltaUpdateVulnerabilities implements vulnstore.Updater.
@@ -68,10 +82,24 @@ func (s *MatcherStore) UpdateVulnerabilities(ctx context.Context, updater string
68
82
// - Associate new vulnerabilities with new updateOperation
69
83
func (s * MatcherStore ) DeltaUpdateVulnerabilities (ctx context.Context , updater string , fingerprint driver.Fingerprint , vulns []* claircore.Vulnerability , deletedVulns []string ) (uuid.UUID , error ) {
70
84
ctx = zlog .ContextWithValues (ctx , "component" , "datastore/postgres/MatcherStore.DeltaUpdateVulnerabilities" )
71
- return s .updateVulnerabilities (ctx , updater , fingerprint , vulns , deletedVulns , true )
85
+ iterVulns := func (yield func (* claircore.Vulnerability , error ) bool ) {
86
+ for i := range vulns {
87
+ if ! yield (vulns [i ], nil ) {
88
+ break
89
+ }
90
+ }
91
+ }
92
+ delVulns := func (yield func (string , error ) bool ) {
93
+ for _ , s := range deletedVulns {
94
+ if ! yield (s , nil ) {
95
+ break
96
+ }
97
+ }
98
+ }
99
+ return s .updateVulnerabilities (ctx , updater , fingerprint , iterVulns , delVulns )
72
100
}
73
101
74
- func (s * MatcherStore ) updateVulnerabilities (ctx context.Context , updater string , fingerprint driver.Fingerprint , vulns [] * claircore. Vulnerability , deletedVulns [] string , delta bool ) (uuid.UUID , error ) {
102
+ func (s * MatcherStore ) updateVulnerabilities (ctx context.Context , updater string , fingerprint driver.Fingerprint , vulnIter datastore. VulnerabilityIter , delIter datastore. Iter [ string ] ) (uuid.UUID , error ) {
75
103
const (
76
104
// Create makes a new update operation and returns the reference and ID.
77
105
create = `INSERT INTO update_operation (updater, fingerprint, kind) VALUES ($1, $2, 'vulnerability') RETURNING id, ref;`
@@ -139,6 +167,7 @@ func (s *MatcherStore) updateVulnerabilities(ctx context.Context, updater string
139
167
return uuid .Nil , fmt .Errorf ("failed to create update_operation: %w" , err )
140
168
}
141
169
170
+ delta := delIter != nil
142
171
updateVulnerabilitiesCounter .WithLabelValues ("create" , strconv .FormatBool (delta )).Add (1 )
143
172
updateVulnerabilitiesDuration .WithLabelValues ("create" , strconv .FormatBool (delta )).Observe (time .Since (start ).Seconds ())
144
173
@@ -181,18 +210,20 @@ func (s *MatcherStore) updateVulnerabilities(ctx context.Context, updater string
181
210
}
182
211
183
212
if len (oldVulns ) > 0 {
184
- for _ , v := range vulns {
213
+ vulnIter ( func ( v * claircore. Vulnerability , _ error ) bool {
185
214
// If we have an existing vuln in the new batch
186
215
// delete it from the oldVulns map so it doesn't
187
216
// get associated with the new update_operation.
188
217
delete (oldVulns , v .Name )
189
- }
190
- for _ , delName := range deletedVulns {
218
+ return true
219
+ })
220
+ delIter (func (delName string , _ error ) bool {
191
221
// If we have an existing vuln that has been signaled
192
222
// as deleted by the updater then delete it so it doesn't
193
223
// get associated with the new update_operation.
194
224
delete (oldVulns , delName )
195
- }
225
+ return true
226
+ })
196
227
}
197
228
start = time .Now ()
198
229
// Associate already existing vulnerabilities with new update_operation.
@@ -211,14 +242,20 @@ func (s *MatcherStore) updateVulnerabilities(ctx context.Context, updater string
211
242
212
243
// batch insert vulnerabilities
213
244
skipCt := 0
214
-
245
+ vulnCt := 0
215
246
start = time .Now ()
216
247
217
248
mBatcher := microbatch .NewInsert (tx , 2000 , time .Minute )
218
- for _ , vuln := range vulns {
249
+
250
+ vulnIter (func (vuln * claircore.Vulnerability , iterErr error ) bool {
251
+ if iterErr != nil {
252
+ err = iterErr
253
+ return false
254
+ }
255
+ vulnCt ++
219
256
if vuln .Package == nil || vuln .Package .Name == "" {
220
257
skipCt ++
221
- continue
258
+ return true
222
259
}
223
260
224
261
pkg := vuln .Package
@@ -233,7 +270,7 @@ func (s *MatcherStore) updateVulnerabilities(ctx context.Context, updater string
233
270
hashKind , hash := md5Vuln (vuln )
234
271
vKind , vrLower , vrUpper := rangefmt (vuln .Range )
235
272
236
- err : = mBatcher .Queue (ctx , insert ,
273
+ err = mBatcher .Queue (ctx , insert ,
237
274
hashKind , hash ,
238
275
vuln .Name , vuln .Updater , vuln .Description , vuln .Issued , vuln .Links , vuln .Severity , vuln .NormalizedSeverity ,
239
276
pkg .Name , pkg .Version , pkg .Module , pkg .Arch , pkg .Kind ,
@@ -242,12 +279,20 @@ func (s *MatcherStore) updateVulnerabilities(ctx context.Context, updater string
242
279
vuln .FixedInVersion , vuln .ArchOperation , vKind , vrLower , vrUpper ,
243
280
)
244
281
if err != nil {
245
- return uuid .Nil , fmt .Errorf ("failed to queue vulnerability: %w" , err )
282
+ err = fmt .Errorf ("failed to queue vulnerability: %w" , err )
283
+ return false
246
284
}
247
285
248
- if err := mBatcher .Queue (ctx , assoc , hashKind , hash , uoID ); err != nil {
249
- return uuid .Nil , fmt .Errorf ("failed to queue association: %w" , err )
286
+ err = mBatcher .Queue (ctx , assoc , hashKind , hash , uoID )
287
+ if err != nil {
288
+ err = fmt .Errorf ("failed to queue association: %w" , err )
289
+ return false
250
290
}
291
+
292
+ return true
293
+ })
294
+ if err != nil {
295
+ return uuid .Nil , fmt .Errorf ("iterating on vulnerabilities: %w" , err )
251
296
}
252
297
if err := mBatcher .Done (ctx ); err != nil {
253
298
return uuid .Nil , fmt .Errorf ("failed to finish batch vulnerability insert: %w" , err )
@@ -266,7 +311,7 @@ func (s *MatcherStore) updateVulnerabilities(ctx context.Context, updater string
266
311
zlog .Debug (ctx ).
267
312
Str ("ref" , ref .String ()).
268
313
Int ("skipped" , skipCt ).
269
- Int ("inserted" , len ( vulns ) - skipCt ).
314
+ Int ("inserted" , vulnCt - skipCt ).
270
315
Msg ("update_operation committed" )
271
316
return ref , nil
272
317
}
0 commit comments