Skip to content

Commit 404425e

Browse files
committed
use structs for display
1 parent ebe4db1 commit 404425e

File tree

2 files changed

+913
-5
lines changed

2 files changed

+913
-5
lines changed

cmd/validate/vsa.go

Lines changed: 231 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,45 @@ type AllSectionsData struct {
585585
FallbackResults []validate_utils.Result
586586
}
587587

588+
// ComponentResultsDisplay holds all formatted display data for component results
589+
type ComponentResultsDisplay struct {
590+
Header HeaderDisplay
591+
Result ResultDisplay
592+
VSASummary VSASummaryDisplay
593+
PolicyDiff *PolicyDiffDisplay // nil if no policy diff
594+
// Other sections will be added one at a time
595+
}
596+
597+
// HeaderDisplay holds the formatted header section data
598+
type HeaderDisplay struct {
599+
Title string
600+
Timestamp string
601+
}
602+
603+
// ResultDisplay holds the formatted Result section data
604+
type ResultDisplay struct {
605+
Overall string // "✅ PASSED" or "❌ FAILED"
606+
Fallback string // "used for all images", "used for some images", or ""
607+
ImageCount int
608+
ImageLines []string // Formatted image status lines
609+
}
610+
611+
// VSASummaryDisplay holds the formatted VSA Summary section data
612+
type VSASummaryDisplay struct {
613+
Signature string // Signature status
614+
Predicate string // Predicate status line
615+
Policy string // Policy status line
616+
FallbackReasons string // Fallback reason(s) line, or ""
617+
}
618+
619+
// PolicyDiffDisplay holds the formatted Policy Diff section data
620+
type PolicyDiffDisplay struct {
621+
AffectedImages string // Comma-separated list of affected images
622+
Added string // "none" or "[include] N"
623+
Removed string // "none" or "N"
624+
Changed string // "none" or "N"
625+
}
626+
588627
// Helper functions
589628

590629
// shortenImageDigest extracts and shortens image digest to 8 characters
@@ -788,12 +827,81 @@ func aggregateAllSectionsData(allResults []vsa.ComponentResult) AllSectionsData
788827
return data
789828
}
790829

830+
// buildHeaderDisplay creates a HeaderDisplay from a timestamp
831+
func buildHeaderDisplay(timestamp time.Time) HeaderDisplay {
832+
return HeaderDisplay{
833+
Title: "VALIDATE VSA RESULT",
834+
Timestamp: timestamp.Format(time.RFC3339),
835+
}
836+
}
837+
838+
// String formats the header for display
839+
func (h HeaderDisplay) String() string {
840+
return fmt.Sprintf("=== %s — %s ===\n", h.Title, h.Timestamp)
841+
}
842+
791843
// displayHeaderSection - Displays header with timestamp
844+
// DEPRECATED: Use buildHeaderDisplay and HeaderDisplay.String() instead
792845
func displayHeaderSection(timestamp time.Time) {
793846
fmt.Printf("=== VALIDATE VSA RESULT — %s ===\n", timestamp.Format(time.RFC3339))
794847
}
795848

