Add glide.yaml and vendor deps
This commit is contained in:
parent
db918f12ad
commit
5b3d5e81bd
18880 changed files with 5166045 additions and 1 deletions
111
vendor/github.com/containers/image/directory/directory_dest.go
generated
vendored
Normal file
111
vendor/github.com/containers/image/directory/directory_dest.go
generated
vendored
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
package directory
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/containers/image/types"
|
||||
)
|
||||
|
||||
type dirImageDestination struct {
|
||||
ref dirReference
|
||||
}
|
||||
|
||||
// newImageDestination returns an ImageDestination for writing to an existing directory.
|
||||
func newImageDestination(ref dirReference) types.ImageDestination {
|
||||
return &dirImageDestination{ref}
|
||||
}
|
||||
|
||||
// Reference returns the reference used to set up this destination. Note that this should directly correspond to user's intent,
|
||||
// e.g. it should use the public hostname instead of the result of resolving CNAMEs or following redirects.
|
||||
func (d *dirImageDestination) Reference() types.ImageReference {
|
||||
return d.ref
|
||||
}
|
||||
|
||||
// Close removes resources associated with an initialized ImageDestination, if any.
|
||||
func (d *dirImageDestination) Close() {
|
||||
}
|
||||
|
||||
func (d *dirImageDestination) SupportedManifestMIMETypes() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SupportsSignatures returns an error (to be displayed to the user) if the destination certainly can't store signatures.
|
||||
// Note: It is still possible for PutSignatures to fail if SupportsSignatures returns nil.
|
||||
func (d *dirImageDestination) SupportsSignatures() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ShouldCompressLayers returns true iff it is desirable to compress layer blobs written to this destination.
|
||||
func (d *dirImageDestination) ShouldCompressLayers() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// PutBlob writes contents of stream and returns data representing the result (with all data filled in).
|
||||
// inputInfo.Digest can be optionally provided if known; it is not mandatory for the implementation to verify it.
|
||||
// inputInfo.Size is the expected length of stream, if known.
|
||||
// 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.
|
||||
func (d *dirImageDestination) PutBlob(stream io.Reader, inputInfo types.BlobInfo) (types.BlobInfo, error) {
|
||||
blobFile, err := ioutil.TempFile(d.ref.path, "dir-put-blob")
|
||||
if err != nil {
|
||||
return types.BlobInfo{}, err
|
||||
}
|
||||
succeeded := false
|
||||
defer func() {
|
||||
blobFile.Close()
|
||||
if !succeeded {
|
||||
os.Remove(blobFile.Name())
|
||||
}
|
||||
}()
|
||||
|
||||
h := sha256.New()
|
||||
tee := io.TeeReader(stream, h)
|
||||
|
||||
size, err := io.Copy(blobFile, tee)
|
||||
if err != nil {
|
||||
return types.BlobInfo{}, err
|
||||
}
|
||||
computedDigest := hex.EncodeToString(h.Sum(nil))
|
||||
if inputInfo.Size != -1 && size != inputInfo.Size {
|
||||
return types.BlobInfo{}, fmt.Errorf("Size mismatch when copying %s, expected %d, got %d", computedDigest, inputInfo.Size, size)
|
||||
}
|
||||
if err := blobFile.Sync(); err != nil {
|
||||
return types.BlobInfo{}, err
|
||||
}
|
||||
if err := blobFile.Chmod(0644); err != nil {
|
||||
return types.BlobInfo{}, err
|
||||
}
|
||||
blobPath := d.ref.layerPath(computedDigest)
|
||||
if err := os.Rename(blobFile.Name(), blobPath); err != nil {
|
||||
return types.BlobInfo{}, err
|
||||
}
|
||||
succeeded = true
|
||||
return types.BlobInfo{Digest: "sha256:" + computedDigest, Size: size}, nil
|
||||
}
|
||||
|
||||
func (d *dirImageDestination) PutManifest(manifest []byte) error {
|
||||
return ioutil.WriteFile(d.ref.manifestPath(), manifest, 0644)
|
||||
}
|
||||
|
||||
func (d *dirImageDestination) PutSignatures(signatures [][]byte) error {
|
||||
for i, sig := range signatures {
|
||||
if err := ioutil.WriteFile(d.ref.signaturePath(i), sig, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Commit marks the process of storing the image as successful and asks for the image to be persisted.
|
||||
// WARNING: This does not have any transactional semantics:
|
||||
// - Uploaded data MAY be visible to others before Commit() is called
|
||||
// - Uploaded data MAY be removed or MAY remain around if Close() is called without Commit() (i.e. rollback is allowed but not guaranteed)
|
||||
func (d *dirImageDestination) Commit() error {
|
||||
return nil
|
||||
}
|
||||
73
vendor/github.com/containers/image/directory/directory_src.go
generated
vendored
Normal file
73
vendor/github.com/containers/image/directory/directory_src.go
generated
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
package directory
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/containers/image/manifest"
|
||||
"github.com/containers/image/types"
|
||||
)
|
||||
|
||||
type dirImageSource struct {
|
||||
ref dirReference
|
||||
}
|
||||
|
||||
// newImageSource returns an ImageSource reading from an existing directory.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func newImageSource(ref dirReference) types.ImageSource {
|
||||
return &dirImageSource{ref}
|
||||
}
|
||||
|
||||
// Reference returns the reference used to set up this source, _as specified by the user_
|
||||
// (not as the image itself, or its underlying storage, claims). This can be used e.g. to determine which public keys are trusted for this image.
|
||||
func (s *dirImageSource) Reference() types.ImageReference {
|
||||
return s.ref
|
||||
}
|
||||
|
||||
// Close removes resources associated with an initialized ImageSource, if any.
|
||||
func (s *dirImageSource) Close() {
|
||||
}
|
||||
|
||||
// GetManifest returns the image's manifest along with its MIME type (which may be empty when it can't be determined but the manifest is available).
|
||||
// It may use a remote (= slow) service.
|
||||
func (s *dirImageSource) GetManifest() ([]byte, string, error) {
|
||||
m, err := ioutil.ReadFile(s.ref.manifestPath())
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return m, manifest.GuessMIMEType(m), err
|
||||
}
|
||||
|
||||
func (s *dirImageSource) GetTargetManifest(digest string) ([]byte, string, error) {
|
||||
return nil, "", fmt.Errorf("Getting target manifest not supported by dir:")
|
||||
}
|
||||
|
||||
// GetBlob returns a stream for the specified blob, and the blob’s size (or -1 if unknown).
|
||||
func (s *dirImageSource) GetBlob(digest string) (io.ReadCloser, int64, error) {
|
||||
r, err := os.Open(s.ref.layerPath(digest))
|
||||
if err != nil {
|
||||
return nil, 0, nil
|
||||
}
|
||||
fi, err := r.Stat()
|
||||
if err != nil {
|
||||
return nil, 0, nil
|
||||
}
|
||||
return r, fi.Size(), nil
|
||||
}
|
||||
|
||||
func (s *dirImageSource) GetSignatures() ([][]byte, error) {
|
||||
signatures := [][]byte{}
|
||||
for i := 0; ; i++ {
|
||||
signature, err := ioutil.ReadFile(s.ref.signaturePath(i))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
break
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
signatures = append(signatures, signature)
|
||||
}
|
||||
return signatures, nil
|
||||
}
|
||||
165
vendor/github.com/containers/image/directory/directory_test.go
generated
vendored
Normal file
165
vendor/github.com/containers/image/directory/directory_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
package directory
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/containers/image/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDestinationReference(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
dest, err := ref.NewImageDestination(nil)
|
||||
require.NoError(t, err)
|
||||
defer dest.Close()
|
||||
ref2 := dest.Reference()
|
||||
assert.Equal(t, tmpDir, ref2.StringWithinTransport())
|
||||
}
|
||||
|
||||
func TestGetPutManifest(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
man := []byte("test-manifest")
|
||||
dest, err := ref.NewImageDestination(nil)
|
||||
require.NoError(t, err)
|
||||
defer dest.Close()
|
||||
err = dest.PutManifest(man)
|
||||
assert.NoError(t, err)
|
||||
err = dest.Commit()
|
||||
assert.NoError(t, err)
|
||||
|
||||
src, err := ref.NewImageSource(nil, nil)
|
||||
require.NoError(t, err)
|
||||
defer src.Close()
|
||||
m, mt, err := src.GetManifest()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, man, m)
|
||||
assert.Equal(t, "", mt)
|
||||
}
|
||||
|
||||
func TestGetPutBlob(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
digest := "digest-test"
|
||||
blob := []byte("test-blob")
|
||||
dest, err := ref.NewImageDestination(nil)
|
||||
require.NoError(t, err)
|
||||
defer dest.Close()
|
||||
compress := dest.ShouldCompressLayers()
|
||||
assert.False(t, compress)
|
||||
info, err := dest.PutBlob(bytes.NewReader(blob), types.BlobInfo{Digest: digest, Size: int64(9)})
|
||||
assert.NoError(t, err)
|
||||
err = dest.Commit()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(9), info.Size)
|
||||
hash := sha256.Sum256(blob)
|
||||
assert.Equal(t, "sha256:"+hex.EncodeToString(hash[:]), info.Digest)
|
||||
|
||||
src, err := ref.NewImageSource(nil, nil)
|
||||
require.NoError(t, err)
|
||||
defer src.Close()
|
||||
rc, size, err := src.GetBlob(info.Digest)
|
||||
assert.NoError(t, err)
|
||||
defer rc.Close()
|
||||
b, err := ioutil.ReadAll(rc)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, blob, b)
|
||||
assert.Equal(t, int64(len(blob)), size)
|
||||
}
|
||||
|
||||
// readerFromFunc allows implementing Reader by any function, e.g. a closure.
|
||||
type readerFromFunc func([]byte) (int, error)
|
||||
|
||||
func (fn readerFromFunc) Read(p []byte) (int, error) {
|
||||
return fn(p)
|
||||
}
|
||||
|
||||
// TestPutBlobDigestFailure simulates behavior on digest verification failure.
|
||||
func TestPutBlobDigestFailure(t *testing.T) {
|
||||
const digestErrorString = "Simulated digest error"
|
||||
const blobDigest = "test-digest"
|
||||
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
dirRef, ok := ref.(dirReference)
|
||||
require.True(t, ok)
|
||||
blobPath := dirRef.layerPath(blobDigest)
|
||||
|
||||
firstRead := true
|
||||
reader := readerFromFunc(func(p []byte) (int, error) {
|
||||
_, err := os.Lstat(blobPath)
|
||||
require.Error(t, err)
|
||||
require.True(t, os.IsNotExist(err))
|
||||
if firstRead {
|
||||
if len(p) > 0 {
|
||||
firstRead = false
|
||||
}
|
||||
for i := 0; i < len(p); i++ {
|
||||
p[i] = 0xAA
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
return 0, fmt.Errorf(digestErrorString)
|
||||
})
|
||||
|
||||
dest, err := ref.NewImageDestination(nil)
|
||||
require.NoError(t, err)
|
||||
defer dest.Close()
|
||||
_, err = dest.PutBlob(reader, types.BlobInfo{Digest: blobDigest, Size: -1})
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, digestErrorString, err.Error())
|
||||
err = dest.Commit()
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = os.Lstat(blobPath)
|
||||
require.Error(t, err)
|
||||
require.True(t, os.IsNotExist(err))
|
||||
}
|
||||
|
||||
func TestGetPutSignatures(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
dest, err := ref.NewImageDestination(nil)
|
||||
require.NoError(t, err)
|
||||
defer dest.Close()
|
||||
signatures := [][]byte{
|
||||
[]byte("sig1"),
|
||||
[]byte("sig2"),
|
||||
}
|
||||
err = dest.SupportsSignatures()
|
||||
assert.NoError(t, err)
|
||||
err = dest.PutSignatures(signatures)
|
||||
assert.NoError(t, err)
|
||||
err = dest.Commit()
|
||||
assert.NoError(t, err)
|
||||
|
||||
src, err := ref.NewImageSource(nil, nil)
|
||||
require.NoError(t, err)
|
||||
defer src.Close()
|
||||
sigs, err := src.GetSignatures()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, signatures, sigs)
|
||||
}
|
||||
|
||||
func TestSourceReference(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
src, err := ref.NewImageSource(nil, nil)
|
||||
require.NoError(t, err)
|
||||
defer src.Close()
|
||||
ref2 := src.Reference()
|
||||
assert.Equal(t, tmpDir, ref2.StringWithinTransport())
|
||||
}
|
||||
172
vendor/github.com/containers/image/directory/directory_transport.go
generated
vendored
Normal file
172
vendor/github.com/containers/image/directory/directory_transport.go
generated
vendored
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
package directory
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/image/directory/explicitfilepath"
|
||||
"github.com/containers/image/docker/reference"
|
||||
"github.com/containers/image/image"
|
||||
"github.com/containers/image/types"
|
||||
)
|
||||
|
||||
// Transport is an ImageTransport for directory paths.
|
||||
var Transport = dirTransport{}
|
||||
|
||||
type dirTransport struct{}
|
||||
|
||||
func (t dirTransport) Name() string {
|
||||
return "dir"
|
||||
}
|
||||
|
||||
// ParseReference converts a string, which should not start with the ImageTransport.Name prefix, into an ImageReference.
|
||||
func (t dirTransport) ParseReference(reference string) (types.ImageReference, error) {
|
||||
return NewReference(reference)
|
||||
}
|
||||
|
||||
// ValidatePolicyConfigurationScope checks that scope is a valid name for a signature.PolicyTransportScopes keys
|
||||
// (i.e. a valid PolicyConfigurationIdentity() or PolicyConfigurationNamespaces() return value).
|
||||
// It is acceptable to allow an invalid value which will never be matched, it can "only" cause user confusion.
|
||||
// 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)
|
||||
}
|
||||
// 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
|
||||
}
|
||||
|
||||
// dirReference is an ImageReference for directory paths.
|
||||
type dirReference struct {
|
||||
// Note that the interpretation of paths below depends on the underlying filesystem state, which may change under us at any time!
|
||||
// Either of the paths may point to a different, or no, inode over time. resolvedPath may contain symbolic links, and so on.
|
||||
|
||||
// Generally we follow the intent of the user, and use the "path" member for filesystem operations (e.g. the user can use a relative path to avoid
|
||||
// being exposed to symlinks and renames in the parent directories to the working directory).
|
||||
// (But in general, we make no attempt to be completely safe against concurrent hostile filesystem modifications.)
|
||||
path string // As specified by the user. May be relative, contain symlinks, etc.
|
||||
resolvedPath string // Absolute path with no symlinks, at least at the time of its creation. Primarily used for policy namespaces.
|
||||
}
|
||||
|
||||
// There is no directory.ParseReference because it is rather pointless.
|
||||
// Callers who need a transport-independent interface will go through
|
||||
// dirTransport.ParseReference; callers who intentionally deal with directories
|
||||
// can use directory.NewReference.
|
||||
|
||||
// NewReference returns a directory reference for a specified path.
|
||||
//
|
||||
// We do not expose an API supplying the resolvedPath; we could, but recomputing it
|
||||
// is generally cheap enough that we prefer being confident about the properties of resolvedPath.
|
||||
func NewReference(path string) (types.ImageReference, error) {
|
||||
resolved, err := explicitfilepath.ResolvePathToFullyExplicit(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dirReference{path: path, resolvedPath: resolved}, nil
|
||||
}
|
||||
|
||||
func (ref dirReference) Transport() types.ImageTransport {
|
||||
return Transport
|
||||
}
|
||||
|
||||
// StringWithinTransport returns a string representation of the reference, which MUST be such that
|
||||
// reference.Transport().ParseReference(reference.StringWithinTransport()) returns an equivalent reference.
|
||||
// NOTE: The returned string is not promised to be equal to the original input to ParseReference;
|
||||
// e.g. default attribute values omitted by the user may be filled in in the return value, or vice versa.
|
||||
// WARNING: Do not use the return value in the UI to describe an image, it does not contain the Transport().Name() prefix.
|
||||
func (ref dirReference) StringWithinTransport() string {
|
||||
return ref.path
|
||||
}
|
||||
|
||||
// DockerReference returns a Docker reference associated with this reference
|
||||
// (fully explicit, i.e. !reference.IsNameOnly, but reflecting user intent,
|
||||
// not e.g. after redirect or alias processing), or nil if unknown/not applicable.
|
||||
func (ref dirReference) DockerReference() reference.Named {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PolicyConfigurationIdentity returns a string representation of the reference, suitable for policy lookup.
|
||||
// This MUST reflect user intent, not e.g. after processing of third-party redirects or aliases;
|
||||
// The value SHOULD be fully explicit about its semantics, with no hidden defaults, AND canonical
|
||||
// (i.e. various references with exactly the same semantics should return the same configuration identity)
|
||||
// It is fine for the return value to be equal to StringWithinTransport(), and it is desirable but
|
||||
// not required/guaranteed that it will be a valid input to Transport().ParseReference().
|
||||
// Returns "" if configuration identities for these references are not supported.
|
||||
func (ref dirReference) PolicyConfigurationIdentity() string {
|
||||
return ref.resolvedPath
|
||||
}
|
||||
|
||||
// PolicyConfigurationNamespaces returns a list of other policy configuration namespaces to search
|
||||
// for if explicit configuration for PolicyConfigurationIdentity() is not set. The list will be processed
|
||||
// in order, terminating on first match, and an implicit "" is always checked at the end.
|
||||
// It is STRONGLY recommended for the first element, if any, to be a prefix of PolicyConfigurationIdentity(),
|
||||
// and each following element to be a prefix of the element preceding it.
|
||||
func (ref dirReference) PolicyConfigurationNamespaces() []string {
|
||||
res := []string{}
|
||||
path := ref.resolvedPath
|
||||
for {
|
||||
lastSlash := strings.LastIndex(path, "/")
|
||||
if lastSlash == -1 || lastSlash == 0 {
|
||||
break
|
||||
}
|
||||
path = path[:lastSlash]
|
||||
res = append(res, path)
|
||||
}
|
||||
// Note that we do not include "/"; it is redundant with the default "" global default,
|
||||
// and rejected by dirTransport.ValidatePolicyConfigurationScope above.
|
||||
return res
|
||||
}
|
||||
|
||||
// NewImage returns a types.Image for this reference, possibly specialized for this ImageTransport.
|
||||
// The caller must call .Close() on the returned Image.
|
||||
// NOTE: If any kind of signature verification should happen, build an UnparsedImage from the value returned by NewImageSource,
|
||||
// verify that UnparsedImage, and convert it into a real Image via image.FromUnparsedImage.
|
||||
func (ref dirReference) NewImage(ctx *types.SystemContext) (types.Image, error) {
|
||||
src := newImageSource(ref)
|
||||
return image.FromSource(src)
|
||||
}
|
||||
|
||||
// NewImageSource returns a types.ImageSource for this reference,
|
||||
// asking the backend to use a manifest from requestedManifestMIMETypes if possible.
|
||||
// nil requestedManifestMIMETypes means manifest.DefaultRequestedManifestMIMETypes.
|
||||
// The caller must call .Close() on the returned ImageSource.
|
||||
func (ref dirReference) NewImageSource(ctx *types.SystemContext, requestedManifestMIMETypes []string) (types.ImageSource, error) {
|
||||
return newImageSource(ref), nil
|
||||
}
|
||||
|
||||
// NewImageDestination returns a types.ImageDestination for this reference.
|
||||
// The caller must call .Close() on the returned ImageDestination.
|
||||
func (ref dirReference) NewImageDestination(ctx *types.SystemContext) (types.ImageDestination, error) {
|
||||
return newImageDestination(ref), nil
|
||||
}
|
||||
|
||||
// DeleteImage deletes the named image from the registry, if supported.
|
||||
func (ref dirReference) DeleteImage(ctx *types.SystemContext) error {
|
||||
return fmt.Errorf("Deleting images not implemented for dir: images")
|
||||
}
|
||||
|
||||
// manifestPath returns a path for the manifest within a directory using our conventions.
|
||||
func (ref dirReference) manifestPath() string {
|
||||
return filepath.Join(ref.path, "manifest.json")
|
||||
}
|
||||
|
||||
// layerPath returns a path for a layer tarball within a directory using our conventions.
|
||||
func (ref dirReference) layerPath(digest string) string {
|
||||
// FIXME: Should we keep the digest identification?
|
||||
return filepath.Join(ref.path, strings.TrimPrefix(digest, "sha256:")+".tar")
|
||||
}
|
||||
|
||||
// signaturePath returns a path for a signature within a directory using our conventions.
|
||||
func (ref dirReference) signaturePath(index int) string {
|
||||
return filepath.Join(ref.path, fmt.Sprintf("signature-%d", index+1))
|
||||
}
|
||||
232
vendor/github.com/containers/image/directory/directory_transport_test.go
generated
vendored
Normal file
232
vendor/github.com/containers/image/directory/directory_transport_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
package directory
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/containers/image/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTransportName(t *testing.T) {
|
||||
assert.Equal(t, "dir", Transport.Name())
|
||||
}
|
||||
|
||||
func TestTransportParseReference(t *testing.T) {
|
||||
testNewReference(t, Transport.ParseReference)
|
||||
}
|
||||
|
||||
func TestTransportValidatePolicyConfigurationScope(t *testing.T) {
|
||||
for _, scope := range []string{
|
||||
"/etc",
|
||||
"/this/does/not/exist",
|
||||
} {
|
||||
err := Transport.ValidatePolicyConfigurationScope(scope)
|
||||
assert.NoError(t, err, scope)
|
||||
}
|
||||
|
||||
for _, scope := range []string{
|
||||
"relative/path",
|
||||
"/double//slashes",
|
||||
"/has/./dot",
|
||||
"/has/dot/../dot",
|
||||
"/trailing/slash/",
|
||||
"/",
|
||||
} {
|
||||
err := Transport.ValidatePolicyConfigurationScope(scope)
|
||||
assert.Error(t, err, scope)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewReference(t *testing.T) {
|
||||
testNewReference(t, NewReference)
|
||||
}
|
||||
|
||||
// testNewReference is a test shared for Transport.ParseReference and NewReference.
|
||||
func testNewReference(t *testing.T, fn func(string) (types.ImageReference, error)) {
|
||||
tmpDir, err := ioutil.TempDir("", "dir-transport-test")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
for _, path := range []string{
|
||||
"/",
|
||||
"/etc",
|
||||
tmpDir,
|
||||
"relativepath",
|
||||
tmpDir + "/thisdoesnotexist",
|
||||
} {
|
||||
ref, err := fn(path)
|
||||
require.NoError(t, err, path)
|
||||
dirRef, ok := ref.(dirReference)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, path, dirRef.path, path)
|
||||
}
|
||||
|
||||
_, err = fn(tmpDir + "/thisparentdoesnotexist/something")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
// refToTempDir creates a temporary directory and returns a reference to it.
|
||||
// The caller should
|
||||
// defer os.RemoveAll(tmpDir)
|
||||
func refToTempDir(t *testing.T) (ref types.ImageReference, tmpDir string) {
|
||||
tmpDir, err := ioutil.TempDir("", "dir-transport-test")
|
||||
require.NoError(t, err)
|
||||
ref, err = NewReference(tmpDir)
|
||||
require.NoError(t, err)
|
||||
return ref, tmpDir
|
||||
}
|
||||
|
||||
func TestReferenceTransport(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
assert.Equal(t, Transport, ref.Transport())
|
||||
}
|
||||
|
||||
func TestReferenceStringWithinTransport(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
assert.Equal(t, tmpDir, ref.StringWithinTransport())
|
||||
}
|
||||
|
||||
func TestReferenceDockerReference(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
assert.Nil(t, ref.DockerReference())
|
||||
}
|
||||
|
||||
func TestReferencePolicyConfigurationIdentity(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
assert.Equal(t, tmpDir, ref.PolicyConfigurationIdentity())
|
||||
// A non-canonical path. Test just one, the various other cases are
|
||||
// tested in explicitfilepath.ResolvePathToFullyExplicit.
|
||||
ref, err := NewReference(tmpDir + "/.")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tmpDir, ref.PolicyConfigurationIdentity())
|
||||
|
||||
// "/" as a corner case.
|
||||
ref, err = NewReference("/")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "/", ref.PolicyConfigurationIdentity())
|
||||
}
|
||||
|
||||
func TestReferencePolicyConfigurationNamespaces(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
// We don't really know enough to make a full equality test here.
|
||||
ns := ref.PolicyConfigurationNamespaces()
|
||||
require.NotNil(t, ns)
|
||||
assert.NotEmpty(t, ns)
|
||||
assert.Equal(t, filepath.Dir(tmpDir), ns[0])
|
||||
|
||||
// Test with a known path which should exist. Test just one non-canonical
|
||||
// path, the various other cases are tested in explicitfilepath.ResolvePathToFullyExplicit.
|
||||
//
|
||||
// It would be nice to test a deeper hierarchy, but it is not obvious what
|
||||
// deeper path is always available in the various distros, AND is not likely
|
||||
// to contains a symbolic link.
|
||||
for _, path := range []string{"/etc/skel", "/etc/skel/./."} {
|
||||
_, err := os.Lstat(path)
|
||||
require.NoError(t, err)
|
||||
ref, err := NewReference(path)
|
||||
require.NoError(t, err)
|
||||
ns := ref.PolicyConfigurationNamespaces()
|
||||
require.NotNil(t, ns)
|
||||
assert.Equal(t, []string{"/etc"}, ns)
|
||||
}
|
||||
|
||||
// "/" as a corner case.
|
||||
ref, err := NewReference("/")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []string{}, ref.PolicyConfigurationNamespaces())
|
||||
}
|
||||
|
||||
func TestReferenceNewImage(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
dest, err := ref.NewImageDestination(nil)
|
||||
require.NoError(t, err)
|
||||
defer dest.Close()
|
||||
mFixture, err := ioutil.ReadFile("../manifest/fixtures/v2s1.manifest.json")
|
||||
require.NoError(t, err)
|
||||
err = dest.PutManifest(mFixture)
|
||||
assert.NoError(t, err)
|
||||
err = dest.Commit()
|
||||
assert.NoError(t, err)
|
||||
|
||||
img, err := ref.NewImage(nil)
|
||||
assert.NoError(t, err)
|
||||
defer img.Close()
|
||||
}
|
||||
|
||||
func TestReferenceNewImageNoValidManifest(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
dest, err := ref.NewImageDestination(nil)
|
||||
require.NoError(t, err)
|
||||
defer dest.Close()
|
||||
err = dest.PutManifest([]byte(`{"schemaVersion":1}`))
|
||||
assert.NoError(t, err)
|
||||
err = dest.Commit()
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = ref.NewImage(nil)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestReferenceNewImageSource(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
src, err := ref.NewImageSource(nil, nil)
|
||||
assert.NoError(t, err)
|
||||
defer src.Close()
|
||||
}
|
||||
|
||||
func TestReferenceNewImageDestination(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
dest, err := ref.NewImageDestination(nil)
|
||||
assert.NoError(t, err)
|
||||
defer dest.Close()
|
||||
}
|
||||
|
||||
func TestReferenceDeleteImage(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
err := ref.DeleteImage(nil)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestReferenceManifestPath(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
dirRef, ok := ref.(dirReference)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, tmpDir+"/manifest.json", dirRef.manifestPath())
|
||||
}
|
||||
|
||||
func TestReferenceLayerPath(t *testing.T) {
|
||||
const hex = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
dirRef, ok := ref.(dirReference)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, tmpDir+"/"+hex+".tar", dirRef.layerPath("sha256:"+hex))
|
||||
}
|
||||
|
||||
func TestReferenceSignaturePath(t *testing.T) {
|
||||
ref, tmpDir := refToTempDir(t)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
dirRef, ok := ref.(dirReference)
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, tmpDir+"/signature-1", dirRef.signaturePath(0))
|
||||
assert.Equal(t, tmpDir+"/signature-10", dirRef.signaturePath(9))
|
||||
}
|
||||
55
vendor/github.com/containers/image/directory/explicitfilepath/path.go
generated
vendored
Normal file
55
vendor/github.com/containers/image/directory/explicitfilepath/path.go
generated
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package explicitfilepath
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// ResolvePathToFullyExplicit returns the input path converted to an absolute, no-symlinks, cleaned up path.
|
||||
// To do so, all elements of the input path must exist; as a special case, the final component may be
|
||||
// a non-existent name (but not a symlink pointing to a non-existent name)
|
||||
// This is intended as a a helper for implementations of types.ImageReference.PolicyConfigurationIdentity etc.
|
||||
func ResolvePathToFullyExplicit(path string) (string, error) {
|
||||
switch _, err := os.Lstat(path); {
|
||||
case err == nil:
|
||||
return resolveExistingPathToFullyExplicit(path)
|
||||
case os.IsNotExist(err):
|
||||
parent, file := filepath.Split(path)
|
||||
resolvedParent, err := resolveExistingPathToFullyExplicit(parent)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if file == "." || file == ".." {
|
||||
// Coverage: This can happen, but very rarely: if we have successfully resolved the parent, both "." and ".." in it should have been resolved as well.
|
||||
// This can still happen if there is a filesystem race condition, causing the Lstat() above to fail but the later resolution to succeed.
|
||||
// We do not care to promise anything if such filesystem race conditions can happen, but we definitely don't want to return "."/".." components
|
||||
// in the resulting path, and especially not at the end.
|
||||
return "", fmt.Errorf("Unexpectedly missing special filename component in %s", path)
|
||||
}
|
||||
resolvedPath := filepath.Join(resolvedParent, file)
|
||||
// As a sanity check, ensure that there are no "." or ".." components.
|
||||
cleanedResolvedPath := filepath.Clean(resolvedPath)
|
||||
if cleanedResolvedPath != resolvedPath {
|
||||
// Coverage: This should never happen.
|
||||
return "", fmt.Errorf("Internal inconsistency: Path %s resolved to %s still cleaned up to %s", path, resolvedPath, cleanedResolvedPath)
|
||||
}
|
||||
return resolvedPath, nil
|
||||
default: // err != nil, unrecognized
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
// resolveExistingPathToFullyExplicit is the same as ResolvePathToFullyExplicit,
|
||||
// but without the special case for missing final component.
|
||||
func resolveExistingPathToFullyExplicit(path string) (string, error) {
|
||||
resolved, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return "", err // Coverage: This can fail only if os.Getwd() fails.
|
||||
}
|
||||
resolved, err = filepath.EvalSymlinks(resolved)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Clean(resolved), nil
|
||||
}
|
||||
173
vendor/github.com/containers/image/directory/explicitfilepath/path_test.go
generated
vendored
Normal file
173
vendor/github.com/containers/image/directory/explicitfilepath/path_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
package explicitfilepath
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type pathResolvingTestCase struct {
|
||||
setup func(*testing.T, string) string
|
||||
expected string
|
||||
}
|
||||
|
||||
var testCases = []pathResolvingTestCase{
|
||||
{ // A straightforward subdirectory hierarchy
|
||||
func(t *testing.T, top string) string {
|
||||
err := os.MkdirAll(filepath.Join(top, "dir1/dir2/dir3"), 0755)
|
||||
require.NoError(t, err)
|
||||
return "dir1/dir2/dir3"
|
||||
},
|
||||
"dir1/dir2/dir3",
|
||||
},
|
||||
{ // Missing component
|
||||
func(t *testing.T, top string) string {
|
||||
return "thisismissing/dir2"
|
||||
},
|
||||
"",
|
||||
},
|
||||
{ // Symlink on the path
|
||||
func(t *testing.T, top string) string {
|
||||
err := os.MkdirAll(filepath.Join(top, "dir1/dir2"), 0755)
|
||||
require.NoError(t, err)
|
||||
err = os.Symlink("dir1", filepath.Join(top, "link1"))
|
||||
require.NoError(t, err)
|
||||
return "link1/dir2"
|
||||
},
|
||||
"dir1/dir2",
|
||||
},
|
||||
{ // Trailing symlink
|
||||
func(t *testing.T, top string) string {
|
||||
err := os.MkdirAll(filepath.Join(top, "dir1/dir2"), 0755)
|
||||
require.NoError(t, err)
|
||||
err = os.Symlink("dir2", filepath.Join(top, "dir1/link2"))
|
||||
require.NoError(t, err)
|
||||
return "dir1/link2"
|
||||
},
|
||||
"dir1/dir2",
|
||||
},
|
||||
{ // Symlink pointing nowhere, as a non-final component
|
||||
func(t *testing.T, top string) string {
|
||||
err := os.Symlink("thisismissing", filepath.Join(top, "link1"))
|
||||
require.NoError(t, err)
|
||||
return "link1/dir2"
|
||||
},
|
||||
"",
|
||||
},
|
||||
{ // Trailing symlink pointing nowhere (but note that a missing non-symlink would be accepted)
|
||||
func(t *testing.T, top string) string {
|
||||
err := os.Symlink("thisismissing", filepath.Join(top, "link1"))
|
||||
require.NoError(t, err)
|
||||
return "link1"
|
||||
},
|
||||
"",
|
||||
},
|
||||
{ // Relative components in a path
|
||||
func(t *testing.T, top string) string {
|
||||
err := os.MkdirAll(filepath.Join(top, "dir1/dir2/dir3"), 0755)
|
||||
require.NoError(t, err)
|
||||
return "dir1/./dir2/../dir2/dir3"
|
||||
},
|
||||
"dir1/dir2/dir3",
|
||||
},
|
||||
{ // Trailing relative components
|
||||
func(t *testing.T, top string) string {
|
||||
err := os.MkdirAll(filepath.Join(top, "dir1/dir2"), 0755)
|
||||
require.NoError(t, err)
|
||||
return "dir1/dir2/.."
|
||||
},
|
||||
"dir1",
|
||||
},
|
||||
{ // Relative components in symlink
|
||||
func(t *testing.T, top string) string {
|
||||
err := os.MkdirAll(filepath.Join(top, "dir1/dir2"), 0755)
|
||||
require.NoError(t, err)
|
||||
err = os.Symlink("../dir1/dir2", filepath.Join(top, "dir1/link2"))
|
||||
require.NoError(t, err)
|
||||
return "dir1/link2"
|
||||
},
|
||||
"dir1/dir2",
|
||||
},
|
||||
{ // Relative component pointing "into" a symlink
|
||||
func(t *testing.T, top string) string {
|
||||
err := os.MkdirAll(filepath.Join(top, "dir1/dir2/dir3"), 0755)
|
||||
require.NoError(t, err)
|
||||
err = os.Symlink("dir3", filepath.Join(top, "dir1/dir2/link3"))
|
||||
require.NoError(t, err)
|
||||
return "dir1/dir2/link3/../.."
|
||||
},
|
||||
"dir1",
|
||||
},
|
||||
{ // Unreadable directory
|
||||
func(t *testing.T, top string) string {
|
||||
err := os.MkdirAll(filepath.Join(top, "unreadable/dir2"), 0755)
|
||||
require.NoError(t, err)
|
||||
err = os.Chmod(filepath.Join(top, "unreadable"), 000)
|
||||
require.NoError(t, err)
|
||||
return "unreadable/dir2"
|
||||
},
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
func testPathsAreSameFile(t *testing.T, path1, path2, description string) {
|
||||
fi1, err := os.Stat(path1)
|
||||
require.NoError(t, err)
|
||||
fi2, err := os.Stat(path2)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, os.SameFile(fi1, fi2), description)
|
||||
}
|
||||
|
||||
func runPathResolvingTestCase(t *testing.T, f func(string) (string, error), c pathResolvingTestCase, suffix string) {
|
||||
topDir, err := ioutil.TempDir("", "pathResolving")
|
||||
defer func() {
|
||||
// Clean up after the "Unreadable directory" case; os.RemoveAll just fails.
|
||||
_ = os.Chmod(filepath.Join(topDir, "unreadable"), 0755) // Ignore errors, especially if this does not exist.
|
||||
os.RemoveAll(topDir)
|
||||
}()
|
||||
|
||||
input := c.setup(t, topDir) + suffix // Do not call filepath.Join() on input, it calls filepath.Clean() internally!
|
||||
description := fmt.Sprintf("%s vs. %s%s", input, c.expected, suffix)
|
||||
|
||||
fullOutput, err := ResolvePathToFullyExplicit(topDir + "/" + input)
|
||||
if c.expected == "" {
|
||||
assert.Error(t, err, description)
|
||||
} else {
|
||||
require.NoError(t, err, input)
|
||||
fullExpected := topDir + "/" + c.expected + suffix
|
||||
assert.Equal(t, fullExpected, fullOutput)
|
||||
|
||||
// Either the two paths resolve to the same existing file, or to the same name in the same existing parent.
|
||||
if _, err := os.Lstat(fullExpected); err == nil {
|
||||
testPathsAreSameFile(t, fullOutput, fullExpected, description)
|
||||
} else {
|
||||
require.True(t, os.IsNotExist(err))
|
||||
_, err := os.Stat(fullOutput)
|
||||
require.Error(t, err)
|
||||
require.True(t, os.IsNotExist(err))
|
||||
|
||||
parentExpected, fileExpected := filepath.Split(fullExpected)
|
||||
parentOutput, fileOutput := filepath.Split(fullOutput)
|
||||
assert.Equal(t, fileExpected, fileOutput)
|
||||
testPathsAreSameFile(t, parentOutput, parentExpected, description)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolvePathToFullyExplicit(t *testing.T) {
|
||||
for _, c := range testCases {
|
||||
runPathResolvingTestCase(t, ResolvePathToFullyExplicit, c, "")
|
||||
runPathResolvingTestCase(t, ResolvePathToFullyExplicit, c, "/trailing")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveExistingPathToFullyExplicit(t *testing.T) {
|
||||
for _, c := range testCases {
|
||||
runPathResolvingTestCase(t, resolveExistingPathToFullyExplicit, c, "")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue