Vendor after merging mtrmac/image:PutBlob-error-handling

This commit is contained in:
Miloslav Trmač 2016-08-04 19:27:28 +02:00
parent 5197c8dba0
commit 6e2cd739da
7 changed files with 71 additions and 9 deletions

View File

@ -4,6 +4,7 @@ import (
"io"
"io/ioutil"
"os"
"path/filepath"
"github.com/containers/image/types"
)
@ -31,18 +32,38 @@ func (d *dirImageDestination) PutManifest(manifest []byte) error {
return ioutil.WriteFile(d.ref.manifestPath(), manifest, 0644)
}
// PutBlob writes contents of stream as a blob identified by digest.
// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
// to any other readers for download using the supplied digest.
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
// Note: Calling PutBlob() and other methods may have ordering dependencies WRT other methods of this type. FIXME: Figure out and document.
func (d *dirImageDestination) PutBlob(digest string, stream io.Reader) error {
layerFile, err := os.Create(d.ref.layerPath(digest))
blobPath := d.ref.layerPath(digest)
blobFile, err := ioutil.TempFile(filepath.Dir(blobPath), filepath.Base(blobPath))
if err != nil {
return err
}
defer layerFile.Close()
if _, err := io.Copy(layerFile, stream); err != nil {
succeeded := false
defer func() {
blobFile.Close()
if !succeeded {
os.Remove(blobFile.Name())
}
}()
if _, err := io.Copy(blobFile, stream); err != nil {
return err
}
if err := layerFile.Sync(); err != nil {
if err := blobFile.Sync(); err != nil {
return err
}
if err := blobFile.Chmod(0644); err != nil {
return err
}
if err := os.Rename(blobFile.Name(), blobPath); err != nil {
return nil
}
succeeded = true
return nil
}

View File

@ -32,13 +32,17 @@ func (t dirTransport) ParseReference(reference string) (types.ImageReference, er
// scope passed to this function will not be "", that value is always allowed.
func (t dirTransport) ValidatePolicyConfigurationScope(scope string) error {
if !strings.HasPrefix(scope, "/") {
return fmt.Errorf("Invalid scope %s: must be an absolute path", scope)
return fmt.Errorf("Invalid scope %s: Must be an absolute path", scope)
}
// Refuse also "/", otherwise "/" and "" would have the same semantics,
// and "" could be unexpectedly shadowed by the "/" entry.
if scope == "/" {
return errors.New(`Invalid scope "/": Use the generic default scope ""`)
}
cleaned := filepath.Clean(scope)
if cleaned != scope {
return fmt.Errorf(`Invalid scope %s: Uses non-canonical format, perhaps try %s`, scope, cleaned)
}
return nil
}

View File

@ -74,6 +74,11 @@ func (d *dockerImageDestination) PutManifest(m []byte) error {
return nil
}
// PutBlob writes contents of stream as a blob identified by digest.
// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
// to any other readers for download using the supplied digest.
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
// Note: Calling PutBlob() and other methods may have ordering dependencies WRT other methods of this type. FIXME: Figure out and document.
func (d *dockerImageDestination) PutBlob(digest string, stream io.Reader) error {
checkURL := fmt.Sprintf(blobsURL, d.ref.ref.RemoteName(), digest)

View File

@ -110,22 +110,41 @@ func (d *ociImageDestination) PutManifest(m []byte) error {
return ioutil.WriteFile(descriptorPath, data, 0644)
}
// PutBlob writes contents of stream as a blob identified by digest.
// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
// to any other readers for download using the supplied digest.
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
// Note: Calling PutBlob() and other methods may have ordering dependencies WRT other methods of this type. FIXME: Figure out and document.
func (d *ociImageDestination) PutBlob(digest string, stream io.Reader) error {
blobPath := d.ref.blobPath(digest)
if err := ensureParentDirectoryExists(blobPath); err != nil {
return err
}
blob, err := os.Create(blobPath)
blobFile, err := ioutil.TempFile(filepath.Dir(blobPath), filepath.Base(blobPath))
if err != nil {
return err
}
defer blob.Close()
if _, err := io.Copy(blob, stream); err != nil {
succeeded := false
defer func() {
blobFile.Close()
if !succeeded {
os.Remove(blobFile.Name())
}
}()
if _, err := io.Copy(blobFile, stream); err != nil {
return err
}
if err := blob.Sync(); err != nil {
if err := blobFile.Sync(); err != nil {
return err
}
if err := blobFile.Chmod(0644); err != nil {
return err
}
if err := os.Rename(blobFile.Name(), blobPath); err != nil {
return nil
}
succeeded = true
return nil
}

View File

@ -58,6 +58,10 @@ func (t ociTransport) ValidatePolicyConfigurationScope(scope string) error {
if scope == "/" {
return errors.New(`Invalid scope "/": Use the generic default scope ""`)
}
cleaned := filepath.Clean(dir)
if cleaned != dir {
return fmt.Errorf(`Invalid scope %s: Uses non-canonical path format, perhaps try with path %s`, scope, cleaned)
}
return nil
}

View File

@ -368,6 +368,11 @@ func (d *openshiftImageDestination) PutManifest(m []byte) error {
return nil
}
// PutBlob writes contents of stream as a blob identified by digest.
// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
// to any other readers for download using the supplied digest.
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
// Note: Calling PutBlob() and other methods may have ordering dependencies WRT other methods of this type. FIXME: Figure out and document.
func (d *openshiftImageDestination) PutBlob(digest string, stream io.Reader) error {
return d.docker.PutBlob(digest, stream)
}

View File

@ -104,6 +104,10 @@ type ImageDestination interface {
Reference() ImageReference
// FIXME? This should also receive a MIME type if known, to differentiate between schema versions.
PutManifest([]byte) error
// PutBlob writes contents of stream as a blob identified by digest.
// WARNING: The contents of stream are being verified on the fly. Until stream.Read() returns io.EOF, the contents of the data SHOULD NOT be available
// to any other readers for download using the supplied digest.
// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlob MUST 1) fail, and 2) delete any data stored so far.
// Note: Calling PutBlob() and other methods may have ordering dependencies WRT other methods of this type. FIXME: Figure out and document.
PutBlob(digest string, stream io.Reader) error
PutSignatures(signatures [][]byte) error