bridge_test.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package notifications
  2. import (
  3. "testing"
  4. "github.com/docker/distribution"
  5. "github.com/docker/distribution/digest"
  6. "github.com/docker/distribution/manifest/schema1"
  7. "github.com/docker/distribution/reference"
  8. "github.com/docker/distribution/registry/api/v2"
  9. "github.com/docker/distribution/uuid"
  10. "github.com/docker/libtrust"
  11. )
  12. var (
  13. // common environment for expected manifest events.
  14. repo = "test/repo"
  15. source = SourceRecord{
  16. Addr: "remote.test",
  17. InstanceID: uuid.Generate().String(),
  18. }
  19. ub = mustUB(v2.NewURLBuilderFromString("http://test.example.com/", false))
  20. actor = ActorRecord{
  21. Name: "test",
  22. }
  23. request = RequestRecord{}
  24. m = schema1.Manifest{
  25. Name: repo,
  26. Tag: "latest",
  27. }
  28. sm *schema1.SignedManifest
  29. payload []byte
  30. dgst digest.Digest
  31. )
  32. func TestEventBridgeManifestPulled(t *testing.T) {
  33. l := createTestEnv(t, testSinkFn(func(events ...Event) error {
  34. checkCommonManifest(t, EventActionPull, events...)
  35. return nil
  36. }))
  37. repoRef, _ := reference.ParseNamed(repo)
  38. if err := l.ManifestPulled(repoRef, sm); err != nil {
  39. t.Fatalf("unexpected error notifying manifest pull: %v", err)
  40. }
  41. }
  42. func TestEventBridgeManifestPushed(t *testing.T) {
  43. l := createTestEnv(t, testSinkFn(func(events ...Event) error {
  44. checkCommonManifest(t, EventActionPush, events...)
  45. return nil
  46. }))
  47. repoRef, _ := reference.ParseNamed(repo)
  48. if err := l.ManifestPushed(repoRef, sm); err != nil {
  49. t.Fatalf("unexpected error notifying manifest pull: %v", err)
  50. }
  51. }
  52. func TestEventBridgeManifestPushedWithTag(t *testing.T) {
  53. l := createTestEnv(t, testSinkFn(func(events ...Event) error {
  54. checkCommonManifest(t, EventActionPush, events...)
  55. if events[0].Target.Tag != "latest" {
  56. t.Fatalf("missing or unexpected tag: %#v", events[0].Target)
  57. }
  58. return nil
  59. }))
  60. repoRef, _ := reference.ParseNamed(repo)
  61. if err := l.ManifestPushed(repoRef, sm, distribution.WithTag(m.Tag)); err != nil {
  62. t.Fatalf("unexpected error notifying manifest pull: %v", err)
  63. }
  64. }
  65. func TestEventBridgeManifestPulledWithTag(t *testing.T) {
  66. l := createTestEnv(t, testSinkFn(func(events ...Event) error {
  67. checkCommonManifest(t, EventActionPull, events...)
  68. if events[0].Target.Tag != "latest" {
  69. t.Fatalf("missing or unexpected tag: %#v", events[0].Target)
  70. }
  71. return nil
  72. }))
  73. repoRef, _ := reference.ParseNamed(repo)
  74. if err := l.ManifestPulled(repoRef, sm, distribution.WithTag(m.Tag)); err != nil {
  75. t.Fatalf("unexpected error notifying manifest pull: %v", err)
  76. }
  77. }
  78. func TestEventBridgeManifestDeleted(t *testing.T) {
  79. l := createTestEnv(t, testSinkFn(func(events ...Event) error {
  80. checkDeleted(t, EventActionDelete, events...)
  81. return nil
  82. }))
  83. repoRef, _ := reference.ParseNamed(repo)
  84. if err := l.ManifestDeleted(repoRef, dgst); err != nil {
  85. t.Fatalf("unexpected error notifying manifest pull: %v", err)
  86. }
  87. }
  88. func createTestEnv(t *testing.T, fn testSinkFn) Listener {
  89. pk, err := libtrust.GenerateECP256PrivateKey()
  90. if err != nil {
  91. t.Fatalf("error generating private key: %v", err)
  92. }
  93. sm, err = schema1.Sign(&m, pk)
  94. if err != nil {
  95. t.Fatalf("error signing manifest: %v", err)
  96. }
  97. payload = sm.Canonical
  98. dgst = digest.FromBytes(payload)
  99. return NewBridge(ub, source, actor, request, fn)
  100. }
  101. func checkDeleted(t *testing.T, action string, events ...Event) {
  102. if len(events) != 1 {
  103. t.Fatalf("unexpected number of events: %v != 1", len(events))
  104. }
  105. event := events[0]
  106. if event.Source != source {
  107. t.Fatalf("source not equal: %#v != %#v", event.Source, source)
  108. }
  109. if event.Request != request {
  110. t.Fatalf("request not equal: %#v != %#v", event.Request, request)
  111. }
  112. if event.Actor != actor {
  113. t.Fatalf("request not equal: %#v != %#v", event.Actor, actor)
  114. }
  115. if event.Target.Digest != dgst {
  116. t.Fatalf("unexpected digest on event target: %q != %q", event.Target.Digest, dgst)
  117. }
  118. if event.Target.Repository != repo {
  119. t.Fatalf("unexpected repository: %q != %q", event.Target.Repository, repo)
  120. }
  121. }
  122. func checkCommonManifest(t *testing.T, action string, events ...Event) {
  123. checkCommon(t, events...)
  124. event := events[0]
  125. if event.Action != action {
  126. t.Fatalf("unexpected event action: %q != %q", event.Action, action)
  127. }
  128. repoRef, _ := reference.ParseNamed(repo)
  129. ref, _ := reference.WithDigest(repoRef, dgst)
  130. u, err := ub.BuildManifestURL(ref)
  131. if err != nil {
  132. t.Fatalf("error building expected url: %v", err)
  133. }
  134. if event.Target.URL != u {
  135. t.Fatalf("incorrect url passed: \n%q != \n%q", event.Target.URL, u)
  136. }
  137. }
  138. func checkCommon(t *testing.T, events ...Event) {
  139. if len(events) != 1 {
  140. t.Fatalf("unexpected number of events: %v != 1", len(events))
  141. }
  142. event := events[0]
  143. if event.Source != source {
  144. t.Fatalf("source not equal: %#v != %#v", event.Source, source)
  145. }
  146. if event.Request != request {
  147. t.Fatalf("request not equal: %#v != %#v", event.Request, request)
  148. }
  149. if event.Actor != actor {
  150. t.Fatalf("request not equal: %#v != %#v", event.Actor, actor)
  151. }
  152. if event.Target.Digest != dgst {
  153. t.Fatalf("unexpected digest on event target: %q != %q", event.Target.Digest, dgst)
  154. }
  155. if event.Target.Length != int64(len(payload)) {
  156. t.Fatalf("unexpected target length: %v != %v", event.Target.Length, len(payload))
  157. }
  158. if event.Target.Repository != repo {
  159. t.Fatalf("unexpected repository: %q != %q", event.Target.Repository, repo)
  160. }
  161. }
  162. type testSinkFn func(events ...Event) error
  163. func (tsf testSinkFn) Write(events ...Event) error {
  164. return tsf(events...)
  165. }
  166. func (tsf testSinkFn) Close() error { return nil }
  167. func mustUB(ub *v2.URLBuilder, err error) *v2.URLBuilder {
  168. if err != nil {
  169. panic(err)
  170. }
  171. return ub
  172. }