@@ -33,17 +33,20 @@ import (
3333 "strings"
3434
3535 v1 "github.com/google/go-containerregistry/pkg/v1"
36+ "github.com/google/go-containerregistry/pkg/v1/empty"
3637 "github.com/google/go-containerregistry/pkg/v1/mutate"
3738 "github.com/google/go-containerregistry/pkg/v1/tarball"
39+ "github.com/google/go-containerregistry/pkg/v1/types"
3840)
3941
4042const (
4143 appDir = "/ko-app"
4244 defaultAppFilename = "ko-app"
4345)
4446
45- // GetBase takes an importpath and returns a base v1.Image.
46- type GetBase func (string ) (v1.Image , error )
47+ // GetBase takes an importpath and returns a base image.
48+ type GetBase func (string ) (Result , error )
49+
4750type builder func (context.Context , string , v1.Platform , bool ) (string , error )
4851
4952type buildContext interface {
@@ -442,15 +445,9 @@ func (g *gobuild) tarKoData(ref reference) (*bytes.Buffer, error) {
442445 return buf , walkRecursive (tw , root , kodataRoot )
443446}
444447
445- // Build implements build.Interface
446- func (gb * gobuild ) Build (ctx context.Context , s string ) (v1.Image , error ) {
448+ func (gb * gobuild ) buildOne (ctx context.Context , s string , base v1.Image ) (v1.Image , error ) {
447449 ref := newRef (s )
448450
449- // Determine the appropriate base image for this import path.
450- base , err := gb .getBase (ref .Path ())
451- if err != nil {
452- return nil , err
453- }
454451 cf , err := base .ConfigFile ()
455452 if err != nil {
456453 return nil , err
@@ -563,3 +560,70 @@ func updatePath(cf *v1.ConfigFile) {
563560 // If we get here, we never saw PATH.
564561 cf .Config .Env = append (cf .Config .Env , "PATH=" + appDir )
565562}
563+
564+ // Build implements build.Interface
565+ func (gb * gobuild ) Build (ctx context.Context , s string ) (Result , error ) {
566+ // Determine the appropriate base image for this import path.
567+ base , err := gb .getBase (s )
568+ if err != nil {
569+ return nil , err
570+ }
571+
572+ mt , err := base .MediaType ()
573+ if err != nil {
574+ return nil , err
575+ }
576+
577+ switch mt {
578+ case types .OCIImageIndex , types .DockerManifestList :
579+ base , ok := base .(v1.ImageIndex )
580+ if ! ok {
581+ return nil , fmt .Errorf ("failed to interpret base as index: %v" , base )
582+ }
583+ return gb .buildAll (ctx , s , base )
584+ case types .OCIManifestSchema1 , types .DockerManifestSchema2 :
585+ base , ok := base .(v1.Image )
586+ if ! ok {
587+ return nil , fmt .Errorf ("failed to interpret base as image: %v" , base )
588+ }
589+ return gb .buildOne (ctx , s , base )
590+ default :
591+ return nil , fmt .Errorf ("base image media type: %s" , mt )
592+ }
593+ }
594+
595+ func (gb * gobuild ) buildAll (ctx context.Context , s string , base v1.ImageIndex ) (v1.ImageIndex , error ) {
596+ im , err := base .IndexManifest ()
597+ if err != nil {
598+ return nil , err
599+ }
600+
601+ adds := []mutate.IndexAddendum {}
602+ for _ , desc := range im .Manifests {
603+ // This will fail if it's not an image, which is fine for now.
604+ base , err := base .Image (desc .Digest )
605+ if err != nil {
606+ return nil , err
607+ }
608+ img , err := gb .buildOne (ctx , s , base )
609+ if err != nil {
610+ return nil , err
611+ }
612+ adds = append (adds , mutate.IndexAddendum {
613+ Add : img ,
614+ Descriptor : v1.Descriptor {
615+ URLs : desc .URLs ,
616+ MediaType : desc .MediaType ,
617+ Annotations : desc .Annotations ,
618+ Platform : desc .Platform ,
619+ },
620+ })
621+ }
622+
623+ baseType , err := base .MediaType ()
624+ if err != nil {
625+ return nil , err
626+ }
627+
628+ return mutate .IndexMediaType (mutate .AppendManifests (empty .Index , adds ... ), baseType ), nil
629+ }
0 commit comments