@@ -22,7 +22,6 @@ import (
2222 "errors"
2323 "fmt"
2424 "runtime/trace"
25- "sort"
2625 "strings"
2726 "time"
2827
@@ -36,7 +35,6 @@ import (
3635
3736 "github.com/conforma/cli/internal/applicationsnapshot"
3837 "github.com/conforma/cli/internal/evaluator"
39- "github.com/conforma/cli/internal/format"
4038 "github.com/conforma/cli/internal/image"
4139 "github.com/conforma/cli/internal/output"
4240 "github.com/conforma/cli/internal/policy"
@@ -321,12 +319,6 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command {
321319 defer task .End ()
322320 }
323321
324- type result struct {
325- err error
326- component applicationsnapshot.Component
327- policyInput []byte
328- }
329-
330322 appComponents := data .spec .Components
331323 evaluators := []evaluator.Evaluator {}
332324
@@ -364,7 +356,7 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command {
364356
365357 // worker is responsible for processing one component at a time from the jobs channel,
366358 // and for emitting a corresponding result for the component on the results channel.
367- worker := func (id int , jobs <- chan app.SnapshotComponent , results chan <- result ) {
359+ worker := func (id int , jobs <- chan app.SnapshotComponent , results chan <- validate_utils. Result ) {
368360 log .Debugf ("Starting worker %d" , id )
369361 for comp := range jobs {
370362 ctx := cmd .Context ()
@@ -391,46 +383,11 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command {
391383 // Use original validation when VSA checking is disabled
392384 out , err = validate (ctx , comp , data .spec , data .policy , evaluators , data .info )
393385 }
394- res := result {
395- err : err ,
396- component : applicationsnapshot.Component {
397- SnapshotComponent : comp ,
398- Success : err == nil ,
399- },
400- }
401-
402- // Skip on err to not panic. Error is return on routine completion.
403- if err == nil {
404- if out != nil {
405- // Normal validation completed
406- res .component .Violations = out .Violations ()
407- res .component .Warnings = out .Warnings ()
408-
409- successes := out .Successes ()
410- res .component .SuccessCount = len (successes )
411- if showSuccesses {
412- res .component .Successes = successes
413- }
414-
415- res .component .Signatures = out .Signatures
416- // Create a new result object for attestations. The point is to only keep the data that's needed.
417- // For example, the Statement is only needed when the full attestation is printed.
418- for _ , att := range out .Attestations {
419- attResult := applicationsnapshot .NewAttestationResult (att )
420- if containsOutput (data .output , "attestation" ) {
421- attResult .Statement = att .Statement ()
422- }
423- res .component .Attestations = append (res .component .Attestations , attResult )
424- }
425- res .component .ContainerImage = out .ImageURL
426- res .policyInput = out .PolicyInput
427- } else {
428- // Validation was skipped due to valid VSA - no violations, no processing needed
429- log .Debugf ("Validation skipped for %s due to valid VSA" , comp .ContainerImage )
430- res .component .ContainerImage = comp .ContainerImage
431- }
386+ res := validate_utils .PopulateResultFromOutput (out , err , comp , showSuccesses , data .output )
387+ if err == nil && out == nil {
388+ // Validation was skipped due to valid VSA - no violations, no processing needed
389+ log .Debugf ("Validation skipped for %s due to valid VSA" , comp .ContainerImage )
432390 }
433- res .component .Success = err == nil && len (res .component .Violations ) == 0
434391
435392 if task != nil {
436393 task .End ()
@@ -446,7 +403,7 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command {
446403 numWorkers := data .workers
447404
448405 jobs := make (chan app.SnapshotComponent , numComponents )
449- results := make (chan result , numComponents )
406+ results := make (chan validate_utils. Result , numComponents )
450407 // Initialize each worker. They will wait patiently until a job is sent to the jobs
451408 // channel, or the jobs channel is closed.
452409 for i := 0 ; i <= numWorkers ; i ++ {
@@ -459,40 +416,43 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command {
459416 }
460417 close (jobs )
461418
462- var components []applicationsnapshot.Component
463- var manyPolicyInput [][]byte
464- var allErrors error = nil
419+ // Collect all results from the channel
420+ var allResults []validate_utils.Result
465421 for i := 0 ; i < numComponents ; i ++ {
466- r := <- results
467- if r .err != nil {
468- e := fmt .Errorf ("error validating image %s of component %s: %w" , r .component .ContainerImage , r .component .Name , r .err )
469- allErrors = errors .Join (allErrors , e )
470- } else {
471- components = append (components , r .component )
472- manyPolicyInput = append (manyPolicyInput , r .policyInput )
473- }
422+ allResults = append (allResults , <- results )
474423 }
475424 close (results )
476- if allErrors != nil {
477- return allErrors
478- }
479425
480- // Ensure some consistency in output.
481- sort .Slice (components , func (i , j int ) bool {
482- return components [i ].ContainerImage > components [j ].ContainerImage
483- })
426+ components , manyPolicyInput , err := validate_utils .CollectComponentResults (
427+ allResults ,
428+ func (r validate_utils.Result ) error {
429+ return fmt .Errorf ("error validating image %s of component %s: %w" , r .Component .ContainerImage , r .Component .Name , r .Err )
430+ },
431+ )
432+ if err != nil {
433+ return err
434+ }
484435
485436 if len (data .outputFile ) > 0 {
486437 data .output = append (data .output , fmt .Sprintf ("%s=%s" , applicationsnapshot .JSON , data .outputFile ))
487438 }
488439
489- report , err := applicationsnapshot .NewReport (data .snapshot , components , data .policy , manyPolicyInput , showSuccesses , showWarnings , data .expansion )
490- if err != nil {
491- return err
440+ reportData := validate_utils.ReportData {
441+ Snapshot : data .snapshot ,
442+ Components : components ,
443+ Policy : data .policy ,
444+ PolicyInputs : manyPolicyInput ,
445+ Expansion : data .expansion ,
446+ ShowSuccesses : showSuccesses ,
447+ ShowWarnings : showWarnings ,
492448 }
493- p := format .NewTargetParser (applicationsnapshot .JSON , format.Options {ShowSuccesses : showSuccesses , ShowWarnings : showWarnings }, cmd .OutOrStdout (), utils .FS (cmd .Context ()))
494- utils .SetColorEnabled (data .noColor , data .forceColor )
495- if err := report .WriteAll (data .output , p ); err != nil {
449+ outputOpts := validate_utils.ReportOutputOptions {
450+ Output : data .output ,
451+ NoColor : data .noColor ,
452+ ForceColor : data .forceColor ,
453+ }
454+ report , err := validate_utils .WriteReport (reportData , outputOpts , cmd )
455+ if err != nil {
496456 return err
497457 }
498458
@@ -684,12 +644,3 @@ func validateImageCmd(validate imageValidationFunc) *cobra.Command {
684644}
685645
686646// find if the slice contains "value" output
687- func containsOutput (data []string , value string ) bool {
688- for _ , item := range data {
689- newItem := strings .Split (item , "=" )
690- if newItem [0 ] == value {
691- return true
692- }
693- }
694- return false
695- }
0 commit comments