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 }