add tag deletion event
whenever a tag is deleted an event is sent out via the regular notification channels Signed-off-by: Manish Tomar <manish.tomar@docker.com>master
							parent
							
								
									f0cc927784
								
							
						
					
					
						commit
						0d8f4ac7b8
					
				|  | @ -108,6 +108,14 @@ func (b *bridge) BlobDeleted(repo reference.Named, dgst digest.Digest) error { | |||
| 	return b.createBlobDeleteEventAndWrite(EventActionDelete, repo, dgst) | ||||
| } | ||||
| 
 | ||||
| func (b *bridge) TagDeleted(repo reference.Named, tag string) error { | ||||
| 	event := b.createEvent(EventActionDelete) | ||||
| 	event.Target.Repository = repo.Name() | ||||
| 	event.Target.Tag = tag | ||||
| 
 | ||||
| 	return b.sink.Write(*event) | ||||
| } | ||||
| 
 | ||||
| func (b *bridge) createManifestEventAndWrite(action string, repo reference.Named, sm distribution.Manifest) error { | ||||
| 	manifestEvent, err := b.createManifestEvent(action, repo, sm) | ||||
| 	if err != nil { | ||||
|  |  | |||
|  | @ -97,6 +97,9 @@ func TestEventBridgeManifestPulledWithTag(t *testing.T) { | |||
| func TestEventBridgeManifestDeleted(t *testing.T) { | ||||
| 	l := createTestEnv(t, testSinkFn(func(events ...Event) error { | ||||
| 		checkDeleted(t, EventActionDelete, events...) | ||||
| 		if events[0].Target.Digest != dgst { | ||||
| 			t.Fatalf("unexpected digest on event target: %q != %q", events[0].Target.Digest, dgst) | ||||
| 		} | ||||
| 		return nil | ||||
| 	})) | ||||
| 
 | ||||
|  | @ -106,6 +109,21 @@ func TestEventBridgeManifestDeleted(t *testing.T) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestEventBridgeTagDeleted(t *testing.T) { | ||||
| 	l := createTestEnv(t, testSinkFn(func(events ...Event) error { | ||||
| 		checkDeleted(t, EventActionDelete, events...) | ||||
| 		if events[0].Target.Tag != m.Tag { | ||||
| 			t.Fatalf("unexpected tag on event target: %q != %q", events[0].Target.Tag, m.Tag) | ||||
| 		} | ||||
| 		return nil | ||||
| 	})) | ||||
| 
 | ||||
| 	repoRef, _ := reference.WithName(repo) | ||||
| 	if err := l.TagDeleted(repoRef, m.Tag); err != nil { | ||||
| 		t.Fatalf("unexpected error notifying tag deletion: %v", err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func createTestEnv(t *testing.T, fn testSinkFn) Listener { | ||||
| 	pk, err := libtrust.GenerateECP256PrivateKey() | ||||
| 	if err != nil { | ||||
|  | @ -142,14 +160,9 @@ func checkDeleted(t *testing.T, action string, events ...Event) { | |||
| 		t.Fatalf("request not equal: %#v != %#v", event.Actor, actor) | ||||
| 	} | ||||
| 
 | ||||
| 	if event.Target.Digest != dgst { | ||||
| 		t.Fatalf("unexpected digest on event target: %q != %q", event.Target.Digest, dgst) | ||||
| 	} | ||||
| 
 | ||||
| 	if event.Target.Repository != repo { | ||||
| 		t.Fatalf("unexpected repository: %q != %q", event.Target.Repository, repo) | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| func checkCommonManifest(t *testing.T, action string, events ...Event) { | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import ( | |||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/docker/distribution" | ||||
| 
 | ||||
| 	dcontext "github.com/docker/distribution/context" | ||||
| 	"github.com/docker/distribution/reference" | ||||
| 	"github.com/opencontainers/go-digest" | ||||
|  | @ -25,10 +26,16 @@ type BlobListener interface { | |||
| 	BlobDeleted(repo reference.Named, desc digest.Digest) error | ||||
| } | ||||
| 
 | ||||
| // RepoListener describes a listener that can respond to repository related events.
 | ||||
| type RepoListener interface { | ||||
| 	TagDeleted(repo reference.Named, tag string) error | ||||
| } | ||||
| 
 | ||||
| // Listener combines all repository events into a single interface.
 | ||||
| type Listener interface { | ||||
| 	ManifestListener | ||||
| 	BlobListener | ||||
| 	RepoListener | ||||
| } | ||||
| 
 | ||||
| type repositoryListener struct { | ||||
|  | @ -214,3 +221,26 @@ func (bwl *blobWriterListener) Commit(ctx context.Context, desc distribution.Des | |||
| 
 | ||||
| 	return committed, err | ||||
| } | ||||
| 
 | ||||
| type tagServiceListener struct { | ||||
| 	distribution.TagService | ||||
| 	parent *repositoryListener | ||||
| } | ||||
| 
 | ||||
| func (rl *repositoryListener) Tags(ctx context.Context) distribution.TagService { | ||||
| 	return &tagServiceListener{ | ||||
| 		TagService: rl.Repository.Tags(ctx), | ||||
| 		parent:     rl, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (tagSL *tagServiceListener) Untag(ctx context.Context, tag string) error { | ||||
| 	if err := tagSL.TagService.Untag(ctx, tag); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := tagSL.parent.listener.TagDeleted(tagSL.parent.Repository.Named(), tag); err != nil { | ||||
| 		dcontext.GetLogger(ctx).Errorf("error dispatching tag deleted to listener: %v", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  |  | |||
|  | @ -50,12 +50,12 @@ func TestListener(t *testing.T) { | |||
| 		"layer:push":      2, | ||||
| 		"layer:pull":      2, | ||||
| 		"layer:delete":    2, | ||||
| 		"tag:delete":      1, | ||||
| 	} | ||||
| 
 | ||||
| 	if !reflect.DeepEqual(tl.ops, expectedOps) { | ||||
| 		t.Fatalf("counts do not match:\n%v\n !=\n%v", tl.ops, expectedOps) | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| type testListener struct { | ||||
|  | @ -64,7 +64,6 @@ type testListener struct { | |||
| 
 | ||||
| func (tl *testListener) ManifestPushed(repo reference.Named, m distribution.Manifest, options ...distribution.ManifestServiceOption) error { | ||||
| 	tl.ops["manifest:push"]++ | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
|  | @ -98,6 +97,11 @@ func (tl *testListener) BlobDeleted(repo reference.Named, d digest.Digest) error | |||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (tl *testListener) TagDeleted(repo reference.Named, tag string) error { | ||||
| 	tl.ops["tag:delete"]++ | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // checkExerciseRegistry takes the registry through all of its operations,
 | ||||
| // carrying out generic checks.
 | ||||
| func checkExerciseRepository(t *testing.T, repository distribution.Repository) { | ||||
|  | @ -200,6 +204,10 @@ func checkExerciseRepository(t *testing.T, repository distribution.Repository) { | |||
| 		if err != nil { | ||||
| 			t.Fatalf("unexpected error deleting blob: %v", err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	err = repository.Tags(ctx).Untag(ctx, m.Tag) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("unexpected error deleting tag: %v", err) | ||||
| 	} | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue