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  }