...

Source file src/github.com/docker/distribution/registry/storage/manifeststore.go

Documentation: github.com/docker/distribution/registry/storage

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

View as plain text