mirror of
https://github.com/mudler/luet.git
synced 2025-06-30 17:22:38 +00:00
130 lines
3.3 KiB
Go
130 lines
3.3 KiB
Go
|
package imgworker
|
||
|
|
||
|
// FROM Slightly adapted from genuinetools/img worker
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
|
||
|
"github.com/containerd/containerd/images"
|
||
|
"github.com/containerd/containerd/platforms"
|
||
|
"github.com/docker/distribution/reference"
|
||
|
"github.com/moby/buildkit/cache"
|
||
|
"github.com/moby/buildkit/exporter"
|
||
|
imageexporter "github.com/moby/buildkit/exporter/containerimage"
|
||
|
"github.com/moby/buildkit/source"
|
||
|
"github.com/moby/buildkit/source/containerimage"
|
||
|
)
|
||
|
|
||
|
// ListedImage represents an image structure returuned from ListImages.
|
||
|
// It extends containerd/images.Image with extra fields.
|
||
|
type ListedImage struct {
|
||
|
images.Image
|
||
|
ContentSize int64
|
||
|
}
|
||
|
|
||
|
// Pull retrieves an image from a remote registry.
|
||
|
func (c *Client) Pull(image string) (*ListedImage, error) {
|
||
|
|
||
|
ctx := c.ctx
|
||
|
|
||
|
sm, err := c.getSessionManager()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
// Parse the image name and tag.
|
||
|
named, err := reference.ParseNormalizedNamed(image)
|
||
|
if err != nil {
|
||
|
return nil, 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()
|
||
|
|
||
|
// Get the identifier for the image.
|
||
|
identifier, err := source.NewImageIdentifier(image)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
// Create the worker opts.
|
||
|
opt, err := c.createWorkerOpt()
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("creating worker opt failed: %v", err)
|
||
|
}
|
||
|
|
||
|
cm, err := cache.NewManager(cache.ManagerOpt{
|
||
|
Snapshotter: opt.Snapshotter,
|
||
|
MetadataStore: opt.MetadataStore,
|
||
|
ContentStore: opt.ContentStore,
|
||
|
LeaseManager: opt.LeaseManager,
|
||
|
GarbageCollect: opt.GarbageCollect,
|
||
|
Applier: opt.Applier,
|
||
|
})
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
// Create the source for the pull.
|
||
|
srcOpt := containerimage.SourceOpt{
|
||
|
Snapshotter: opt.Snapshotter,
|
||
|
ContentStore: opt.ContentStore,
|
||
|
Applier: opt.Applier,
|
||
|
CacheAccessor: cm,
|
||
|
ImageStore: opt.ImageStore,
|
||
|
RegistryHosts: opt.RegistryHosts,
|
||
|
LeaseManager: opt.LeaseManager,
|
||
|
}
|
||
|
src, err := containerimage.NewSource(srcOpt)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
s, err := src.Resolve(ctx, identifier, sm)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
ref, err := s.Snapshot(ctx)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
// Create the exporter for the pull.
|
||
|
iw, err := imageexporter.NewImageWriter(imageexporter.WriterOpt{
|
||
|
Snapshotter: opt.Snapshotter,
|
||
|
ContentStore: opt.ContentStore,
|
||
|
Differ: opt.Differ,
|
||
|
})
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
expOpt := imageexporter.Opt{
|
||
|
SessionManager: sm,
|
||
|
ImageWriter: iw,
|
||
|
Images: opt.ImageStore,
|
||
|
RegistryHosts: opt.RegistryHosts,
|
||
|
LeaseManager: opt.LeaseManager,
|
||
|
}
|
||
|
exp, err := imageexporter.New(expOpt)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
e, err := exp.Resolve(ctx, map[string]string{"name": image})
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if _, err := e.Export(ctx, exporter.Source{Ref: ref}); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
// Get the image.
|
||
|
img, err := opt.ImageStore.Get(ctx, image)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("getting image %s from image store failed: %v", image, err)
|
||
|
}
|
||
|
size, err := img.Size(ctx, opt.ContentStore, platforms.Default())
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("calculating size of image %s failed: %v", img.Name, err)
|
||
|
}
|
||
|
|
||
|
return &ListedImage{Image: img, ContentSize: size}, nil
|
||
|
}
|