@@ -54,6 +54,7 @@ type Input struct {
5454
5555type snapshot struct {
5656 app.SnapshotSpec
57+ Expansion * ExpansionInfo
5758}
5859
5960func (s * snapshot ) merge (snap app.SnapshotSpec ) {
@@ -89,7 +90,7 @@ func (s *snapshot) merge(snap app.SnapshotSpec) {
8990 }
9091}
9192
92- func DetermineInputSpec (ctx context.Context , input Input ) (* app.SnapshotSpec , error ) {
93+ func DetermineInputSpec (ctx context.Context , input Input ) (* app.SnapshotSpec , * ExpansionInfo , error ) {
9394 var snapshot snapshot
9495 provided := false
9596
@@ -106,7 +107,7 @@ func DetermineInputSpec(ctx context.Context, input Input) (*app.SnapshotSpec, er
106107
107108 file , err := readSnapshotSource (content )
108109 if err != nil {
109- return nil , err
110+ return nil , nil , err
110111 }
111112 snapshot .merge (file )
112113 provided = true
@@ -117,11 +118,11 @@ func DetermineInputSpec(ctx context.Context, input Input) (*app.SnapshotSpec, er
117118 fs := utils .FS (ctx )
118119 content , err := afero .ReadFile (fs , input .File )
119120 if err != nil {
120- return nil , err
121+ return nil , nil , err
121122 }
122123 file , err := readSnapshotSource (content )
123124 if err != nil {
124- return nil , err
125+ return nil , nil , err
125126 }
126127 snapshot .merge (file )
127128 provided = true
@@ -131,7 +132,7 @@ func DetermineInputSpec(ctx context.Context, input Input) (*app.SnapshotSpec, er
131132 if input .JSON != "" {
132133 json , err := readSnapshotSource ([]byte (input .JSON ))
133134 if err != nil {
134- return nil , err
135+ return nil , nil , err
135136 }
136137 snapshot .merge (json )
137138 provided = true
@@ -156,25 +157,29 @@ func DetermineInputSpec(ctx context.Context, input Input) (*app.SnapshotSpec, er
156157 client , err := kubernetes .NewClient (ctx )
157158 if err != nil {
158159 log .Debugf ("Unable to initialize Kubernetes Client: %v" , err )
159- return nil , err
160+ return nil , nil , err
160161 }
161162
162163 cluster , err := client .FetchSnapshot (ctx , input .Snapshot )
163164 if err != nil {
164165 log .Debugf ("Unable to fetch snapshot %s from Kubernetes cluster: %v" , input .Snapshot , err )
165- return nil , err
166+ return nil , nil , err
166167 }
167168 snapshot .merge (cluster .Spec )
168169 provided = true
169170 }
170171
171172 if ! provided {
172173 log .Debug ("No application snapshot available" )
173- return nil , errors .New ("neither Snapshot nor image reference provided to validate" )
174+ return nil , nil , errors .New ("neither Snapshot nor image reference provided to validate" )
174175 }
175- expandImageIndex (ctx , & snapshot .SnapshotSpec )
176+ exp := expandImageIndex (ctx , & snapshot .SnapshotSpec )
176177
177- return & snapshot .SnapshotSpec , nil
178+ // Store expansion info in the snapshot for later use
179+ // This will be used when building the Report
180+ snapshot .Expansion = exp
181+
182+ return & snapshot .SnapshotSpec , exp , nil
178183}
179184
180185func readSnapshotSource (input []byte ) (app.SnapshotSpec , error ) {
@@ -192,7 +197,7 @@ func readSnapshotSource(input []byte) (app.SnapshotSpec, error) {
192197// For an image index, remove the original component and replace it with an expanded component with all its image manifests
193198// Do not raise an error if the image is inaccessible, it will be handled as a violation when evaluated against the policy
194199// This is to retain the original behavior of the `ec validate` command.
195- func imageIndexWorker (client oci.Client , component app.SnapshotComponent , componentChan chan <- []app.SnapshotComponent , errorsChan chan <- error ) {
200+ func imageIndexWorker (client oci.Client , component app.SnapshotComponent , componentChan chan <- []app.SnapshotComponent , errorsChan chan <- error , exp * ExpansionInfo ) {
196201 var components []app.SnapshotComponent
197202 components = append (components , component )
198203 // to avoid adding to componentsChan before each return
@@ -228,6 +233,10 @@ func imageIndexWorker(client oci.Client, component app.SnapshotComponent, compon
228233 return
229234 }
230235
236+ // Track expansion metadata
237+ idxPinned := fmt .Sprintf ("%s@%s" , ref .Context ().Name (), desc .Digest )
238+ exp .IndexAliases [ref .Name ()] = idxPinned
239+
231240 // Add the platform-specific image references (Image Manifests) to the list of components so
232241 // each is validated as well as the multi-platform image reference (Image Index).
233242 for i , manifest := range indexManifest .Manifests {
@@ -241,15 +250,21 @@ func imageIndexWorker(client oci.Client, component app.SnapshotComponent, compon
241250 archComponent .Name = fmt .Sprintf ("%s-%s-%s" , component .Name , manifest .Digest , arch )
242251 archComponent .ContainerImage = fmt .Sprintf ("%s@%s" , ref .Context ().Name (), manifest .Digest )
243252 components = append (components , archComponent )
253+
254+ // Track parent-child relationships
255+ childPinned := archComponent .ContainerImage
256+ exp .ChildrenByIndex [idxPinned ] = append (exp .ChildrenByIndex [idxPinned ], childPinned )
257+ exp .ParentByChild [childPinned ] = idxPinned
244258 }
245259}
246260
247- func expandImageIndex (ctx context.Context , snap * app.SnapshotSpec ) {
261+ func expandImageIndex (ctx context.Context , snap * app.SnapshotSpec ) * ExpansionInfo {
248262 if trace .IsEnabled () {
249263 region := trace .StartRegion (ctx , "ec:expand-image-index" )
250264 defer region .End ()
251265 }
252266
267+ exp := NewExpansionInfo ()
253268 client := oci .NewClient (ctx )
254269
255270 componentChan := make (chan []app.SnapshotComponent , len (snap .Components ))
@@ -259,7 +274,7 @@ func expandImageIndex(ctx context.Context, snap *app.SnapshotSpec) {
259274 for _ , component := range snap .Components {
260275 // fetch manifests concurrently
261276 g .Go (func () error {
262- imageIndexWorker (client , component , componentChan , errorsChan )
277+ imageIndexWorker (client , component , componentChan , errorsChan , exp )
263278 return nil
264279 })
265280 }
@@ -289,6 +304,8 @@ func expandImageIndex(ctx context.Context, snap *app.SnapshotSpec) {
289304 log .Warnf ("Encountered error while checking for Image Index: %v" , allErrors )
290305 }
291306 log .Debugf ("Snap component after expanding the image index is %v" , snap .Components )
307+
308+ return exp
292309}
293310
294311func imageWorkers () int {
0 commit comments