...

Source file src/github.com/docker/distribution/notifications/bridge_test.go

Documentation: github.com/docker/distribution/notifications

     1  package notifications
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/distribution/reference"
     7  	"github.com/docker/distribution"
     8  	"github.com/docker/distribution/manifest/schema1"
     9  	v2 "github.com/docker/distribution/registry/api/v2"
    10  	"github.com/docker/distribution/uuid"
    11  	"github.com/docker/libtrust"
    12  	"github.com/opencontainers/go-digest"
    13  )
    14  
    15  var (
    16  	// common environment for expected manifest events.
    17  
    18  	repo   = "test/repo"
    19  	source = SourceRecord{
    20  		Addr:       "remote.test",
    21  		InstanceID: uuid.Generate().String(),
    22  	}
    23  	ub = mustUB(v2.NewURLBuilderFromString("http://test.example.com/", false))
    24  
    25  	actor = ActorRecord{
    26  		Name: "test",
    27  	}
    28  	request = RequestRecord{}
    29  	layers  = []schema1.FSLayer{
    30  		{
    31  			BlobSum: "asdf",
    32  		},
    33  		{
    34  			BlobSum: "qwer",
    35  		},
    36  	}
    37  	m = schema1.Manifest{
    38  		Name:     repo,
    39  		Tag:      "latest",
    40  		FSLayers: layers,
    41  	}
    42  
    43  	sm      *schema1.SignedManifest
    44  	payload []byte
    45  	dgst    digest.Digest
    46  )
    47  
    48  func TestEventBridgeManifestPulled(t *testing.T) {
    49  	l := createTestEnv(t, testSinkFn(func(events ...Event) error {
    50  		checkCommonManifest(t, EventActionPull, events...)
    51  
    52  		return nil
    53  	}))
    54  
    55  	repoRef, _ := reference.WithName(repo)
    56  	if err := l.ManifestPulled(repoRef, sm); err != nil {
    57  		t.Fatalf("unexpected error notifying manifest pull: %v", err)
    58  	}
    59  }
    60  
    61  func TestEventBridgeManifestPushed(t *testing.T) {
    62  	l := createTestEnv(t, testSinkFn(func(events ...Event) error {
    63  		checkCommonManifest(t, EventActionPush, events...)
    64  
    65  		return nil
    66  	}))
    67  
    68  	repoRef, _ := reference.WithName(repo)
    69  	if err := l.ManifestPushed(repoRef, sm); err != nil {
    70  		t.Fatalf("unexpected error notifying manifest pull: %v", err)
    71  	}
    72  }
    73  
    74  func TestEventBridgeManifestPushedWithTag(t *testing.T) {
    75  	l := createTestEnv(t, testSinkFn(func(events ...Event) error {
    76  		checkCommonManifest(t, EventActionPush, events...)
    77  		if events[0].Target.Tag != "latest" {
    78  			t.Fatalf("missing or unexpected tag: %#v", events[0].Target)
    79  		}
    80  
    81  		return nil
    82  	}))
    83  
    84  	repoRef, _ := reference.WithName(repo)
    85  	if err := l.ManifestPushed(repoRef, sm, distribution.WithTag(m.Tag)); err != nil {
    86  		t.Fatalf("unexpected error notifying manifest pull: %v", err)
    87  	}
    88  }
    89  
    90  func TestEventBridgeManifestPulledWithTag(t *testing.T) {
    91  	l := createTestEnv(t, testSinkFn(func(events ...Event) error {
    92  		checkCommonManifest(t, EventActionPull, events...)
    93  		if events[0].Target.Tag != "latest" {
    94  			t.Fatalf("missing or unexpected tag: %#v", events[0].Target)
    95  		}
    96  
    97  		return nil
    98  	}))
    99  
   100  	repoRef, _ := reference.WithName(repo)
   101  	if err := l.ManifestPulled(repoRef, sm, distribution.WithTag(m.Tag)); err != nil {
   102  		t.Fatalf("unexpected error notifying manifest pull: %v", err)
   103  	}
   104  }
   105  
   106  func TestEventBridgeManifestDeleted(t *testing.T) {
   107  	l := createTestEnv(t, testSinkFn(func(events ...Event) error {
   108  		checkDeleted(t, EventActionDelete, events...)
   109  		if events[0].Target.Digest != dgst {
   110  			t.Fatalf("unexpected digest on event target: %q != %q", events[0].Target.Digest, dgst)
   111  		}
   112  		return nil
   113  	}))
   114  
   115  	repoRef, _ := reference.WithName(repo)
   116  	if err := l.ManifestDeleted(repoRef, dgst); err != nil {
   117  		t.Fatalf("unexpected error notifying manifest pull: %v", err)
   118  	}
   119  }
   120  
   121  func TestEventBridgeTagDeleted(t *testing.T) {
   122  	l := createTestEnv(t, testSinkFn(func(events ...Event) error {
   123  		checkDeleted(t, EventActionDelete, events...)
   124  		if events[0].Target.Tag != m.Tag {
   125  			t.Fatalf("unexpected tag on event target: %q != %q", events[0].Target.Tag, m.Tag)
   126  		}
   127  		return nil
   128  	}))
   129  
   130  	repoRef, _ := reference.WithName(repo)
   131  	if err := l.TagDeleted(repoRef, m.Tag); err != nil {
   132  		t.Fatalf("unexpected error notifying tag deletion: %v", err)
   133  	}
   134  }
   135  
   136  func TestEventBridgeRepoDeleted(t *testing.T) {
   137  	l := createTestEnv(t, testSinkFn(func(events ...Event) error {
   138  		checkDeleted(t, EventActionDelete, events...)
   139  		return nil
   140  	}))
   141  
   142  	repoRef, _ := reference.WithName(repo)
   143  	if err := l.RepoDeleted(repoRef); err != nil {
   144  		t.Fatalf("unexpected error notifying repo deletion: %v", err)
   145  	}
   146  }
   147  
   148  func createTestEnv(t *testing.T, fn testSinkFn) Listener {
   149  	pk, err := libtrust.GenerateECP256PrivateKey()
   150  	if err != nil {
   151  		t.Fatalf("error generating private key: %v", err)
   152  	}
   153  
   154  	sm, err = schema1.Sign(&m, pk)
   155  	if err != nil {
   156  		t.Fatalf("error signing manifest: %v", err)
   157  	}
   158  
   159  	payload = sm.Canonical
   160  	dgst = digest.FromBytes(payload)
   161  
   162  	return NewBridge(ub, source, actor, request, fn, true)
   163  }
   164  
   165  func checkDeleted(t *testing.T, action string, events ...Event) {
   166  	if len(events) != 1 {
   167  		t.Fatalf("unexpected number of events: %v != 1", len(events))
   168  	}
   169  
   170  	event := events[0]
   171  
   172  	if event.Source != source {
   173  		t.Fatalf("source not equal: %#v != %#v", event.Source, source)
   174  	}
   175  
   176  	if event.Request != request {
   177  		t.Fatalf("request not equal: %#v != %#v", event.Request, request)
   178  	}
   179  
   180  	if event.Actor != actor {
   181  		t.Fatalf("request not equal: %#v != %#v", event.Actor, actor)
   182  	}
   183  
   184  	if event.Target.Repository != repo {
   185  		t.Fatalf("unexpected repository: %q != %q", event.Target.Repository, repo)
   186  	}
   187  }
   188  
   189  func checkCommonManifest(t *testing.T, action string, events ...Event) {
   190  	checkCommon(t, events...)
   191  
   192  	event := events[0]
   193  	if event.Action != action {
   194  		t.Fatalf("unexpected event action: %q != %q", event.Action, action)
   195  	}
   196  
   197  	repoRef, _ := reference.WithName(repo)
   198  	ref, _ := reference.WithDigest(repoRef, dgst)
   199  	u, err := ub.BuildManifestURL(ref)
   200  	if err != nil {
   201  		t.Fatalf("error building expected url: %v", err)
   202  	}
   203  
   204  	if event.Target.URL != u {
   205  		t.Fatalf("incorrect url passed: \n%q != \n%q", event.Target.URL, u)
   206  	}
   207  
   208  	if len(event.Target.References) != len(layers) {
   209  		t.Fatalf("unexpected number of references %v != %v", len(event.Target.References), len(layers))
   210  	}
   211  	for i, targetReference := range event.Target.References {
   212  		if targetReference.Digest != layers[i].BlobSum {
   213  			t.Fatalf("unexpected reference: %q != %q", targetReference.Digest, layers[i].BlobSum)
   214  		}
   215  	}
   216  }
   217  
   218  func checkCommon(t *testing.T, events ...Event) {
   219  	if len(events) != 1 {
   220  		t.Fatalf("unexpected number of events: %v != 1", len(events))
   221  	}
   222  
   223  	event := events[0]
   224  
   225  	if event.Source != source {
   226  		t.Fatalf("source not equal: %#v != %#v", event.Source, source)
   227  	}
   228  
   229  	if event.Request != request {
   230  		t.Fatalf("request not equal: %#v != %#v", event.Request, request)
   231  	}
   232  
   233  	if event.Actor != actor {
   234  		t.Fatalf("request not equal: %#v != %#v", event.Actor, actor)
   235  	}
   236  
   237  	if event.Target.Digest != dgst {
   238  		t.Fatalf("unexpected digest on event target: %q != %q", event.Target.Digest, dgst)
   239  	}
   240  
   241  	if event.Target.Length != int64(len(payload)) {
   242  		t.Fatalf("unexpected target length: %v != %v", event.Target.Length, len(payload))
   243  	}
   244  
   245  	if event.Target.Repository != repo {
   246  		t.Fatalf("unexpected repository: %q != %q", event.Target.Repository, repo)
   247  	}
   248  
   249  }
   250  
   251  type testSinkFn func(events ...Event) error
   252  
   253  func (tsf testSinkFn) Write(events ...Event) error {
   254  	return tsf(events...)
   255  }
   256  
   257  func (tsf testSinkFn) Close() error { return nil }
   258  
   259  func mustUB(ub *v2.URLBuilder, err error) *v2.URLBuilder {
   260  	if err != nil {
   261  		panic(err)
   262  	}
   263  
   264  	return ub
   265  }
   266  

View as plain text