@@ -14,6 +14,7 @@ import (
1414 "path/filepath"
1515 "reflect"
1616 "regexp"
17+ "runtime"
1718 "slices"
1819 "strings"
1920 "time"
@@ -22,6 +23,7 @@ import (
2223 cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
2324 . "github.com/onsi/ginkgo/v2"
2425 . "github.com/onsi/gomega"
26+ "golang.org/x/sync/errgroup"
2527 appsv1 "k8s.io/api/apps/v1"
2628 batchv1 "k8s.io/api/batch/v1"
2729 corev1 "k8s.io/api/core/v1"
@@ -466,6 +468,37 @@ func SetupCA(ctx context.Context, k8sClient client.Client, namespace string, suf
466468 })
467469}
468470
471+ // PreloadImages pulls each image from the registry and loads it into the kind cluster.
472+ // All images are processed in parallel.
473+ func PreloadImages (ctx context.Context , images []string ) * errgroup.Group {
474+ g , ctx := errgroup .WithContext (ctx )
475+
476+ for _ , image := range images {
477+ g .Go (func () error {
478+ // Remove any cached manifest-index
479+ _ = exec .CommandContext (ctx , "docker" , "image" , "rm" , image ).Run ()
480+
481+ By ("pulling image:" + image )
482+
483+ pull := exec .CommandContext (ctx , "docker" , "pull" , "--platform" , "linux/" + runtime .GOARCH , image )
484+ if out , err := pull .CombinedOutput (); err != nil {
485+ return fmt .Errorf ("docker pull %s: %w\n %s" , image , err , out )
486+ }
487+
488+ By ("loading image into kind: " + image )
489+
490+ load := exec .CommandContext (ctx , "kind" , "load" , "docker-image" , image )
491+ if out , err := load .CombinedOutput (); err != nil {
492+ return fmt .Errorf ("kind load %s: %w\n %s" , image , err , out )
493+ }
494+
495+ return nil
496+ })
497+ }
498+
499+ return g
500+ }
501+
469502// EnsureNamespace ensures the test namespace is created and active.
470503func EnsureNamespace (ctx context.Context , k8sClient client.Client , name string ) {
471504 DeferCleanup (func (ctx context.Context ) {
0 commit comments