forked from TrueCloudLab/distribution
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>
This commit is contained in:
parent
f0cc927784
commit
0d8f4ac7b8
4 changed files with 66 additions and 7 deletions
|
@ -108,6 +108,14 @@ func (b *bridge) BlobDeleted(repo reference.Named, dgst digest.Digest) error {
|
||||||
return b.createBlobDeleteEventAndWrite(EventActionDelete, repo, dgst)
|
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 {
|
func (b *bridge) createManifestEventAndWrite(action string, repo reference.Named, sm distribution.Manifest) error {
|
||||||
manifestEvent, err := b.createManifestEvent(action, repo, sm)
|
manifestEvent, err := b.createManifestEvent(action, repo, sm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -97,6 +97,9 @@ func TestEventBridgeManifestPulledWithTag(t *testing.T) {
|
||||||
func TestEventBridgeManifestDeleted(t *testing.T) {
|
func TestEventBridgeManifestDeleted(t *testing.T) {
|
||||||
l := createTestEnv(t, testSinkFn(func(events ...Event) error {
|
l := createTestEnv(t, testSinkFn(func(events ...Event) error {
|
||||||
checkDeleted(t, EventActionDelete, events...)
|
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
|
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 {
|
func createTestEnv(t *testing.T, fn testSinkFn) Listener {
|
||||||
pk, err := libtrust.GenerateECP256PrivateKey()
|
pk, err := libtrust.GenerateECP256PrivateKey()
|
||||||
if err != nil {
|
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)
|
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 {
|
if event.Target.Repository != repo {
|
||||||
t.Fatalf("unexpected repository: %q != %q", event.Target.Repository, repo)
|
t.Fatalf("unexpected repository: %q != %q", event.Target.Repository, repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkCommonManifest(t *testing.T, action string, events ...Event) {
|
func checkCommonManifest(t *testing.T, action string, events ...Event) {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/docker/distribution"
|
"github.com/docker/distribution"
|
||||||
|
|
||||||
dcontext "github.com/docker/distribution/context"
|
dcontext "github.com/docker/distribution/context"
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
@ -25,10 +26,16 @@ type BlobListener interface {
|
||||||
BlobDeleted(repo reference.Named, desc digest.Digest) error
|
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.
|
// Listener combines all repository events into a single interface.
|
||||||
type Listener interface {
|
type Listener interface {
|
||||||
ManifestListener
|
ManifestListener
|
||||||
BlobListener
|
BlobListener
|
||||||
|
RepoListener
|
||||||
}
|
}
|
||||||
|
|
||||||
type repositoryListener struct {
|
type repositoryListener struct {
|
||||||
|
@ -214,3 +221,26 @@ func (bwl *blobWriterListener) Commit(ctx context.Context, desc distribution.Des
|
||||||
|
|
||||||
return committed, err
|
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:push": 2,
|
||||||
"layer:pull": 2,
|
"layer:pull": 2,
|
||||||
"layer:delete": 2,
|
"layer:delete": 2,
|
||||||
|
"tag:delete": 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(tl.ops, expectedOps) {
|
if !reflect.DeepEqual(tl.ops, expectedOps) {
|
||||||
t.Fatalf("counts do not match:\n%v\n !=\n%v", tl.ops, expectedOps)
|
t.Fatalf("counts do not match:\n%v\n !=\n%v", tl.ops, expectedOps)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type testListener struct {
|
type testListener struct {
|
||||||
|
@ -64,7 +64,6 @@ type testListener struct {
|
||||||
|
|
||||||
func (tl *testListener) ManifestPushed(repo reference.Named, m distribution.Manifest, options ...distribution.ManifestServiceOption) error {
|
func (tl *testListener) ManifestPushed(repo reference.Named, m distribution.Manifest, options ...distribution.ManifestServiceOption) error {
|
||||||
tl.ops["manifest:push"]++
|
tl.ops["manifest:push"]++
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,6 +97,11 @@ func (tl *testListener) BlobDeleted(repo reference.Named, d digest.Digest) error
|
||||||
return nil
|
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,
|
// checkExerciseRegistry takes the registry through all of its operations,
|
||||||
// carrying out generic checks.
|
// carrying out generic checks.
|
||||||
func checkExerciseRepository(t *testing.T, repository distribution.Repository) {
|
func checkExerciseRepository(t *testing.T, repository distribution.Repository) {
|
||||||
|
@ -200,6 +204,10 @@ func checkExerciseRepository(t *testing.T, repository distribution.Repository) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error deleting blob: %v", err)
|
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 a new issue