1
0
mirror of https://github.com/openshift/image-registry.git synced 2026-02-05 18:45:15 +01:00

Refactor integration tests

This commit is contained in:
Oleg Bulatov
2018-09-20 16:01:40 +02:00
parent e37665144e
commit f736dd7046
5 changed files with 168 additions and 183 deletions

View File

@@ -0,0 +1,106 @@
package testframework
import (
"encoding/json"
"fmt"
"net/http"
"github.com/opencontainers/go-digest"
"github.com/pborman/uuid"
)
type Schema2ImageData struct {
ConfigMediaType string
Config []byte
ConfigDigest digest.Digest
LayerMediaType string
Layer []byte
LayerDigest digest.Digest
ManifestMediaType string
Manifest []byte
ManifestDigest digest.Digest
}
func NewSchema2ImageData() (Schema2ImageData, error) {
data := Schema2ImageData{
ConfigMediaType: "application/vnd.docker.container.image.v1+json",
Config: []byte("{}"),
LayerMediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip",
Layer: []byte("image-registry-integration-test-" + uuid.NewRandom().String()),
ManifestMediaType: "application/vnd.docker.distribution.manifest.v2+json",
}
data.ConfigDigest = digest.FromBytes(data.Config)
data.LayerDigest = digest.FromBytes(data.Layer)
manifest, err := json.Marshal(map[string]interface{}{
"schemaVersion": 2,
"mediaType": data.ManifestMediaType,
"config": map[string]interface{}{
"mediaType": data.ConfigMediaType,
"size": len(data.Config),
"digest": data.ConfigDigest.String(),
},
"layers": []map[string]interface{}{
{
"mediaType": data.LayerMediaType,
"size": len(data.Layer),
"digest": data.LayerDigest.String(),
},
},
})
if err != nil {
return data, fmt.Errorf("unable to create image manifest: %v", err)
}
data.Manifest = manifest
data.ManifestDigest = digest.FromBytes(data.Manifest)
return data, nil
}
func ServeV2(w http.ResponseWriter, r *http.Request) bool {
if r.Method == "GET" && r.URL.Path == "/v2/" {
_, _ = w.Write([]byte(`{}`))
return true
}
return false
}
func ServeImage(w http.ResponseWriter, r *http.Request, image string, data Schema2ImageData, tags []string) bool {
prefix := "/v2/" + image
isGetManifest := func() bool {
if r.Method == "GET" {
if r.URL.Path == prefix+"/manifests/"+data.ManifestDigest.String() {
return true
}
for _, tag := range tags {
if r.URL.Path == prefix+"/manifests/"+tag {
return true
}
}
}
return false
}
switch {
case isGetManifest():
w.Header().Set("Content-Type", data.ManifestMediaType)
_, _ = w.Write(data.Manifest)
case r.Method == "GET" && r.URL.Path == prefix+"/blobs/"+data.ConfigDigest.String():
_, _ = w.Write(data.Config)
case r.Method == "GET" && r.URL.Path == prefix+"/blobs/"+data.LayerDigest.String():
_, _ = w.Write(data.Layer)
case r.Method == "HEAD" && r.URL.Path == prefix+"/blobs/"+data.ConfigDigest.String():
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(data.Config)))
w.WriteHeader(http.StatusOK)
case r.Method == "HEAD" && r.URL.Path == prefix+"/blobs/"+data.LayerDigest.String():
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(data.Layer)))
w.WriteHeader(http.StatusOK)
default:
return false
}
return true
}

View File

