API to retrive tag's digests
Add an interface alongside TagStore that provides API to retreive digests of all manifests that a tag historically pointed to. It also includes currently linked tag. Signed-off-by: Manish Tomar <manish.tomar@docker.com>master
							parent
							
								
									1cb4180b1a
								
							
						
					
					
						commit
						9ebf151ac2
					
				|  | @ -196,3 +196,37 @@ func (ts *tagStore) Lookup(ctx context.Context, desc distribution.Descriptor) ([ | |||
| 
 | ||||
| 	return tags, nil | ||||
| } | ||||
| 
 | ||||
| func (ts *tagStore) Indexes(ctx context.Context, tag string) ([]digest.Digest, error) { | ||||
| 	var tagLinkPath = func(name string, dgst digest.Digest) (string, error) { | ||||
| 		return pathFor(manifestTagIndexEntryLinkPathSpec{ | ||||
| 			name:     name, | ||||
| 			tag:      tag, | ||||
| 			revision: dgst, | ||||
| 		}) | ||||
| 	} | ||||
| 	lbs := &linkedBlobStore{ | ||||
| 		blobStore: ts.blobStore, | ||||
| 		blobAccessController: &linkedBlobStatter{ | ||||
| 			blobStore:   ts.blobStore, | ||||
| 			repository:  ts.repository, | ||||
| 			linkPathFns: []linkPathFunc{manifestRevisionLinkPath}, | ||||
| 		}, | ||||
| 		repository:  ts.repository, | ||||
| 		ctx:         ctx, | ||||
| 		linkPathFns: []linkPathFunc{tagLinkPath}, | ||||
| 		linkDirectoryPathSpec: manifestTagIndexPathSpec{ | ||||
| 			name: ts.repository.Named().Name(), | ||||
| 			tag:  tag, | ||||
| 		}, | ||||
| 	} | ||||
| 	var dgsts []digest.Digest | ||||
| 	err := lbs.Enumerate(ctx, func(dgst digest.Digest) error { | ||||
| 		dgsts = append(dgsts, dgst) | ||||
| 		return nil | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return dgsts, nil | ||||
| } | ||||
|  |  | |||
|  | @ -2,15 +2,22 @@ package storage | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"reflect" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/docker/distribution" | ||||
| 	"github.com/docker/distribution/manifest" | ||||
| 	"github.com/docker/distribution/manifest/schema2" | ||||
| 	"github.com/docker/distribution/reference" | ||||
| 	"github.com/docker/distribution/registry/storage/driver/inmemory" | ||||
| 	digest "github.com/opencontainers/go-digest" | ||||
| ) | ||||
| 
 | ||||
| type tagsTestEnv struct { | ||||
| 	ts  distribution.TagService | ||||
| 	bs  distribution.BlobStore | ||||
| 	ms  distribution.ManifestService | ||||
| 	gbs distribution.BlobStatter | ||||
| 	ctx context.Context | ||||
| } | ||||
| 
 | ||||
|  | @ -27,10 +34,17 @@ func testTagStore(t *testing.T) *tagsTestEnv { | |||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	ms, err := repo.Manifests(ctx) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	return &tagsTestEnv{ | ||||
| 		ctx: ctx, | ||||
| 		ts:  repo.Tags(ctx), | ||||
| 		bs:  repo.Blobs(ctx), | ||||
| 		gbs: reg.BlobStatter(), | ||||
| 		ms:  ms, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -205,5 +219,75 @@ func TestTagLookup(t *testing.T) { | |||
| 	if len(tags) != 2 { | ||||
| 		t.Errorf("Lookup of descB returned %d tags, expected 2", len(tags)) | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| func TestTagIndexes(t *testing.T) { | ||||
| 	env := testTagStore(t) | ||||
| 	tagStore := env.ts | ||||
| 	ctx := env.ctx | ||||
| 
 | ||||
| 	indexes, ok := tagStore.(distribution.TagIndexes) | ||||
| 	if !ok { | ||||
| 		t.Fatal("tagStore does not implement TagIndexes interface") | ||||
| 	} | ||||
| 
 | ||||
| 	conf, err := env.bs.Put(ctx, "application/octet-stream", []byte{0}) | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 
 | ||||
| 	dgstsSet := make(map[digest.Digest]bool) | ||||
| 	for i := 0; i < 3; i++ { | ||||
| 		layer, err := env.bs.Put(ctx, "application/octet-stream", []byte{byte(i + 1)}) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		m := schema2.Manifest{ | ||||
| 			Versioned: manifest.Versioned{ | ||||
| 				SchemaVersion: 2, | ||||
| 				MediaType:     schema2.MediaTypeManifest, | ||||
| 			}, | ||||
| 			Config: distribution.Descriptor{ | ||||
| 				Digest:    conf.Digest, | ||||
| 				Size:      1, | ||||
| 				MediaType: schema2.MediaTypeImageConfig, | ||||
| 			}, | ||||
| 			Layers: []distribution.Descriptor{ | ||||
| 				{ | ||||
| 					Digest:    layer.Digest, | ||||
| 					Size:      1, | ||||
| 					MediaType: schema2.MediaTypeLayer, | ||||
| 				}, | ||||
| 			}, | ||||
| 		} | ||||
| 		dm, err := schema2.FromStruct(m) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		dgst, err := env.ms.Put(ctx, dm) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		desc, err := env.gbs.Stat(ctx, dgst) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		err = tagStore.Tag(ctx, "t", desc) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		dgstsSet[dgst] = true | ||||
| 	} | ||||
| 
 | ||||
| 	gotDgsts, err := indexes.Indexes(ctx, "t") | ||||
| 	if err != nil { | ||||
| 		t.Fatal(err) | ||||
| 	} | ||||
| 	gotDgstsSet := make(map[digest.Digest]bool) | ||||
| 	for _, dgst := range gotDgsts { | ||||
| 		gotDgstsSet[dgst] = true | ||||
| 	} | ||||
| 	if !reflect.DeepEqual(dgstsSet, gotDgstsSet) { | ||||
| 		t.Fatalf("Expected digests: %v but got digests: %v", dgstsSet, gotDgstsSet) | ||||
| 	} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										9
									
								
								tags.go
								
								
								
								
							
							
						
						
									
										9
									
								
								tags.go
								
								
								
								
							|  | @ -2,6 +2,8 @@ package distribution | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	digest "github.com/opencontainers/go-digest" | ||||
| ) | ||||
| 
 | ||||
| // TagService provides access to information about tagged objects.
 | ||||
|  | @ -25,3 +27,10 @@ type TagService interface { | |||
| 	// Lookup returns the set of tags referencing the given digest.
 | ||||
| 	Lookup(ctx context.Context, digest Descriptor) ([]string, error) | ||||
| } | ||||
| 
 | ||||
| // TagIndexes proves method to retreive all the digests that a tag historically pointed to
 | ||||
| type TagIndexes interface { | ||||
| 	// Indexes returns set of digests that this tag historically pointed to. This also includes
 | ||||
| 	// currently linked digest. There is no ordering guaranteed
 | ||||
| 	Indexes(ctx context.Context, tag string) ([]digest.Digest, error) | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue