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
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