1515package  cmd
1616
1717import  (
18+ 	"errors" 
1819	"fmt" 
1920	"io" 
2021	"os" 
2122	"runtime" 
23+ 	"strings" 
2224
2325	"github.com/GoogleContainerTools/container-structure-test/cmd/container-structure-test/app/cmd/test" 
2426	v1 "github.com/opencontainers/image-spec/specs-go/v1" 
@@ -32,6 +34,7 @@ import (
3234
3335	docker "github.com/fsouza/go-dockerclient" 
3436	"github.com/google/go-containerregistry/pkg/name" 
37+ 	gcrv1 "github.com/google/go-containerregistry/pkg/v1" 
3538	"github.com/google/go-containerregistry/pkg/v1/daemon" 
3639	"github.com/google/go-containerregistry/pkg/v1/layout" 
3740	"github.com/sirupsen/logrus" 
@@ -44,13 +47,60 @@ Be sure you know what you're doing before continuing!
4447
4548Continue? (y/n)` 
4649
50+ const  maxSubIndexes  =  5 
51+ 
4752var  (
4853	opts  =  & config.StructureTestOptions {}
4954
5055	args        * drivers.DriverConfig 
5156	driverImpl  func (drivers.DriverConfig ) (drivers.Driver , error )
57+ 
58+ 	errNoImageFound  =  errors .New ("no compatible image found" )
5259)
5360
61+ func  parsePlatform (s  string ) (* gcrv1.Platform , error ) {
62+ 	parts  :=  strings .Split (s , "/" )
63+ 	if  len (parts ) !=  2  {
64+ 		return  nil , fmt .Errorf ("invalid platform %q" , s )
65+ 	}
66+ 	os , arch  :=  parts [0 ], parts [1 ]
67+ 	platform  :=  & gcrv1.Platform {
68+ 		Architecture : arch ,
69+ 		OS :           os ,
70+ 	}
71+ 	return  platform , nil 
72+ }
73+ 
74+ func  findImageInIndex (index  gcrv1.ImageIndex , requirements  * gcrv1.Platform , depth  int ) (gcrv1.Image , error ) {
75+ 	if  depth  >  maxSubIndexes  {
76+ 		return  nil , fmt .Errorf ("too many subindexes (%d)" , maxSubIndexes )
77+ 	}
78+ 
79+ 	manifest , err  :=  index .IndexManifest ()
80+ 	if  err  !=  nil  {
81+ 		return  nil , fmt .Errorf ("failed to read index manifest: %w" , err )
82+ 	}
83+ 
84+ 	for  _ , desc  :=  range  manifest .Manifests  {
85+ 		if  desc .MediaType .IsImage () &&  desc .Platform .Satisfies (* requirements ) {
86+ 			return  index .Image (desc .Digest )
87+ 		}
88+ 		if  desc .MediaType .IsIndex () {
89+ 			// Recursively check subindex. 
90+ 			childIndex , err  :=  index .ImageIndex (desc .Digest )
91+ 			if  err  !=  nil  {
92+ 				return  nil , err 
93+ 			}
94+ 			img , err  :=  findImageInIndex (childIndex , requirements , depth + 1 )
95+ 			if  ! errors .Is (err , errNoImageFound ) {
96+ 				return  img , err 
97+ 			}
98+ 		}
99+ 	}
100+ 
101+ 	return  nil , errNoImageFound 
102+ }
103+ 
54104func  NewCmdTest (out  io.Writer ) * cobra.Command  {
55105	var  testCmd  =  & cobra.Command {
56106		Use :   "test" ,
@@ -124,14 +174,22 @@ func run(out io.Writer) error {
124174
125175		desc  :=  m .Manifests [0 ]
126176
177+ 		var  img  gcrv1.Image 
127178		if  desc .MediaType .IsIndex () {
128- 			logrus . Fatal ( "multi-arch images are not supported yet." )
129- 		} 
130- 
131- 		img ,  err   :=   l . Image ( desc . Digest ) 
179+ 			platform ,  err   :=   parsePlatform ( opts . Platform )
180+ 			 if   err   !=   nil  { 
181+ 				 logrus . Fatalf ( "%s" ,  err ) 
182+ 			} 
132183
133- 		if  err  !=  nil  {
134- 			logrus .Fatalf ("could not get image from %s: %v" , opts .ImageFromLayout , err )
184+ 			img , err  =  findImageInIndex (l , platform , 0 )
185+ 			if  err  !=  nil  {
186+ 				logrus .Fatalf ("could not get image from %s (platform %v): %v" , opts .ImageFromLayout , opts .Platform , err )
187+ 			}
188+ 		} else  {
189+ 			img , err  =  l .Image (desc .Digest )
190+ 			if  err  !=  nil  {
191+ 				logrus .Fatalf ("could not get image from %s: %v" , opts .ImageFromLayout , err )
192+ 			}
135193		}
136194
137195		var  tag  name.Tag 
0 commit comments