1
0
Fork 0
mirror of https://github.com/imjasonh/kontain.me synced 2026-07-19 07:09:18 +00:00

resolve TODOs in pkg/serve

This commit is contained in:
Jason Hall 2020-12-31 07:44:38 -05:00
parent d0af4eaa9b
commit ce2d2cc45c
7 changed files with 122 additions and 108 deletions

View file

@ -9,6 +9,7 @@ import (
"log"
"net/http"
"os"
"time"
"cloud.google.com/go/storage"
v1 "github.com/google/go-containerregistry/pkg/v1"
@ -23,26 +24,31 @@ func Blob(w http.ResponseWriter, r *http.Request, name string) {
http.Redirect(w, r, url, http.StatusSeeOther)
}
func BlobExists(name string) error {
ctx := context.Background() // TODO
type Storage struct {
client *storage.Client
}
func NewStorage(ctx context.Context) (*Storage, error) {
client, err := storage.NewClient(ctx)
if err != nil {
return fmt.Errorf("NewClient: %v", err)
return nil, fmt.Errorf("NewClient: %v", err)
}
_, err = client.Bucket(bucket).Object(fmt.Sprintf("blobs/%s", name)).Attrs(ctx)
return &Storage{client}, nil
}
func (s *Storage) BlobExists(ctx context.Context, name string) error {
_, err := s.client.Bucket(bucket).Object(fmt.Sprintf("blobs/%s", name)).Attrs(ctx)
return err
}
func writeBlob(name string, h v1.Hash, rc io.ReadCloser, contentType string) error {
ctx := context.Background() // TODO
client, err := storage.NewClient(ctx)
if err != nil {
return fmt.Errorf("NewClient: %v", err)
}
func (s *Storage) writeBlob(ctx context.Context, name string, h v1.Hash, rc io.ReadCloser, contentType string) error {
start := time.Now()
defer func() { log.Printf("writeBlob(%q) took %s", name, time.Since(start)) }()
// The DoesNotExist precondition can be hit when writing or flushing
// data, which can happen any of three places. Anywhere it happens,
// just ignore the error since that means the blob already exists.
w := client.Bucket(bucket).Object(fmt.Sprintf("blobs/%s", name)).
w := s.client.Bucket(bucket).Object(fmt.Sprintf("blobs/%s", name)).
If(storage.Conditions{DoesNotExist: true}).
NewWriter(ctx)
w.ObjectAttrs.ContentType = contentType
@ -65,14 +71,14 @@ func writeBlob(name string, h v1.Hash, rc io.ReadCloser, contentType string) err
}
return fmt.Errorf("w.Close: %v", err)
}
log.Printf("wrote blob %s", name)
return nil
}
// Index writes manifest, config and layer blobs for each image in the index,
// then writes and redirects to the index manifest contents pointing to those
// blobs.
func Index(w http.ResponseWriter, r *http.Request, idx v1.ImageIndex, also ...string) error {
// ServeIndex writes manifest, config and layer blobs for each image in the
// index, then writes and redirects to the index manifest contents pointing to
// those blobs.
func (s *Storage) ServeIndex(w http.ResponseWriter, r *http.Request, idx v1.ImageIndex, also ...string) error {
ctx := r.Context()
im, err := idx.IndexManifest()
if err != nil {
return err
@ -85,7 +91,7 @@ func Index(w http.ResponseWriter, r *http.Request, idx v1.ImageIndex, also ...st
if err != nil {
return err
}
return writeImage(img)
return s.writeImage(ctx, img)
})
}
if err := g.Wait(); err != nil {
@ -105,16 +111,14 @@ func Index(w http.ResponseWriter, r *http.Request, idx v1.ImageIndex, also ...st
if err != nil {
return err
}
log.Printf("writing index manifest %q", digest)
if err := writeBlob(digest.String(), digest, ioutil.NopCloser(bytes.NewReader(b)), string(mt)); err != nil {
if err := s.writeBlob(ctx, digest.String(), digest, ioutil.NopCloser(bytes.NewReader(b)), string(mt)); err != nil {
return err
}
for _, a := range also {
a := a
g.Go(func() error {
log.Printf("writing index manifest %q also to %q", digest, a)
return writeBlob(a, digest, ioutil.NopCloser(bytes.NewReader(b)), string(mt))
return s.writeBlob(ctx, a, digest, ioutil.NopCloser(bytes.NewReader(b)), string(mt))
})
}
if err := g.Wait(); err != nil {
@ -127,7 +131,7 @@ func Index(w http.ResponseWriter, r *http.Request, idx v1.ImageIndex, also ...st
}
// writeImage writes the layer blobs, config blob and manifest.
func writeImage(img v1.Image, also ...string) error {
func (s *Storage) writeImage(ctx context.Context, img v1.Image, also ...string) error {
// Write config blob for later serving.
ch, err := img.ConfigName()
if err != nil {
@ -137,8 +141,7 @@ func writeImage(img v1.Image, also ...string) error {
if err != nil {
return err
}
log.Printf("writing config blob %q", ch)
if err := writeBlob(ch.String(), ch, ioutil.NopCloser(bytes.NewReader(cb)), ""); err != nil {
if err := s.writeBlob(ctx, ch.String(), ch, ioutil.NopCloser(bytes.NewReader(cb)), "application/json"); err != nil {
return err
}
@ -159,8 +162,11 @@ func writeImage(img v1.Image, also ...string) error {
if err != nil {
return err
}
log.Printf("writing layer blob %q", lh)
return writeBlob(lh.String(), lh, rc, "")
mt, err := l.MediaType()
if err != nil {
return err
}
return s.writeBlob(ctx, lh.String(), lh, rc, string(mt))
})
}
if err := g.Wait(); err != nil {
@ -180,25 +186,24 @@ func writeImage(img v1.Image, also ...string) error {
if err != nil {
return err
}
log.Printf("writing image manifest %q", digest)
if err := writeBlob(digest.String(), digest, ioutil.NopCloser(bytes.NewReader(b)), string(mt)); err != nil {
if err := s.writeBlob(ctx, digest.String(), digest, ioutil.NopCloser(bytes.NewReader(b)), string(mt)); err != nil {
return err
}
for _, a := range also {
a := a
g.Go(func() error {
log.Printf("writing image manifest %q also to %q", digest, a)
return writeBlob(a, digest, ioutil.NopCloser(bytes.NewReader(b)), string(mt))
return s.writeBlob(ctx, a, digest, ioutil.NopCloser(bytes.NewReader(b)), string(mt))
})
}
return g.Wait()
return nil
}
// Manifest writes config and layer blobs for the image, then writes and
// ServeManifest writes config and layer blobs for the image, then writes and
// redirects to the image manifest contents pointing to those blobs.
func Manifest(w http.ResponseWriter, r *http.Request, img v1.Image, also ...string) error {
if err := writeImage(img, also...); err != nil {
func (s *Storage) ServeManifest(w http.ResponseWriter, r *http.Request, img v1.Image, also ...string) error {
ctx := r.Context()
if err := s.writeImage(ctx, img, also...); err != nil {
return err
}