849+
// buildResultDisplay creates a ResultDisplay from AllSectionsData
850+
func buildResultDisplay(data AllSectionsData) ResultDisplay {
851+
result := ResultDisplay{
852+
ImageCount: data.TotalImages,
853+
}
854+
855+
// Set overall status
856+
if data.OverallPassed {
857+
result.Overall = "✅ PASSED"
858+
} else {
859+
result.Overall = "❌ FAILED"
860+
}
861+
862+
// Set fallback status
863+
if data.FallbackUsed {
864+
if data.FallbackCount == data.TotalImages {
865+
result.Fallback = "used for all images"
866+
} else {
867+
result.Fallback = "used for some images"
868+
}
869+
}
870+
871+
// Build image status lines
872+
result.ImageLines = make([]string, 0, len(data.ImageStatuses))
873+
for _, img := range data.ImageStatuses {
874+
statusLine := fmt.Sprintf(" [%d] …%s VSA=%s", img.Index, img.Digest, img.VSAStatus)
875+
if img.FallbackStatus != "" {
876+
statusLine += fmt.Sprintf(" Fallback=%s", img.FallbackStatus)
877+
}
878+
result.ImageLines = append(result.ImageLines, statusLine)
879+
}
880+
881+
return result
882+
}
883+
884+
// String formats the Result section for display
885+
func (r ResultDisplay) String() string {
886+
var b strings.Builder
887+
b.WriteString("Result\n")
888+
b.WriteString(fmt.Sprintf(" Overall: %s\n", r.Overall))
889+
890+
if r.Fallback != "" {
891+
b.WriteString(fmt.Sprintf(" Fallback: %s\n", r.Fallback))
892+
}
893+
894+
b.WriteString(fmt.Sprintf(" Images (%d):\n", r.ImageCount))
895+
for _, line := range r.ImageLines {
896+
b.WriteString(line)
897+
b.WriteString("\n")
898+
}
899+
900+
return b.String()
901+
}
902+
796903
// displayResultSection - Displays Result section
904+
// DEPRECATED: Use buildResultDisplay and ResultDisplay.String() instead
797905
func displayResultSection(data AllSectionsData) {
798906
fmt.Println("Result")
799907
if data.OverallPassed {
@@ -820,7 +928,67 @@ func displayResultSection(data AllSectionsData) {
820928
}
821929
}
822930

931+
// buildVSASummaryDisplay creates a VSASummaryDisplay from AllSectionsData
932+
func buildVSASummaryDisplay(data AllSectionsData) VSASummaryDisplay {
933+
summary := VSASummaryDisplay{
934+
Signature: data.SignatureStatus,
935+
}
936+
937+
// Build predicate status
938+
totalPredicates := data.PredicatePassed + data.PredicateFailed
939+
if totalPredicates == 0 {
940+
summary.Predicate = "(no predicate data)"
941+
} else if data.PredicateFailed == 0 {
942+
summary.Predicate = fmt.Sprintf("passed (%d/%d)", data.PredicatePassed, totalPredicates)
943+
} else if data.PredicatePassed == 0 {
944+
summary.Predicate = fmt.Sprintf("failed (%d/%d)", data.PredicateFailed, totalPredicates)
945+
} else {
946+
summary.Predicate = fmt.Sprintf("mixed (passed: %d, failed: %d)", data.PredicatePassed, data.PredicateFailed)
947+
}
948+
949+
// Build policy status
950+
totalPolicyChecks := data.PolicyMatches + data.PolicyMismatches
951+
if totalPolicyChecks == 0 {
952+
summary.Policy = "(no policy data)"
953+
} else if data.PolicyMismatches == 0 {
954+
summary.Policy = "matches (no differences)"
955+
} else {
956+
// Aggregate policy diff counts
957+
totals := aggregatePolicyDiffTotals(data.PolicyDiffCounts)
958+
summary.Policy = fmt.Sprintf("mismatches on %d/%d images (adds=%d, removes=%d, changes=%d)",
959+
data.PolicyMismatches, totalPolicyChecks, totals.Added, totals.Removed, totals.Changed)
960+
}
961+
962+
// Build fallback reasons
963+
if len(data.FallbackReasons) > 0 {
964+
var reasons []string
965+
for reason := range data.FallbackReasons {
966+
reasons = append(reasons, reason)
967+
}
968+
sort.Strings(reasons)
969+
summary.FallbackReasons = strings.Join(reasons, ", ")
970+
}
971+
972+
return summary
973+
}
974+
975+
// String formats the VSA Summary section for display
976+
func (v VSASummaryDisplay) String() string {
977+
var b strings.Builder
978+
b.WriteString("VSA Summary\n")
979+
b.WriteString(fmt.Sprintf(" Signature: %s\n", v.Signature))
980+
b.WriteString(fmt.Sprintf(" Predicate: %s\n", v.Predicate))
981+
b.WriteString(fmt.Sprintf(" Policy: %s\n", v.Policy))
982+
983+
if v.FallbackReasons != "" {
984+
b.WriteString(fmt.Sprintf(" Fallback reason(s): %s\n", v.FallbackReasons))
985+
}
986+
987+
return b.String()
988+
}
989+
823990
// displayVSASummarySection - Displays VSA Summary section
991+
// DEPRECATED: Use buildVSASummaryDisplay and VSASummaryDisplay.String() instead
824992
func displayVSASummarySection(data AllSectionsData) {
825993
fmt.Println("VSA Summary")
826994
fmt.Printf(" Signature: %s\n", data.SignatureStatus)
@@ -861,7 +1029,57 @@ func displayVSASummarySection(data AllSectionsData) {
8611029
}
8621030
}
8631031

1032+
// buildPolicyDiffDisplay creates a PolicyDiffDisplay from AllSectionsData
1033+
// Returns nil if there is no policy diff
1034+
func buildPolicyDiffDisplay(data AllSectionsData) *PolicyDiffDisplay {
1035+
if !data.HasPolicyDiff {
1036+
return nil
1037+
}
1038+
1039+
diff := &PolicyDiffDisplay{
1040+
AffectedImages: strings.Join(data.AffectedImages, ", "),
1041+
}
1042+
1043+
// Aggregate policy diff counts across all affected images
1044+
totals := aggregatePolicyDiffTotals(data.PolicyDiffCounts)
1045+
1046+
// Build added line
1047+
if totals.Added > 0 {
1048+
diff.Added = fmt.Sprintf("[include] %d", totals.Added)
1049+
} else {
1050+
diff.Added = "none"
1051+
}
1052+
1053+
// Build removed line
1054+
if totals.Removed > 0 {
1055+
diff.Removed = fmt.Sprintf("%d", totals.Removed)
1056+
} else {
1057+
diff.Removed = "none"
1058+
}
1059+
1060+
// Build changed line
1061+
if totals.Changed > 0 {
1062+
diff.Changed = fmt.Sprintf("%d", totals.Changed)
1063+
} else {
1064+
diff.Changed = "none"
1065+
}
1066+
1067+
return diff
1068+
}
1069+
1070+
// String formats the Policy Diff section for display
1071+
func (p PolicyDiffDisplay) String() string {
1072+
var b strings.Builder
1073+
b.WriteString("Policy Diff (summary)\n")
1074+
b.WriteString(fmt.Sprintf(" Affected images: [%s]\n", p.AffectedImages))
1075+
b.WriteString(fmt.Sprintf(" Added: %s\n", p.Added))
1076+
b.WriteString(fmt.Sprintf(" Removed: %s\n", p.Removed))
1077+
b.WriteString(fmt.Sprintf(" Changed: %s\n", p.Changed))
1078+
return b.String()
1079+
}
1080+
8641081
// displayPolicyDiffSection - Displays Policy Diff section (only if policy diff exists)
1082+
// DEPRECATED: Use buildPolicyDiffDisplay and PolicyDiffDisplay.String() instead
8651083
func displayPolicyDiffSection(data AllSectionsData) {
8661084
if !data.HasPolicyDiff {
8671085
return
@@ -974,19 +1192,27 @@ func displayComponentResults(allResults []vsa.ComponentResult, data *validateVSA
9741192
// Single aggregation pass - collect everything once
9751193
allData := aggregateAllSectionsData(allResults)
9761194

1195+
// Build display struct
1196+
display := ComponentResultsDisplay{
1197+
Header: buildHeaderDisplay(time.Now()),
1198+
Result: buildResultDisplay(allData),
1199+
VSASummary: buildVSASummaryDisplay(allData),
1200+
PolicyDiff: buildPolicyDiffDisplay(allData),
1201+
}
1202+
9771203
// Display sections in order (each is self-contained)
978-
displayHeaderSection(time.Now())
1204+
fmt.Print(display.Header.String())
9791205
fmt.Println()
9801206

981-
displayResultSection(allData)
1207+
fmt.Print(display.Result.String())
9821208
fmt.Println()
9831209

984-
displayVSASummarySection(allData)
1210+
fmt.Print(display.VSASummary.String())
9851211
fmt.Println()
9861212

9871213
// Conditional sections
988-
if allData.HasPolicyDiff {
989-
displayPolicyDiffSection(allData)
1214+
if display.PolicyDiff != nil {
1215+
fmt.Print(display.PolicyDiff.String())
9901216
fmt.Println()
9911217
}
9921218

0 commit comments

Comments
 (0)