-
Notifications
You must be signed in to change notification settings - Fork 229
/
save.go
58 lines (49 loc) · 1.47 KB
/
save.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package client
import (
"context"
"errors"
"fmt"
"io"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/images/oci"
"github.com/docker/distribution/reference"
"github.com/moby/buildkit/util/dockerexporter"
)
// SaveImage exports an image as a tarball which can then be imported by docker.
func (c *Client) SaveImage(ctx context.Context, image, format string, writer io.WriteCloser) error {
// Parse the image name and tag.
named, err := reference.ParseNormalizedNamed(image)
if err != nil {
return fmt.Errorf("parsing image name %q failed: %v", image, err)
}
// Add the latest lag if they did not provide one.
named = reference.TagNameOnly(named)
image = named.String()
// Create the worker opts.
opt, err := c.createWorkerOpt(false)
if err != nil {
return fmt.Errorf("creating worker opt failed: %v", err)
}
if opt.ImageStore == nil {
return errors.New("image store is nil")
}
img, err := opt.ImageStore.Get(ctx, image)
if err != nil {
return fmt.Errorf("getting image %s from image store failed: %v", image, err)
}
var exporter images.Exporter
switch format {
case "docker":
exporter = &dockerexporter.DockerExporter{
Name: img.Name,
}
case "oci":
exporter = &oci.V1Exporter{}
default:
return fmt.Errorf("%q is not a valid format", format)
}
if err := exporter.Export(ctx, opt.ContentStore, img.Target, writer); err != nil {
return fmt.Errorf("exporting image %s failed: %v", image, err)
}
return writer.Close()
}