Skip to content

Commit c3f6716

Browse files
magerstamyockgen
andauthored
Added image comparison functionality (#361)
* Added image comparison functionality * enhanced partition sorting in image comparison * Removed dead code * fixing lint issues * addressing failed UT and lint issues * Added additional go-tests * Added GPT disk/partition GUIDs to image comparison output --------- Co-authored-by: yockgen <yock.gen.mah@intel.com>
1 parent 08ba1e9 commit c3f6716

File tree

13 files changed

+2415
-186
lines changed

13 files changed

+2415
-186
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"strings"
7+
8+
"github.com/open-edge-platform/os-image-composer/internal/image/imageinspect"
9+
"github.com/open-edge-platform/os-image-composer/internal/utils/logger"
10+
"github.com/spf13/cobra"
11+
)
12+
13+
// Output format command flags
14+
var (
15+
prettyDiffJSON bool = true // Pretty-print JSON output
16+
outFormat string // "text" | "json"
17+
outMode string = "" // "full" | "diff" | "summary"
18+
)
19+
20+
// createCompareCommand creates the compare subcommand
21+
func createCompareCommand() *cobra.Command {
22+
compareCmd := &cobra.Command{
23+
Use: "compare [flags] IMAGE_FILE1 IMAGE_FILE2",
24+
Short: "compares two RAW image files",
25+
Long: `Compare performs a deep comparison of two generated
26+
RAW images and provides useful details of the differences such as
27+
partition table layout, filesystem type, bootloader type and
28+
configuration and overall SBOM details if available.`,
29+
Args: cobra.ExactArgs(2),
30+
31+
RunE: executeCompare,
32+
ValidArgsFunction: templateFileCompletion,
33+
}
34+
35+
// Add flags
36+
compareCmd.Flags().BoolVar(&prettyDiffJSON, "pretty", true,
37+
"Pretty-print JSON output (only for --format json)")
38+
compareCmd.Flags().StringVar(&outFormat, "format", "text",
39+
"Output format: text or json")
40+
compareCmd.Flags().StringVar(&outMode, "mode", "",
41+
"Output mode: full, diff, or summary (default: diff for text, full for json)")
42+
return compareCmd
43+
}
44+
45+
func resolveDefaults(format, mode string) (string, string) {
46+
format = strings.ToLower(format)
47+
mode = strings.ToLower(mode)
48+
49+
// Set default mode if not specified
50+
if mode == "" {
51+
if format == "json" {
52+
mode = "full"
53+
} else {
54+
mode = "diff"
55+
}
56+
}
57+
return format, mode
58+
}
59+
60+
// executeCompare handles the compare command execution logic
61+
func executeCompare(cmd *cobra.Command, args []string) error {
62+
log := logger.Logger()
63+
imageFile1 := args[0]
64+
imageFile2 := args[1]
65+
log.Infof("Comparing image files: %s and %s", imageFile1, imageFile2)
66+
67+
inspector := newInspector()
68+
69+
image1, err1 := inspector.Inspect(imageFile1)
70+
if err1 != nil {
71+
return fmt.Errorf("image inspection failed: %v", err1)
72+
}
73+
image2, err2 := inspector.Inspect(imageFile2)
74+
if err2 != nil {
75+
return fmt.Errorf("image inspection failed: %v", err2)
76+
}
77+
78+
compareResult := imageinspect.CompareImages(image1, image2)
79+
80+
format, mode := resolveDefaults(outFormat, outMode)
81+
82+
switch format {
83+
case "json":
84+
var payload any
85+
switch mode {
86+
case "full":
87+
payload = &compareResult
88+
case "diff":
89+
payload = struct {
90+
Equal bool `json:"equal"`
91+
Diff imageinspect.ImageDiff `json:"diff"`
92+
}{Equal: compareResult.Equal, Diff: compareResult.Diff}
93+
case "summary":
94+
payload = struct {
95+
Equal bool `json:"equal"`
96+
Summary imageinspect.CompareSummary `json:"summary"`
97+
}{Equal: compareResult.Equal, Summary: compareResult.Summary}
98+
default:
99+
return fmt.Errorf("invalid --mode %q (expected diff|summary|full)", mode)
100+
}
101+
return writeCompareResult(cmd, payload, prettyDiffJSON)
102+
103+
case "text":
104+
return imageinspect.RenderCompareText(cmd.OutOrStdout(), &compareResult,
105+
imageinspect.CompareTextOptions{Mode: mode})
106+
107+
default:
108+
return fmt.Errorf("invalid --mode %q (expected text|json)", outMode)
109+
}
110+
}
111+
112+
func writeCompareResult(cmd *cobra.Command, v any, pretty bool) error {
113+
out := cmd.OutOrStdout()
114+
115+
var (
116+
b []byte
117+
err error
118+
)
119+
if pretty {
120+
b, err = json.MarshalIndent(v, "", " ")
121+
} else {
122+
b, err = json.Marshal(v)
123+
}
124+
if err != nil {
125+
return fmt.Errorf("marshal json: %w", err)
126+
}
127+
_, _ = fmt.Fprintln(out, string(b))
128+
return nil
129+
}

0 commit comments

Comments
 (0)