152 lines
2.9 KiB
Go
Raw Normal View History

package controller
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"nf-repo/internal/interfaces"
"nf-repo/internal/model"
"nf-repo/internal/opt"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
)
func PullRepo(ctx context.Context, repo string, tag string, proxy string,
mh interfaces.ManifestHandler, bh interfaces.BlobHandler,
) (*v1.Manifest, error) {
if repo == "" || tag == "" {
return nil, fmt.Errorf("invalid repo or tag")
}
var (
err error
transport = &http.Transport{}
puller *remote.Puller
tn name.Tag
des *remote.Descriptor
img v1.Image
manifest *v1.Manifest
bs []byte
mhash model.Hash
target = fmt.Sprintf("%s:%s", repo, tag)
)
if opt.Proxy != nil {
transport.Proxy = http.ProxyURL(opt.Proxy)
}
if proxy != "" {
var pu *url.URL
if pu, err = url.Parse(proxy); err != nil {
return nil, err
}
transport.Proxy = http.ProxyURL(pu)
}
if puller, err = remote.NewPuller(
remote.WithTransport(transport),
); err != nil {
return nil, err
}
if tn, err = name.NewTag(target); err != nil {
return nil, err
}
if des, err = puller.Get(ctx, tn); err != nil {
return nil, err
}
if img, err = des.Image(); err != nil {
return nil, err
}
if manifest, err = img.Manifest(); err != nil {
return nil, err
}
total := model.ManifestCountSize(manifest)
size := 0
_ = total
var (
tly v1.Layer
tdigest v1.Hash
treader io.ReadCloser
)
if tly, err = img.LayerByDigest(manifest.Config.Digest); err != nil {
return nil, err
}
if tdigest, err = tly.Digest(); err != nil {
return nil, err
}
if treader, err = tly.Uncompressed(); err != nil {
return nil, err
}
defer treader.Close()
if err = bh.Put(
ctx,
target,
model.Hash{Algorithm: tdigest.Algorithm, Hex: tdigest.Hex},
treader,
); err != nil {
return nil, err
}
size = size + int(manifest.Config.Size)
if bs, err = json.Marshal(manifest); err != nil {
return nil, err
}
if mhash, _, err = model.SHA256(bytes.NewReader(bs)); err != nil {
return nil, err
}
for idx := range manifest.Layers {
var (
reader io.ReadCloser
lyHash v1.Hash
ly v1.Layer
)
lyHash = manifest.Layers[idx].Digest
if ly, err = img.LayerByDigest(manifest.Layers[idx].Digest); err != nil {
return nil, err
}
if reader, err = ly.Compressed(); err != nil {
return nil, err
}
defer reader.Close()
if err = bh.Put(ctx, repo, model.Hash{Algorithm: lyHash.Algorithm, Hex: lyHash.Hex}, reader); err != nil {
return nil, err
}
size = size + int(manifest.Layers[idx].Size)
}
if re := mh.Put(ctx, repo, tag, mhash.String(), &model.RepoSimpleManifest{
ContentType: string(manifest.MediaType),
Blob: bs,
}); re != nil {
return nil, err
}
return manifest, nil
}