github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+incompatible/registry/storage/manifeststore.go (about)

     1  package storage
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"encoding/json"
     7  	"github.com/docker/distribution"
     8  	"github.com/docker/distribution/context"
     9  	"github.com/docker/distribution/digest"
    10  	"github.com/docker/distribution/manifest"
    11  	"github.com/docker/distribution/manifest/manifestlist"
    12  	"github.com/docker/distribution/manifest/schema1"
    13  	"github.com/docker/distribution/manifest/schema2"
    14  )
    15  
    16  // A ManifestHandler gets and puts manifests of a particular type.
    17  type ManifestHandler interface {
    18  	// Unmarshal unmarshals the manifest from a byte slice.
    19  	Unmarshal(ctx context.Context, dgst digest.Digest, content []byte) (distribution.Manifest, error)
    20  
    21  	// Put creates or updates the given manifest returning the manifest digest.
    22  	Put(ctx context.Context, manifest distribution.Manifest, skipDependencyVerification bool) (digest.Digest, error)
    23  }
    24  
    25  // SkipLayerVerification allows a manifest to be Put before its
    26  // layers are on the filesystem
    27  func SkipLayerVerification() distribution.ManifestServiceOption {
    28  	return skipLayerOption{}
    29  }
    30  
    31  type skipLayerOption struct{}
    32  
    33  func (o skipLayerOption) Apply(m distribution.ManifestService) error {
    34  	if ms, ok := m.(*manifestStore); ok {
    35  		ms.skipDependencyVerification = true
    36  		return nil
    37  	}
    38  	return fmt.Errorf("skip layer verification only valid for manifestStore")
    39  }
    40  
    41  type manifestStore struct {
    42  	repository *repository
    43  	blobStore  *linkedBlobStore
    44  	ctx        context.Context
    45  
    46  	skipDependencyVerification bool
    47  
    48  	schema1Handler      ManifestHandler
    49  	schema2Handler      ManifestHandler
    50  	manifestListHandler ManifestHandler
    51  }
    52  
    53  var _ distribution.ManifestService = &manifestStore{}
    54  
    55  func (ms *manifestStore) Exists(ctx context.Context, dgst digest.Digest) (bool, error) {
    56  	context.GetLogger(ms.ctx).Debug("(*manifestStore).Exists")
    57  
    58  	_, err := ms.blobStore.Stat(ms.ctx, dgst)
    59  	if err != nil {
    60  		if err == distribution.ErrBlobUnknown {
    61  			return false, nil
    62  		}
    63  
    64  		return false, err
    65  	}
    66  
    67  	return true, nil
    68  }
    69  
    70  func (ms *manifestStore) Get(ctx context.Context, dgst digest.Digest, options ...distribution.ManifestServiceOption) (distribution.Manifest, error) {
    71  	context.GetLogger(ms.ctx).Debug("(*manifestStore).Get")
    72  
    73  	// TODO(stevvooe): Need to check descriptor from above to ensure that the
    74  	// mediatype is as we expect for the manifest store.
    75  
    76  	content, err := ms.blobStore.Get(ctx, dgst)
    77  	if err != nil {
    78  		if err == distribution.ErrBlobUnknown {
    79  			return nil, distribution.ErrManifestUnknownRevision{
    80  				Name:     ms.repository.Name(),
    81  				Revision: dgst,
    82  			}
    83  		}
    84  
    85  		return nil, err
    86  	}
    87  
    88  	var versioned manifest.Versioned
    89  	if err = json.Unmarshal(content, &versioned); err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	switch versioned.SchemaVersion {
    94  	case 1:
    95  		return ms.schema1Handler.Unmarshal(ctx, dgst, content)
    96  	case 2:
    97  		// This can be an image manifest or a manifest list
    98  		switch versioned.MediaType {
    99  		case schema2.MediaTypeManifest:
   100  			return ms.schema2Handler.Unmarshal(ctx, dgst, content)
   101  		case manifestlist.MediaTypeManifestList:
   102  			return ms.manifestListHandler.Unmarshal(ctx, dgst, content)
   103  		default:
   104  			return nil, distribution.ErrManifestVerification{fmt.Errorf("unrecognized manifest content type %s", versioned.MediaType)}
   105  		}
   106  	}
   107  
   108  	return nil, fmt.Errorf("unrecognized manifest schema version %d", versioned.SchemaVersion)
   109  }
   110  
   111  func (ms *manifestStore) Put(ctx context.Context, manifest distribution.Manifest, options ...distribution.ManifestServiceOption) (digest.Digest, error) {
   112  	context.GetLogger(ms.ctx).Debug("(*manifestStore).Put")
   113  
   114  	switch manifest.(type) {
   115  	case *schema1.SignedManifest:
   116  		return ms.schema1Handler.Put(ctx, manifest, ms.skipDependencyVerification)
   117  	case *schema2.DeserializedManifest:
   118  		return ms.schema2Handler.Put(ctx, manifest, ms.skipDependencyVerification)
   119  	case *manifestlist.DeserializedManifestList:
   120  		return ms.manifestListHandler.Put(ctx, manifest, ms.skipDependencyVerification)
   121  	}
   122  
   123  	return "", fmt.Errorf("unrecognized manifest type %T", manifest)
   124  }
   125  
   126  // Delete removes the revision of the specified manfiest.
   127  func (ms *manifestStore) Delete(ctx context.Context, dgst digest.Digest) error {
   128  	context.GetLogger(ms.ctx).Debug("(*manifestStore).Delete")
   129  	return ms.blobStore.Delete(ctx, dgst)
   130  }
   131  
   132  func (ms *manifestStore) Enumerate(ctx context.Context, manifests []distribution.Manifest, last distribution.Manifest) (n int, err error) {
   133  	return 0, distribution.ErrUnsupported
   134  }