github.com/lusis/distribution@v2.0.1+incompatible/registry/storage/revisionstore.go (about) 1 package storage 2 3 import ( 4 "encoding/json" 5 6 "github.com/Sirupsen/logrus" 7 "github.com/docker/distribution" 8 "github.com/docker/distribution/digest" 9 "github.com/docker/distribution/manifest" 10 "github.com/docker/libtrust" 11 ) 12 13 // revisionStore supports storing and managing manifest revisions. 14 type revisionStore struct { 15 *repository 16 } 17 18 // exists returns true if the revision is available in the named repository. 19 func (rs *revisionStore) exists(revision digest.Digest) (bool, error) { 20 revpath, err := rs.pm.path(manifestRevisionPathSpec{ 21 name: rs.Name(), 22 revision: revision, 23 }) 24 25 if err != nil { 26 return false, err 27 } 28 29 exists, err := exists(rs.driver, revpath) 30 if err != nil { 31 return false, err 32 } 33 34 return exists, nil 35 } 36 37 // get retrieves the manifest, keyed by revision digest. 38 func (rs *revisionStore) get(revision digest.Digest) (*manifest.SignedManifest, error) { 39 // Ensure that this revision is available in this repository. 40 if exists, err := rs.exists(revision); err != nil { 41 return nil, err 42 } else if !exists { 43 return nil, distribution.ErrUnknownManifestRevision{ 44 Name: rs.Name(), 45 Revision: revision, 46 } 47 } 48 49 content, err := rs.blobStore.get(revision) 50 if err != nil { 51 return nil, err 52 } 53 54 // Fetch the signatures for the manifest 55 signatures, err := rs.Signatures().Get(revision) 56 if err != nil { 57 return nil, err 58 } 59 60 jsig, err := libtrust.NewJSONSignature(content, signatures...) 61 if err != nil { 62 return nil, err 63 } 64 65 // Extract the pretty JWS 66 raw, err := jsig.PrettySignature("signatures") 67 if err != nil { 68 return nil, err 69 } 70 71 var sm manifest.SignedManifest 72 if err := json.Unmarshal(raw, &sm); err != nil { 73 return nil, err 74 } 75 76 return &sm, nil 77 } 78 79 // put stores the manifest in the repository, if not already present. Any 80 // updated signatures will be stored, as well. 81 func (rs *revisionStore) put(sm *manifest.SignedManifest) (digest.Digest, error) { 82 // Resolve the payload in the manifest. 83 payload, err := sm.Payload() 84 if err != nil { 85 return "", err 86 } 87 88 // Digest and store the manifest payload in the blob store. 89 revision, err := rs.blobStore.put(payload) 90 if err != nil { 91 logrus.Errorf("error putting payload into blobstore: %v", err) 92 return "", err 93 } 94 95 // Link the revision into the repository. 96 if err := rs.link(revision); err != nil { 97 return "", err 98 } 99 100 // Grab each json signature and store them. 101 signatures, err := sm.Signatures() 102 if err != nil { 103 return "", err 104 } 105 106 if err := rs.Signatures().Put(revision, signatures...); err != nil { 107 return "", err 108 } 109 110 return revision, nil 111 } 112 113 // link links the revision into the repository. 114 func (rs *revisionStore) link(revision digest.Digest) error { 115 revisionPath, err := rs.pm.path(manifestRevisionLinkPathSpec{ 116 name: rs.Name(), 117 revision: revision, 118 }) 119 120 if err != nil { 121 return err 122 } 123 124 if exists, err := exists(rs.driver, revisionPath); err != nil { 125 return err 126 } else if exists { 127 // Revision has already been linked! 128 return nil 129 } 130 131 return rs.blobStore.link(revisionPath, revision) 132 } 133 134 // delete removes the specified manifest revision from storage. 135 func (rs *revisionStore) delete(revision digest.Digest) error { 136 revisionPath, err := rs.pm.path(manifestRevisionPathSpec{ 137 name: rs.Name(), 138 revision: revision, 139 }) 140 141 if err != nil { 142 return err 143 } 144 145 return rs.driver.Delete(revisionPath) 146 }