mirror of
https://github.com/openshift/image-registry.git
synced 2026-02-05 09:45:55 +01:00
Merge pull request #353 from flavianmissi/IR-264
IR-264: add basic tests for hard pruner
This commit is contained in:
179
pkg/dockerregistry/server/prune/prune_test.go
Normal file
179
pkg/dockerregistry/server/prune/prune_test.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package prune
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/manifest/schema1"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/distribution/registry/storage"
|
||||
"github.com/docker/distribution/registry/storage/driver/inmemory"
|
||||
"github.com/opencontainers/go-digest"
|
||||
imageapiv1 "github.com/openshift/api/image/v1"
|
||||
registryclient "github.com/openshift/image-registry/pkg/dockerregistry/server/client"
|
||||
"github.com/openshift/image-registry/pkg/testutil"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func makeRepoRef(t *testing.T, namespace, name string) reference.Named {
|
||||
refName := fmt.Sprintf("%s/%s", namespace, name)
|
||||
parsed, err := reference.Parse(refName)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to parse reference %q: %v", refName, err)
|
||||
}
|
||||
ref, ok := parsed.(reference.Named)
|
||||
if !ok {
|
||||
t.Fatalf("expected Named reference, not %T", parsed)
|
||||
}
|
||||
return ref
|
||||
}
|
||||
|
||||
func makeNamedTaggedRef(t *testing.T, namespace, name, tag string) reference.NamedTagged {
|
||||
refName := fmt.Sprintf("%s/%s:%s", namespace, name, tag)
|
||||
parsed, err := reference.Parse(refName)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to parse reference %q: %v", refName, err)
|
||||
}
|
||||
namedTagged, ok := parsed.(reference.NamedTagged)
|
||||
if !ok {
|
||||
t.Fatalf("expected NamedTagged reference, not %T", parsed)
|
||||
}
|
||||
return namedTagged
|
||||
}
|
||||
|
||||
func createBlob(
|
||||
ctx context.Context,
|
||||
t *testing.T,
|
||||
reg distribution.Namespace,
|
||||
namespace, name, tag string,
|
||||
) distribution.Descriptor {
|
||||
namedTagged := makeNamedTaggedRef(t, namespace, name, tag)
|
||||
repo, err := reg.Repository(ctx, namedTagged)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting repo %q: %v", namedTagged.Name(), err)
|
||||
}
|
||||
payload, blobDesc, err := testutil.MakeRandomLayer()
|
||||
wr, err := repo.Blobs(ctx).Create(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error creating test upload: %v", err)
|
||||
}
|
||||
defer wr.Close()
|
||||
_, err = io.Copy(wr, bytes.NewReader(payload))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error copying to upload: %v", err)
|
||||
}
|
||||
dgst := digest.FromBytes(payload)
|
||||
if _, err := wr.Commit(ctx, distribution.Descriptor{Digest: dgst, MediaType: schema1.MediaTypeManifestLayer}); err != nil {
|
||||
t.Fatalf("unexpected error finishing upload: %v", err)
|
||||
}
|
||||
return blobDesc
|
||||
}
|
||||
|
||||
func populateRegistry(
|
||||
ctx context.Context,
|
||||
t *testing.T,
|
||||
fos *testutil.FakeOpenShift,
|
||||
reg distribution.Namespace,
|
||||
namespace, name, tag string,
|
||||
) *imageapiv1.Image {
|
||||
blobDesc := createBlob(ctx, t, reg, namespace, name, tag)
|
||||
|
||||
shasum := "sha256:83c0e63f5efb64cba26be647e93bf036b8d88b774f0726936c1b956424b1abf6"
|
||||
remoteRef := "registry.redhat.io/ubi8/ubi"
|
||||
is := &imageapiv1.ImageStream{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: imageapiv1.ImageStreamSpec{
|
||||
LookupPolicy: imageapiv1.ImageLookupPolicy{Local: false},
|
||||
Tags: []imageapiv1.TagReference{
|
||||
{
|
||||
Name: tag,
|
||||
From: &corev1.ObjectReference{
|
||||
Kind: "DockerImage",
|
||||
Name: fmt.Sprintf("%s:%s", remoteRef, tag),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: imageapiv1.ImageStreamStatus{
|
||||
Tags: []imageapiv1.NamedTagEventList{
|
||||
{
|
||||
Tag: tag,
|
||||
Items: []imageapiv1.TagEvent{
|
||||
{
|
||||
Created: metav1.NewTime(time.Now()),
|
||||
DockerImageReference: fmt.Sprintf("%s@%s", remoteRef, shasum),
|
||||
Image: shasum,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
is, err := fos.CreateImageStream(namespace, is)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not create image stream: %v", err)
|
||||
}
|
||||
|
||||
image := &imageapiv1.Image{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: shasum,
|
||||
},
|
||||
DockerImageLayers: []imageapiv1.ImageLayer{
|
||||
{
|
||||
Name: blobDesc.Digest.String(),
|
||||
LayerSize: blobDesc.Size,
|
||||
MediaType: blobDesc.MediaType,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
image, err = fos.CreateImage(image)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not create image: %v", err)
|
||||
}
|
||||
|
||||
return image
|
||||
}
|
||||
|
||||
func TestPrune(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ctx = testutil.WithTestLogger(ctx, t)
|
||||
storageDriver := inmemory.New()
|
||||
fos, imageClient := testutil.NewFakeOpenShiftWithClient(ctx)
|
||||
reg, err := storage.NewRegistry(ctx, storageDriver)
|
||||
if err != nil {
|
||||
t.Fatalf("error creating registry: %v", err)
|
||||
}
|
||||
|
||||
image1 := populateRegistry(ctx, t, fos, reg, "ns-test", "is-test", "latest")
|
||||
danglingBlob := createBlob(ctx, t, reg, "ns-test", "this-is-has-been-deleted", "latest")
|
||||
|
||||
pruner := &RegistryPruner{StorageDriver: storageDriver}
|
||||
_, err = Prune(ctx, reg, registryclient.NewFakeRegistryClient(imageClient), pruner)
|
||||
if err != nil {
|
||||
t.Fatalf("error calling Prune: %s", err)
|
||||
}
|
||||
|
||||
statter := reg.BlobStatter()
|
||||
for _, blob := range image1.DockerImageLayers {
|
||||
_, err := statter.Stat(ctx, digest.Digest(blob.Name))
|
||||
if err != nil {
|
||||
t.Errorf("error retrieving blob %q: %#v", blob.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = statter.Stat(ctx, danglingBlob.Digest)
|
||||
if err != distribution.ErrBlobUnknown {
|
||||
t.Errorf("expected error to be distribution.ErrBlobUnknown, got %#v", err)
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,25 @@ func (fos *FakeOpenShift) GetImage(name string) (*imageapiv1.Image, error) {
|
||||
return &image, nil
|
||||
}
|
||||
|
||||
func (fos *FakeOpenShift) ListImages(namespace string) (*imageapiv1.ImageList, error) {
|
||||
fos.mu.Lock()
|
||||
defer fos.mu.Unlock()
|
||||
|
||||
imageList := imageapiv1.ImageList{
|
||||
ListMeta: metav1.ListMeta{},
|
||||
Items: []imageapiv1.Image{},
|
||||
}
|
||||
|
||||
for _, image := range fos.images {
|
||||
if len(namespace) != 0 && namespace != image.Namespace {
|
||||
continue
|
||||
}
|
||||
imageList.Items = append(imageList.Items, image)
|
||||
}
|
||||
|
||||
return &imageList, nil
|
||||
}
|
||||
|
||||
func (fos *FakeOpenShift) UpdateImage(image *imageapiv1.Image) (*imageapiv1.Image, error) {
|
||||
fos.mu.Lock()
|
||||
defer fos.mu.Unlock()
|
||||
@@ -446,6 +465,9 @@ func (fos *FakeOpenShift) imagesHandler(action clientgotesting.Action) (bool, ru
|
||||
case clientgotesting.GetActionImpl:
|
||||
image, err := fos.GetImage(action.Name)
|
||||
return true, image, err
|
||||
case clientgotesting.ListActionImpl:
|
||||
images, err := fos.ListImages(action.GetNamespace())
|
||||
return true, images, err
|
||||
case clientgotesting.UpdateActionImpl:
|
||||
image, err := fos.UpdateImage(
|
||||
action.Object.(*imageapiv1.Image),
|
||||
|
||||
Reference in New Issue
Block a user