-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #64 from stevvooe/separate-signature-storage
- Loading branch information
Showing
14 changed files
with
1,142 additions
and
252 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
package storage | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/Sirupsen/logrus" | ||
|
||
"github.com/docker/distribution/digest" | ||
"github.com/docker/distribution/storagedriver" | ||
) | ||
|
||
// TODO(stevvooe): Currently, the blobStore implementation used by the | ||
// manifest store. The layer store should be refactored to better leverage the | ||
// blobStore, reducing duplicated code. | ||
|
||
// blobStore implements a generalized blob store over a driver, supporting the | ||
// read side and link management. This object is intentionally a leaky | ||
// abstraction, providing utility methods that support creating and traversing | ||
// backend links. | ||
type blobStore struct { | ||
driver storagedriver.StorageDriver | ||
pm *pathMapper | ||
} | ||
|
||
// exists reports whether or not the path exists. If the driver returns error | ||
// other than storagedriver.PathNotFound, an error may be returned. | ||
func (bs *blobStore) exists(dgst digest.Digest) (bool, error) { | ||
path, err := bs.path(dgst) | ||
|
||
if err != nil { | ||
return false, err | ||
} | ||
|
||
ok, err := exists(bs.driver, path) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
return ok, nil | ||
} | ||
|
||
// get retrieves the blob by digest, returning it a byte slice. This should | ||
// only be used for small objects. | ||
func (bs *blobStore) get(dgst digest.Digest) ([]byte, error) { | ||
bp, err := bs.path(dgst) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return bs.driver.GetContent(bp) | ||
} | ||
|
||
// link links the path to the provided digest by writing the digest into the | ||
// target file. | ||
func (bs *blobStore) link(path string, dgst digest.Digest) error { | ||
if exists, err := bs.exists(dgst); err != nil { | ||
return err | ||
} else if !exists { | ||
return fmt.Errorf("cannot link non-existent blob") | ||
} | ||
|
||
// The contents of the "link" file are the exact string contents of the | ||
// digest, which is specified in that package. | ||
return bs.driver.PutContent(path, []byte(dgst)) | ||
} | ||
|
||
// linked reads the link at path and returns the content. | ||
func (bs *blobStore) linked(path string) ([]byte, error) { | ||
linked, err := bs.readlink(path) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return bs.get(linked) | ||
} | ||
|
||
// readlink returns the linked digest at path. | ||
func (bs *blobStore) readlink(path string) (digest.Digest, error) { | ||
content, err := bs.driver.GetContent(path) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
linked, err := digest.ParseDigest(string(content)) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
if exists, err := bs.exists(linked); err != nil { | ||
return "", err | ||
} else if !exists { | ||
return "", fmt.Errorf("link %q invalid: blob %s does not exist", path, linked) | ||
} | ||
|
||
return linked, nil | ||
} | ||
|
||
// resolve reads the digest link at path and returns the blob store link. | ||
func (bs *blobStore) resolve(path string) (string, error) { | ||
dgst, err := bs.readlink(path) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return bs.path(dgst) | ||
} | ||
|
||
// put stores the content p in the blob store, calculating the digest. If the | ||
// content is already present, only the digest will be returned. This should | ||
// only be used for small objects, such as manifests. | ||
func (bs *blobStore) put(p []byte) (digest.Digest, error) { | ||
dgst, err := digest.FromBytes(p) | ||
if err != nil { | ||
logrus.Errorf("error digesting content: %v, %s", err, string(p)) | ||
return "", err | ||
} | ||
|
||
bp, err := bs.path(dgst) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
// If the content already exists, just return the digest. | ||
if exists, err := bs.exists(dgst); err != nil { | ||
return "", err | ||
} else if exists { | ||
return dgst, nil | ||
} | ||
|
||
return dgst, bs.driver.PutContent(bp, p) | ||
} | ||
|
||
// path returns the canonical path for the blob identified by digest. The blob | ||
// may or may not exist. | ||
func (bs *blobStore) path(dgst digest.Digest) (string, error) { | ||
bp, err := bs.pm.path(blobDataPathSpec{ | ||
digest: dgst, | ||
}) | ||
|
||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return bp, nil | ||
} | ||
|
||
// exists provides a utility method to test whether or not | ||
func exists(driver storagedriver.StorageDriver, path string) (bool, error) { | ||
if _, err := driver.Stat(path); err != nil { | ||
switch err := err.(type) { | ||
case storagedriver.PathNotFoundError: | ||
return false, nil | ||
default: | ||
return false, err | ||
} | ||
} | ||
|
||
return true, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.