Files
ociclient/pullimage.go

105 lines
2.2 KiB
Go

package repocli
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
const (
MediaTypeOIIv1 = "application/vnd.oci.image.index.v1+json"
MediatypeDDMLv2 = "application/vnd.docker.distribution.manifest.list.v2+json"
MediatypeDDMv2 = "application/vnd.docker.distribution.manifest.v2+json"
MediaTypeOIMv1 = "application/vnd.oci.image.manifest.v1+json"
)
type Downloader struct {
cli *Client
}
func NewDownloader(client *Client) *Downloader {
return &Downloader{
cli: client,
}
}
func (down *Downloader) Pull(ctx context.Context, rawref, dir, os, arch string) error {
var err error
ref, err := NewReference(rawref)
if err != nil {
return err
}
rawrepo := ref.Repo()
tag := ref.Tag()
exist, mime, man, err := down.cli.GetManifest(ctx, rawrepo, tag)
if err != nil {
return err
}
if !exist {
err = errors.New("Manifest not found")
return err
}
if mime == MediaTypeOIIv1 || mime == MediatypeDDMLv2 {
var index ocispec.Index
err = json.Unmarshal(man, &index)
if err != nil {
return err
}
for _, descr := range index.Manifests {
if descr.Platform != nil {
cond := descr.Platform.Architecture == arch
cond = cond && descr.Platform.OS == os
if cond {
tag = descr.Digest.String()
}
}
}
}
fmt.Printf("Tag: %s\n", tag)
exist, mime, man, err = down.cli.GetManifest(ctx, rawrepo, tag)
if err != nil {
return err
}
fmt.Printf("Mime: %s\n", mime)
if !exist {
err = errors.New("Manifest not found")
return err
}
if mime != MediaTypeOIMv1 && mime != MediatypeDDMv2 {
err = errors.New("Unknown manifest media type")
return err
}
var manifest ocispec.Manifest
err = json.Unmarshal(man, &manifest)
if err != nil {
return err
}
"oci-layout"
"index.json"
layers := make([]ocispec.Descriptor, 0)
layers = append(layers, manifest.Config)
layers = append(layers, manifest.Layers...)
for _, layer := range layers {
digest := layer.Digest.String()
exist, err := down.cli.GetBlob(ctx, rawrepo, io.Discard, digest)
if err != nil {
return err
}
if !exist {
err = errors.New("Layer not found")
return err
}
fmt.Printf("Layer type: %s\n", layer.MediaType)
}
return err
}