@@ -3,12 +3,10 @@ package integration
import (
"bytes"
"context"
"encoding/json"
"testing"
"time"
"github.com/docker/distribution/registry/storage/driver/inmemory"
"github.com/opencontainers/go-digest"
kerrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -25,33 +23,10 @@ import (
)
func TestManifestMigration(t *testing.T) {
config := []byte("{}")
configDigest := digest.FromBytes(config)
foo := []byte("foo-manifest-migration")
fooDigest := digest.FromBytes(foo)
manifestMediaType := "application/vnd.docker.distribution.manifest.v2+json"
manifest, err := json.Marshal(map[string]interface{}{
"schemaVersion": 2,
"mediaType": manifestMediaType,
"config": map[string]interface{}{
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": len(config),
"digest": configDigest.String(),
},
"layers": []map[string]interface{}{
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": len(foo),
"digest": fooDigest.String(),
},
},
})
imageData, err := testframework.NewSchema2ImageData()
if err != nil {
t.Fatalf("unable to marshal manifest: %v", err)
t.Fatal(err)
}
manifestDigest := digest.FromBytes(manifest)
master := testframework.NewMaster(t)
defer master.Close()
@@ -72,7 +47,7 @@ func TestManifestMigration(t *testing.T) {
t.Fatal(err)
}
err = imageClient.Images().Delete(string(manifestDigest), &metav1.DeleteOptions{})
err = imageClient.Images().Delete(imageData.ManifestDigest.String(), &metav1.DeleteOptions{})
if err != nil && !kerrors.IsNotFound(err) {
t.Fatalf("failed to delete an old instance of the image: %v", err)
}
@@ -84,15 +59,15 @@ func TestManifestMigration(t *testing.T) {
},
Image: imageapiv1.Image{
ObjectMeta: metav1.ObjectMeta{
Name: string(manifestDigest),
Name: imageData.ManifestDigest.String(),
Annotations: map[string]string{
imageapi.ManagedByOpenShiftAnnotation: "true",
},
},
DockerImageReference: "shouldnt-be-resolved.example.com/this-is-a-fake-image",
DockerImageManifestMediaType: manifestMediaType,
DockerImageManifest: string(manifest),
DockerImageConfig: string(config),
DockerImageManifestMediaType: imageData.ManifestMediaType,
DockerImageManifest: string(imageData.Manifest),
DockerImageConfig: string(imageData.Config),
},
Tag: "latest",
})
@@ -114,25 +89,25 @@ func TestManifestMigration(t *testing.T) {
t.Fatal(err)
}
_, err = ms.Get(ctx, digest.Digest(manifestDigest))
_, err = ms.Get(ctx, imageData.ManifestDigest)
if err != nil {
t.Fatal(err)
}
t.Logf("waiting for migration to finish...")
if err := driver.WaitFor(ctx, storagepath.Blob(manifestDigest)); err != nil {
if err := driver.WaitFor(ctx, storagepath.Blob(imageData.ManifestDigest)); err != nil {
t.Fatal(err)
}
t.Logf("manifest is migrated, checking results...")
manifestOnStorage, err := driver.GetContent(ctx, storagepath.Blob(manifestDigest))
manifestOnStorage, err := driver.GetContent(ctx, storagepath.Blob(imageData.ManifestDigest))
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(manifestOnStorage, manifest) {
t.Errorf("migration has changed the manifest: got %q, want %q", manifestOnStorage, manifest)
if !bytes.Equal(manifestOnStorage, imageData.Manifest) {
t.Errorf("migration has changed the manifest: got %q, want %q", manifestOnStorage, imageData.Manifest)
}
w, err := imageClient.Images().Watch(metav1.ListOptions{
@@ -150,7 +125,7 @@ func TestManifestMigration(t *testing.T) {
if !ok {
return false, nil
}
if image.Name != string(manifestDigest) || image.DockerImageManifest != "" && image.DockerImageConfig != "" {
if image.Name != imageData.ManifestDigest.String() || image.DockerImageManifest != "" && image.DockerImageConfig != "" {
return false, nil
}
return true, nil

View File

@@ -3,7 +3,6 @@ package integration
import (
"bufio"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
@@ -11,7 +10,6 @@ import (
"testing"
"github.com/docker/distribution"
digest "github.com/opencontainers/go-digest"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -23,11 +21,10 @@ import (
)
func TestPullthroughBlob(t *testing.T) {
config := "{}"
configDigest := digest.FromBytes([]byte(config))
foo := "foo"
fooDigest := digest.FromBytes([]byte(foo))
imageData, err := testframework.NewSchema2ImageData()
if err != nil {
t.Fatal(err)
}
master := testframework.NewMaster(t)
defer master.Close()
@@ -50,38 +47,13 @@ func TestPullthroughBlob(t *testing.T) {
return
}
switch req {
case "GET /v2/":
w.Write([]byte(`{}`))
case "GET /v2/remoteimage/manifests/latest":
mediaType := "application/vnd.docker.distribution.manifest.v2+json"
w.Header().Set("Content-Type", mediaType)
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"schemaVersion": 2,
"mediaType": mediaType,
"config": map[string]interface{}{
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": len(config),
"digest": configDigest.String(),
},
"layers": []map[string]interface{}{
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": len(foo),
"digest": fooDigest.String(),
},
},
})
case "GET /v2/remoteimage/blobs/" + configDigest.String():
w.Write([]byte(config))
case "HEAD /v2/remoteimage/blobs/" + fooDigest.String():
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(foo)))
w.WriteHeader(http.StatusOK)
case "GET /v2/remoteimage/blobs/" + fooDigest.String():
w.Write([]byte(foo))
default:
t.Errorf("error: remote registry got unexpected request %s: %#+v", req, r)
if testframework.ServeV2(w, r) ||
testframework.ServeImage(w, r, "remoteimage", imageData, []string{"latest"}) {
return
}
t.Errorf("error: remote registry got unexpected request %s: %#+v", req, r)
http.Error(w, "unable to handle the request", http.StatusInternalServerError)
}))
defer ts.Close()
@@ -128,7 +100,7 @@ func TestPullthroughBlob(t *testing.T) {
ctx := context.Background()
_, err = repo.Blobs(ctx).Get(ctx, fooDigest)
_, err = repo.Blobs(ctx).Get(ctx, imageData.LayerDigest)
if err != distribution.ErrBlobUnknown {
t.Fatal(err)
}

View File

@@ -2,14 +2,12 @@ package integration
import (
"context"
"encoding/json"
"fmt"
"net/http"
"testing"
"time"
"github.com/docker/distribution/registry/storage/driver/inmemory"
digest "github.com/opencontainers/go-digest"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -23,34 +21,11 @@ import (
"github.com/openshift/image-registry/test/internal/storagepath"
)
func TestPullthroughBlob(t *testing.T) {
config := []byte("{}")
configDigest := digest.FromBytes(config)
foo := []byte("foo")
fooDigest := digest.FromBytes(foo)
manifestMediaType := "application/vnd.docker.distribution.manifest.v2+json"
manifest, err := json.Marshal(map[string]interface{}{
"schemaVersion": 2,
"mediaType": manifestMediaType,
"config": map[string]interface{}{
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": len(config),
"digest": configDigest.String(),
},
"layers": []map[string]interface{}{
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": len(foo),
"digest": fooDigest.String(),
},
},
})
func TestOffline(t *testing.T) {
imageData, err := testframework.NewSchema2ImageData()
if err != nil {
t.Fatalf("unable to marshal manifest: %v", err)
t.Fatal(err)
}
manifestDigest := digest.FromBytes(manifest)
remoteRegistryUnavailable := false
ts := testframework.NewHTTPServer(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -65,26 +40,13 @@ func TestPullthroughBlob(t *testing.T) {
return
}
switch req {
case "GET /v2/":
w.Write([]byte(`{}`))
case "GET /v2/remoteimage/manifests/latest", "GET /v2/remoteimage/manifests/" + manifestDigest.String():
w.Header().Set("Content-Type", manifestMediaType)
w.Write(manifest)
case "HEAD /v2/remoteimage/blobs/" + configDigest.String():
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(config)))
w.WriteHeader(http.StatusOK)
case "GET /v2/remoteimage/blobs/" + configDigest.String():
w.Write(config)
case "HEAD /v2/remoteimage/blobs/" + fooDigest.String():
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(foo)))
w.WriteHeader(http.StatusOK)
case "GET /v2/remoteimage/blobs/" + fooDigest.String():
w.Write(foo)
default:
t.Errorf("error: remote registry got unexpected request %s: %#+v", req, r)
http.Error(w, "unable to handle the request", http.StatusInternalServerError)
if testframework.ServeV2(w, r) ||
testframework.ServeImage(w, r, "remoteimage", imageData, []string{"latest"}) {
return
}
t.Errorf("error: remote registry got unexpected request %s: %#+v", req, r)
http.Error(w, "unable to handle the request", http.StatusInternalServerError)
}))
defer ts.Close()
@@ -147,20 +109,20 @@ func TestPullthroughBlob(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if mediatype != manifestMediaType {
t.Fatalf("manifest mediatype: got %q, want %q", mediatype, manifestMediaType)
if mediatype != imageData.ManifestMediaType {
t.Fatalf("manifest mediatype: got %q, want %q", mediatype, imageData.ManifestMediaType)
}
if dgst != manifestDigest {
t.Fatalf("manifest digest: got %q, want %q", dgst, manifestDigest)
if dgst != imageData.ManifestDigest {
t.Fatalf("manifest digest: got %q, want %q", dgst, imageData.ManifestDigest)
}
/* Wait for mirroring to complete */
timeoutContext, timeoutCancel := context.WithTimeout(ctx, 10*time.Second)
if err := driver.WaitFor(
timeoutContext,
storagepath.Layer(testproject.Name+"/"+teststream.Name, configDigest),
storagepath.Layer(testproject.Name+"/"+teststream.Name, fooDigest),
storagepath.Manifest(testproject.Name+"/"+teststream.Name, manifestDigest),
storagepath.Layer(testproject.Name+"/"+teststream.Name, imageData.ConfigDigest),
storagepath.Layer(testproject.Name+"/"+teststream.Name, imageData.LayerDigest),
storagepath.Manifest(testproject.Name+"/"+teststream.Name, imageData.ManifestDigest),
); err != nil {
t.Fatal(err)
}
@@ -174,10 +136,10 @@ func TestPullthroughBlob(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if mediatype != manifestMediaType {
t.Fatalf("manifest mediatype: got %q, want %q", mediatype, manifestMediaType)
if mediatype != imageData.ManifestMediaType {
t.Fatalf("manifest mediatype: got %q, want %q", mediatype, imageData.ManifestMediaType)
}
if dgst != manifestDigest {
t.Fatalf("manifest digest: got %q, want %q", dgst, manifestDigest)
if dgst != imageData.ManifestDigest {
t.Fatalf("manifest digest: got %q, want %q", dgst, imageData.ManifestDigest)
}
}

View File

@@ -2,13 +2,10 @@ package integration
import (
"context"
"encoding/json"
"fmt"
"net/http"
"testing"
digest "github.com/opencontainers/go-digest"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -20,11 +17,10 @@ import (
)
func TestPullthroughBlob(t *testing.T) {
config := "{}"
configDigest := digest.FromBytes([]byte(config))
foo := "foo"
fooDigest := digest.FromBytes([]byte(foo))
imageData, err := testframework.NewSchema2ImageData()
if err != nil {
t.Fatal(err)
}
master := testframework.NewMaster(t)
defer master.Close()
@@ -42,39 +38,13 @@ func TestPullthroughBlob(t *testing.T) {
w.Header().Set("Docker-Distribution-API-Version", "registry/2.0")
switch req {
case "GET /v2/":
w.Write([]byte(`{}`))
case "GET /v2/remoteimage/manifests/latest":
mediaType := "application/vnd.docker.distribution.manifest.v2+json"
w.Header().Set("Content-Type", mediaType)
_ = json.NewEncoder(w).Encode(map[string]interface{}{
"schemaVersion": 2,
"mediaType": mediaType,
"config": map[string]interface{}{
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": len(config),
"digest": configDigest.String(),
},
"layers": []map[string]interface{}{
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": len(foo),
"digest": fooDigest.String(),
},
},
})
case "GET /v2/remoteimage/blobs/" + configDigest.String():
w.Write([]byte(config))
case "HEAD /v2/remoteimage/blobs/" + fooDigest.String():
w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(foo)))
w.WriteHeader(http.StatusOK)
case "GET /v2/remoteimage/blobs/" + fooDigest.String():
w.Write([]byte(foo))
default:
t.Errorf("error: remote registry got unexpected request %s: %#+v", req, r)
if testframework.ServeV2(w, r) ||
testframework.ServeImage(w, r, "remoteimage", imageData, []string{"latest"}) {
return
}
t.Errorf("error: remote registry got unexpected request %s: %#+v", req, r)
http.Error(w, "unable to handle the request", http.StatusInternalServerError)
}))
defer ts.Close()
@@ -113,9 +83,9 @@ func TestPullthroughBlob(t *testing.T) {
}
if diff := requestCounter.Diff(counter.M{
"GET /v2/": 1,
"GET /v2/remoteimage/manifests/latest": 1,
"GET /v2/remoteimage/blobs/" + configDigest.String(): 1,
"GET /v2/": 1,
"GET /v2/remoteimage/manifests/latest": 1,
"GET /v2/remoteimage/blobs/" + imageData.ConfigDigest.String(): 1,
}); diff != nil {
t.Fatalf("unexpected number of requests: %q", diff)
}
@@ -130,20 +100,20 @@ func TestPullthroughBlob(t *testing.T) {
ctx := context.Background()
data, err := repo.Blobs(ctx).Get(ctx, fooDigest)
data, err := repo.Blobs(ctx).Get(ctx, imageData.LayerDigest)
if err != nil {
t.Fatal(err)
}
if string(data) != foo {
t.Fatalf("got %q, want %q", string(data), foo)
if string(data) != string(imageData.Layer) {
t.Fatalf("got %q, want %q", string(data), string(imageData.Layer))
}
// TODO(dmage): remove the HEAD request
if diff := requestCounter.Diff(counter.M{
"GET /v2/": 1,
"HEAD /v2/remoteimage/blobs/" + fooDigest.String(): 1,
"GET /v2/remoteimage/blobs/" + fooDigest.String(): 1,
"HEAD /v2/remoteimage/blobs/" + imageData.LayerDigest.String(): 1,
"GET /v2/remoteimage/blobs/" + imageData.LayerDigest.String(): 1,
}); diff != nil {
t.Fatalf("unexpected number of requests: %q", diff)
}