Skip to content

Commit d464819

Browse files
feat: allow saving specific platforms for an image
1 parent c6cd357 commit d464819

File tree

4 files changed

+86
-6
lines changed

4 files changed

+86
-6
lines changed

docker.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1786,6 +1786,22 @@ func (p *DockerProvider) ListImages(ctx context.Context) ([]ImageInfo, error) {
17861786

17871787
// SaveImages exports a list of images as an uncompressed tar
17881788
func (p *DockerProvider) SaveImages(ctx context.Context, output string, images ...string) error {
1789+
return p.SaveImagesWithOps(ctx, output, images)
1790+
}
1791+
1792+
// SaveImagesWithOpts exports a list of images as an uncompressed tar, passiong options to thw provider
1793+
func (p *DockerProvider) SaveImagesWithOps(ctx context.Context, output string, images []string, opts ...SaveImageOption) error {
1794+
saveOpts := saveOptions{}
1795+
dockerOpts := []client.ImageSaveOption{}
1796+
1797+
for _, o := range opts {
1798+
o(&saveOpts)
1799+
}
1800+
1801+
if len(saveOpts.Platforms) > 0 {
1802+
dockerOpts = append(dockerOpts, client.ImageSaveWithPlatforms(saveOpts.Platforms...))
1803+
}
1804+
17891805
outputFile, err := os.Create(output)
17901806
if err != nil {
17911807
return fmt.Errorf("opening output file %w", err)
@@ -1794,7 +1810,7 @@ func (p *DockerProvider) SaveImages(ctx context.Context, output string, images .
17941810
_ = outputFile.Close()
17951811
}()
17961812

1797-
imageReader, err := p.client.ImageSave(ctx, images)
1813+
imageReader, err := p.client.ImageSave(ctx, images, dockerOpts...)
17981814
if err != nil {
17991815
return fmt.Errorf("saving images %w", err)
18001816
}

image.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ package testcontainers
22

33
import (
44
"context"
5+
6+
"github.com/containerd/platforms"
7+
specs "github.com/opencontainers/image-spec/specs-go/v1"
58
)
69

710
// ImageInfo represents summary information of an image
@@ -10,9 +13,31 @@ type ImageInfo struct {
1013
Name string
1114
}
1215

16+
type saveOptions struct {
17+
Platforms []specs.Platform
18+
}
19+
20+
type SaveImageOption func(*saveOptions) error
21+
22+
// SaveImageWithPlatforms allows specifying which platform(s) to save
23+
func SaveImageWithPlatforms(plaforms ...string) SaveImageOption {
24+
return func(opts *saveOptions) error {
25+
for _, p := range plaforms {
26+
platform, err := platforms.Parse(p)
27+
if err != nil {
28+
return err
29+
}
30+
opts.Platforms = append(opts.Platforms, platform)
31+
}
32+
33+
return nil
34+
}
35+
}
36+
1337
// ImageProvider allows manipulating images
1438
type ImageProvider interface {
1539
ListImages(context.Context) ([]ImageInfo, error)
1640
SaveImages(context.Context, string, ...string) error
41+
SaveImagesWithOps(context.Context, string, []string, ...SaveImageOption) error
1742
PullImage(context.Context, string) error
1843
}

image_test.go

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"testing"
88

99
"github.com/stretchr/testify/require"
10-
1110
"github.com/testcontainers/testcontainers-go/internal/core"
1211
)
1312

@@ -18,7 +17,8 @@ func TestImageList(t *testing.T) {
1817
require.NoErrorf(t, err, "failed to get provider")
1918

2019
defer func() {
21-
_ = provider.Close()
20+
err = provider.Close()
21+
require.NoError(t, err)
2222
}()
2323

2424
req := ContainerRequest{
@@ -51,7 +51,8 @@ func TestSaveImages(t *testing.T) {
5151
require.NoErrorf(t, err, "failed to get provider")
5252

5353
defer func() {
54-
_ = provider.Close()
54+
err = provider.Close()
55+
require.NoError(t, err)
5556
}()
5657

5758
req := ContainerRequest{
@@ -71,3 +72,35 @@ func TestSaveImages(t *testing.T) {
7172

7273
require.NotZerof(t, info.Size(), "output file is empty")
7374
}
75+
76+
func TestSaveImagesWithOpts(t *testing.T) {
77+
t.Setenv("DOCKER_HOST", core.MustExtractDockerHost(context.Background()))
78+
79+
provider, err := ProviderDocker.GetProvider()
80+
require.NoErrorf(t, err, "failed to get provider")
81+
82+
defer func() {
83+
err = provider.Close()
84+
require.NoError(t, err)
85+
}()
86+
87+
req := ContainerRequest{
88+
Image: "redis:latest",
89+
ImagePlatform: "linux/amd64",
90+
}
91+
92+
ctr, err := provider.CreateContainer(context.Background(), req)
93+
CleanupContainer(t, ctr)
94+
require.NoErrorf(t, err, "creating test container")
95+
96+
output := filepath.Join(t.TempDir(), "images.tar")
97+
err = provider.SaveImagesWithOps(
98+
context.Background(), output, []string{req.Image}, SaveImageWithPlatforms("linux/amd64"),
99+
)
100+
require.NoErrorf(t, err, "saving image %q", req.Image)
101+
102+
info, err := os.Stat(output)
103+
require.NoError(t, err)
104+
105+
require.NotZerof(t, info.Size(), "output file is empty")
106+
}

modules/k3s/k3s.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,13 @@ func unmarshal(bytes []byte) (*KubeConfigValue, error) {
195195
}
196196

197197
// LoadImages loads images into the k3s container.
198+
type LoadImageOption = testcontainers.SaveImageOption
199+
198200
func (c *K3sContainer) LoadImages(ctx context.Context, images ...string) error {
201+
return c.LoadImagesWithOpts(ctx, images)
202+
}
203+
204+
func (c *K3sContainer) LoadImagesWithOpts(ctx context.Context, images []string, opts ...LoadImageOption) error {
199205
provider, err := testcontainers.ProviderDocker.GetProvider()
200206
if err != nil {
201207
return fmt.Errorf("getting docker provider %w", err)
@@ -210,7 +216,7 @@ func (c *K3sContainer) LoadImages(ctx context.Context, images ...string) error {
210216
_ = os.Remove(imagesTar.Name())
211217
}()
212218

213-
err = provider.SaveImages(context.Background(), imagesTar.Name(), images...)
219+
err = provider.SaveImagesWithOps(context.Background(), imagesTar.Name(), images, opts...)
214220
if err != nil {
215221
return fmt.Errorf("saving images %w", err)
216222
}
@@ -221,7 +227,7 @@ func (c *K3sContainer) LoadImages(ctx context.Context, images ...string) error {
221227
return fmt.Errorf("copying image to container %w", err)
222228
}
223229

224-
_, _, err = c.Exec(ctx, []string{"ctr", "-n=k8s.io", "images", "import", containerPath})
230+
_, _, err = c.Exec(ctx, []string{"ctr", "-n=k8s.io", "images", "import", "--all-platforms", containerPath})
225231
if err != nil {
226232
return fmt.Errorf("importing image %w", err)
227233
}

0 commit comments

Comments
 (0)