@@ -13,6 +13,7 @@ import (
13
13
"testing"
14
14
"time"
15
15
16
+ "github.com/docker/distribution/registry/api/errcode"
16
17
gocontext "golang.org/x/net/context"
17
18
18
19
kapi "k8s.io/kubernetes/pkg/api"
@@ -135,16 +136,27 @@ func TestImageStreamImport(t *testing.T) {
135
136
}
136
137
}
137
138
138
- func mockRegistryHandler (t * testing.T , count * int ) http.Handler {
139
+ // mockRegistryHandler returns a registry mock handler with several repositories.
140
+ // requireAuth causes handler to to return unauthorized and request basic authentication header if not given.
141
+ // count is increased each time the handler is invoked.
142
+ // There are three repositories:
143
+ // - test/image with phpManifest
144
+ // - test/image2 with etcdManifest
145
+ // - test/image3 with tags: v1, v2 and latest
146
+ // - the first points to etcdManifest
147
+ // - the others cause handler to return unknown error
148
+ func mockRegistryHandler (t * testing.T , requireAuth bool , count * int ) http.Handler {
139
149
return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
140
150
(* count )++
141
151
t .Logf ("%d got %s %s" , * count , r .Method , r .URL .Path )
142
152
143
153
w .Header ().Set ("Docker-Distribution-API-Version" , "registry/2.0" )
144
- if len (r .Header .Get ("Authorization" )) == 0 {
145
- w .Header ().Set ("WWW-Authenticate" , "BASIC" )
146
- w .WriteHeader (http .StatusUnauthorized )
147
- return
154
+ if requireAuth {
155
+ if len (r .Header .Get ("Authorization" )) == 0 {
156
+ w .Header ().Set ("WWW-Authenticate" , "BASIC" )
157
+ w .WriteHeader (http .StatusUnauthorized )
158
+ return
159
+ }
148
160
}
149
161
150
162
switch r .URL .Path {
@@ -154,6 +166,12 @@ func mockRegistryHandler(t *testing.T, count *int) http.Handler {
154
166
w .Write ([]byte (phpManifest ))
155
167
case "/v2/test/image2/manifests/" + etcdDigest :
156
168
w .Write ([]byte (etcdManifest ))
169
+ case "/v2/test/image3/tags/list" :
170
+ w .Write ([]byte ("{\" name\" : \" test/image3\" , \" tags\" : [\" latest\" , \" v1\" , \" v2\" ]}" ))
171
+ case "/v2/test/image3/manifests/latest" , "/v2/test/image3/manifests/v2" , "/v2/test/image3/manifests/" + danglingDigest :
172
+ errcode .ServeJSON (w , errcode .ErrorCodeUnknown )
173
+ case "/v2/test/image3/manifests/v1" , "/v2/test/image3/manifests/" + etcdDigest :
174
+ w .Write ([]byte (etcdManifest ))
157
175
default :
158
176
t .Fatalf ("unexpected request %s: %#v" , r .URL .Path , r )
159
177
}
@@ -164,7 +182,7 @@ func TestImageStreamImportAuthenticated(t *testing.T) {
164
182
testutil .RequireEtcd (t )
165
183
// start regular HTTP servers
166
184
count := 0
167
- server := httptest .NewServer (mockRegistryHandler (t , & count ))
185
+ server := httptest .NewServer (mockRegistryHandler (t , true , & count ))
168
186
server2 := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
169
187
w .Header ().Set ("Docker-Distribution-API-Version" , "registry/2.0" )
170
188
if len (r .Header .Get ("Authorization" )) == 0 {
@@ -177,7 +195,7 @@ func TestImageStreamImportAuthenticated(t *testing.T) {
177
195
178
196
// start a TLS server
179
197
count2 := 0
180
- server3 := httptest .NewTLSServer (mockRegistryHandler (t , & count2 ))
198
+ server3 := httptest .NewTLSServer (mockRegistryHandler (t , true , & count2 ))
181
199
182
200
url1 , _ := url .Parse (server .URL )
183
201
url2 , _ := url .Parse (server2 .URL )
@@ -324,6 +342,105 @@ func TestImageStreamImportAuthenticated(t *testing.T) {
324
342
}
325
343
}
326
344
345
+ // Verifies that individual errors for particular tags are handled properly when pulling all tags from a
346
+ // repository.
347
+ func TestImageStreamImportTagsFromRepository (t * testing.T ) {
348
+ testutil .RequireEtcd (t )
349
+ // start regular HTTP servers
350
+ count := 0
351
+ server := httptest .NewServer (mockRegistryHandler (t , false , & count ))
352
+
353
+ url , _ := url .Parse (server .URL )
354
+
355
+ // start a master
356
+ _ , clusterAdminKubeConfig , err := testserver .StartTestMaster ()
357
+ if err != nil {
358
+ t .Fatalf ("unexpected error: %v" , err )
359
+ }
360
+ /*
361
+ _, err := testutil.GetClusterAdminKubeClient(clusterAdminKubeConfig)
362
+ if err != nil {
363
+ t.Fatalf("unexpected error: %v", err)
364
+ }
365
+ */
366
+ c , err := testutil .GetClusterAdminClient (clusterAdminKubeConfig )
367
+ if err != nil {
368
+ t .Fatalf ("unexpected error: %v" , err )
369
+ }
370
+ err = testutil .CreateNamespace (clusterAdminKubeConfig , testutil .Namespace ())
371
+ if err != nil {
372
+ t .Fatalf ("unexpected error: %v" , err )
373
+ }
374
+
375
+ importSpec := & api.ImageStreamImport {
376
+ ObjectMeta : kapi.ObjectMeta {Name : "test" },
377
+ Spec : api.ImageStreamImportSpec {
378
+ Import : true ,
379
+ Repository : & api.RepositoryImportSpec {
380
+ From : kapi.ObjectReference {Kind : "DockerImage" , Name : url .Host + "/test/image3" },
381
+ ImportPolicy : api.TagImportPolicy {Insecure : true },
382
+ IncludeManifest : true ,
383
+ },
384
+ },
385
+ }
386
+
387
+ // import expecting regular image to pass
388
+ isi , err := c .ImageStreams (testutil .Namespace ()).Import (importSpec )
389
+ if err != nil {
390
+ t .Fatal (err )
391
+ }
392
+ if len (isi .Status .Images ) != 0 {
393
+ t .Errorf ("imported unexpected number of images (%d != 0)" , len (isi .Status .Images ))
394
+ }
395
+ if isi .Status .Repository == nil {
396
+ t .Fatalf ("exported non-nil repository status" )
397
+ }
398
+ if len (isi .Status .Repository .Images ) != 3 {
399
+ t .Fatalf ("imported unexpected number of tags (%d != 3)" , len (isi .Status .Repository .Images ))
400
+ }
401
+ for i , image := range isi .Status .Repository .Images {
402
+ switch i {
403
+ case 2 :
404
+ if image .Status .Status != unversioned .StatusSuccess {
405
+ t .Errorf ("import of image %d did not succeed: %#v" , i , image .Status )
406
+ }
407
+ if image .Tag != "v1" {
408
+ t .Errorf ("unexpected tag at position %d (%s != v1)" , i , image .Tag )
409
+ }
410
+ if image .Image == nil {
411
+ t .Fatalf ("expected image to be set" )
412
+ }
413
+ if image .Image .DockerImageReference != url .Host + "/test/image3@" + etcdDigest {
414
+ t .Errorf ("unexpected DockerImageReference (%s != %s)" , image .Image .DockerImageReference , url .Host + "/test/image3@" + etcdDigest )
415
+ }
416
+ if image .Image .Name != etcdDigest {
417
+ t .Errorf ("expected etcd digest as a name of the image (%s != %s)" , image .Image .Name , etcdDigest )
418
+ }
419
+ default :
420
+ if image .Status .Status != unversioned .StatusFailure || image .Status .Reason != unversioned .StatusReasonInternalError {
421
+ t .Fatalf ("import of image %d did not report internal server error: %#v" , i , image .Status )
422
+ }
423
+ expectedTags := []string {"latest" , "v2" }[i ]
424
+ if image .Tag != expectedTags {
425
+ t .Errorf ("unexpected tag at position %d (%s != %s)" , i , image .Tag , expectedTags [i ])
426
+ }
427
+ }
428
+ }
429
+
430
+ is , err := c .ImageStreams (testutil .Namespace ()).Get ("test" )
431
+ if err != nil {
432
+ t .Fatal (err )
433
+ }
434
+ tagEvent := api .LatestTaggedImage (is , "v1" )
435
+ if tagEvent == nil {
436
+ t .Fatalf ("no image tagged for v1: %#v" , is )
437
+ }
438
+
439
+ if tagEvent == nil || tagEvent .Image != etcdDigest || tagEvent .DockerImageReference != url .Host + "/test/image3@" + etcdDigest {
440
+ t .Fatalf ("expected the etcd image to be tagged: %#v" , tagEvent )
441
+ }
442
+ }
443
+
327
444
// Verifies that the import scheduler fetches an image repeatedly (every 1s as per the default
328
445
// test controller interval), updates the image stream only when there are changes, and if an
329
446
// error occurs writes the error only once (instead of every interval)
@@ -861,3 +978,5 @@ const phpManifest = `{
861
978
}
862
979
]
863
980
}`
981
+
982
+ const danglingDigest = `sha256:f374c0d9b59e6fdf9f8922d59e946b05fbeabaed70b0639d7b6b524f3299e87b`
0 commit comments