forked from TrueCloudLab/distribution
96 lines
2.1 KiB
Go
96 lines
2.1 KiB
Go
|
package client
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"crypto/sha1"
|
||
|
"io"
|
||
|
"io/ioutil"
|
||
|
|
||
|
"github.com/docker/docker-registry"
|
||
|
|
||
|
log "github.com/Sirupsen/logrus"
|
||
|
)
|
||
|
|
||
|
// Push implements a client push workflow for the image defined by the given
|
||
|
// name and tag pair, using the given ObjectStore for local manifest and layer
|
||
|
// storage
|
||
|
func Push(c Client, objectStore ObjectStore, name, tag string) error {
|
||
|
manifest, err := objectStore.Manifest(name, tag)
|
||
|
if err != nil {
|
||
|
log.WithFields(log.Fields{
|
||
|
"error": err,
|
||
|
"name": name,
|
||
|
"tag": tag,
|
||
|
}).Info("No image found")
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
for _, fsLayer := range manifest.FSLayers {
|
||
|
layer, err := objectStore.Layer(fsLayer.BlobSum)
|
||
|
if err != nil {
|
||
|
log.WithFields(log.Fields{
|
||
|
"error": err,
|
||
|
"layer": fsLayer,
|
||
|
}).Warn("Unable to read local layer")
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
layerReader, err := layer.Reader()
|
||
|
if err != nil {
|
||
|
log.WithFields(log.Fields{
|
||
|
"error": err,
|
||
|
"layer": fsLayer,
|
||
|
}).Warn("Unable to read local layer")
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
location, err := c.InitiateLayerUpload(name, fsLayer.BlobSum)
|
||
|
if _, ok := err.(*registry.LayerAlreadyExistsError); ok {
|
||
|
log.WithField("layer", fsLayer).Info("Layer already exists")
|
||
|
continue
|
||
|
}
|
||
|
if err != nil {
|
||
|
log.WithFields(log.Fields{
|
||
|
"error": err,
|
||
|
"layer": fsLayer,
|
||
|
}).Warn("Unable to upload layer")
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
layerBuffer := new(bytes.Buffer)
|
||
|
checksum := sha1.New()
|
||
|
teeReader := io.TeeReader(layerReader, checksum)
|
||
|
|
||
|
_, err = io.Copy(layerBuffer, teeReader)
|
||
|
if err != nil {
|
||
|
log.WithFields(log.Fields{
|
||
|
"error": err,
|
||
|
"layer": fsLayer,
|
||
|
}).Warn("Unable to read local layer")
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
err = c.UploadLayer(location, ioutil.NopCloser(layerBuffer), layerBuffer.Len(),
|
||
|
®istry.Checksum{HashAlgorithm: "sha1", Sum: string(checksum.Sum(nil))},
|
||
|
)
|
||
|
if err != nil {
|
||
|
log.WithFields(log.Fields{
|
||
|
"error": err,
|
||
|
"layer": fsLayer,
|
||
|
}).Warn("Unable to upload layer")
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
err = c.PutImageManifest(name, tag, manifest)
|
||
|
if err != nil {
|
||
|
log.WithFields(log.Fields{
|
||
|
"error": err,
|
||
|
"manifest": manifest,
|
||
|
}).Warn("Unable to upload manifest")
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|