forked from TrueCloudLab/distribution
Remove references to schema1 pacakge from notifications package
Schema1 package was deprecated a while ago but it's wildly referenced thrhougout distribution codebase. Signed-off-by: Milos Gajdos <milosthegajdos@gmail.com>
This commit is contained in:
parent
69fe169013
commit
565dafa48c
5 changed files with 123 additions and 97 deletions
|
@ -4,13 +4,14 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/manifest/schema1" //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
"github.com/distribution/distribution/v3/manifest"
|
||||||
|
"github.com/distribution/distribution/v3/manifest/schema2"
|
||||||
"github.com/distribution/distribution/v3/reference"
|
"github.com/distribution/distribution/v3/reference"
|
||||||
v2 "github.com/distribution/distribution/v3/registry/api/v2"
|
v2 "github.com/distribution/distribution/v3/registry/api/v2"
|
||||||
"github.com/distribution/distribution/v3/uuid"
|
"github.com/distribution/distribution/v3/uuid"
|
||||||
events "github.com/docker/go-events"
|
events "github.com/docker/go-events"
|
||||||
"github.com/docker/libtrust"
|
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
|
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -27,21 +28,16 @@ var (
|
||||||
Name: "test",
|
Name: "test",
|
||||||
}
|
}
|
||||||
request = RequestRecord{}
|
request = RequestRecord{}
|
||||||
layers = []schema1.FSLayer{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
tag = "latest"
|
||||||
{
|
ociMediaType = v1.MediaTypeImageManifest
|
||||||
BlobSum: "asdf",
|
artifactType = "application/vnd.example.sbom.v1"
|
||||||
},
|
cfg = distribution.Descriptor{
|
||||||
{
|
MediaType: artifactType,
|
||||||
BlobSum: "qwer",
|
Size: 100,
|
||||||
},
|
Digest: "cfgdgst",
|
||||||
}
|
|
||||||
m = schema1.Manifest{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
|
||||||
Name: repo,
|
|
||||||
Tag: "latest",
|
|
||||||
FSLayers: layers,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sm *schema1.SignedManifest //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
sm *schema2.DeserializedManifest
|
||||||
payload []byte
|
payload []byte
|
||||||
dgst digest.Digest
|
dgst digest.Digest
|
||||||
)
|
)
|
||||||
|
@ -83,7 +79,7 @@ func TestEventBridgeManifestPushedWithTag(t *testing.T) {
|
||||||
}))
|
}))
|
||||||
|
|
||||||
repoRef, _ := reference.WithName(repo)
|
repoRef, _ := reference.WithName(repo)
|
||||||
if err := l.ManifestPushed(repoRef, sm, distribution.WithTag(m.Tag)); err != nil {
|
if err := l.ManifestPushed(repoRef, sm, distribution.WithTag(tag)); err != nil {
|
||||||
t.Fatalf("unexpected error notifying manifest pull: %v", err)
|
t.Fatalf("unexpected error notifying manifest pull: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +95,7 @@ func TestEventBridgeManifestPulledWithTag(t *testing.T) {
|
||||||
}))
|
}))
|
||||||
|
|
||||||
repoRef, _ := reference.WithName(repo)
|
repoRef, _ := reference.WithName(repo)
|
||||||
if err := l.ManifestPulled(repoRef, sm, distribution.WithTag(m.Tag)); err != nil {
|
if err := l.ManifestPulled(repoRef, sm, distribution.WithTag(tag)); err != nil {
|
||||||
t.Fatalf("unexpected error notifying manifest pull: %v", err)
|
t.Fatalf("unexpected error notifying manifest pull: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,14 +118,14 @@ func TestEventBridgeManifestDeleted(t *testing.T) {
|
||||||
func TestEventBridgeTagDeleted(t *testing.T) {
|
func TestEventBridgeTagDeleted(t *testing.T) {
|
||||||
l := createTestEnv(t, testSinkFn(func(event events.Event) error {
|
l := createTestEnv(t, testSinkFn(func(event events.Event) error {
|
||||||
checkDeleted(t, EventActionDelete, event)
|
checkDeleted(t, EventActionDelete, event)
|
||||||
if event.(Event).Target.Tag != m.Tag {
|
if event.(Event).Target.Tag != tag {
|
||||||
t.Fatalf("unexpected tag on event target: %q != %q", event.(Event).Target.Tag, m.Tag)
|
t.Fatalf("unexpected tag on event target: %q != %q", event.(Event).Target.Tag, tag)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}))
|
}))
|
||||||
|
|
||||||
repoRef, _ := reference.WithName(repo)
|
repoRef, _ := reference.WithName(repo)
|
||||||
if err := l.TagDeleted(repoRef, m.Tag); err != nil {
|
if err := l.TagDeleted(repoRef, tag); err != nil {
|
||||||
t.Fatalf("unexpected error notifying tag deletion: %v", err)
|
t.Fatalf("unexpected error notifying tag deletion: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,18 +143,21 @@ func TestEventBridgeRepoDeleted(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestEnv(t *testing.T, fn testSinkFn) Listener {
|
func createTestEnv(t *testing.T, fn testSinkFn) Listener {
|
||||||
pk, err := libtrust.GenerateECP256PrivateKey()
|
manifest := schema2.Manifest{
|
||||||
if err != nil {
|
Versioned: manifest.Versioned{
|
||||||
t.Fatalf("error generating private key: %v", err)
|
MediaType: ociMediaType,
|
||||||
|
},
|
||||||
|
Config: cfg,
|
||||||
}
|
}
|
||||||
|
|
||||||
sm, err = schema1.Sign(&m, pk) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
deserializedManifest, err := schema2.FromStruct(manifest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error signing manifest: %v", err)
|
t.Fatalf("creating OCI manifest: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
payload = sm.Canonical
|
_, payload, _ = deserializedManifest.Payload()
|
||||||
dgst = digest.FromBytes(payload)
|
dgst = digest.FromBytes(payload)
|
||||||
|
sm = deserializedManifest
|
||||||
|
|
||||||
return NewBridge(ub, source, actor, request, fn, true)
|
return NewBridge(ub, source, actor, request, fn, true)
|
||||||
}
|
}
|
||||||
|
@ -198,15 +197,6 @@ func checkCommonManifest(t *testing.T, action string, event events.Event) {
|
||||||
if event.(Event).Target.URL != u {
|
if event.(Event).Target.URL != u {
|
||||||
t.Fatalf("incorrect url passed: \n%q != \n%q", event.(Event).Target.URL, u)
|
t.Fatalf("incorrect url passed: \n%q != \n%q", event.(Event).Target.URL, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(event.(Event).Target.References) != len(layers) {
|
|
||||||
t.Fatalf("unexpected number of references %v != %v", len(event.(Event).Target.References), len(layers))
|
|
||||||
}
|
|
||||||
for i, targetReference := range event.(Event).Target.References {
|
|
||||||
if targetReference.Digest != layers[i].BlobSum {
|
|
||||||
t.Fatalf("unexpected reference: %q != %q", targetReference.Digest, layers[i].BlobSum)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkCommon(t *testing.T, event events.Event) {
|
func checkCommon(t *testing.T, event events.Event) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3/manifest/schema1" //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
"github.com/distribution/distribution/v3/manifest/schema2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestEventJSONFormat provides silly test to detect if the event format or
|
// TestEventJSONFormat provides silly test to detect if the event format or
|
||||||
|
@ -21,7 +21,7 @@ func TestEventEnvelopeJSONFormat(t *testing.T) {
|
||||||
"timestamp": "2006-01-02T15:04:05Z",
|
"timestamp": "2006-01-02T15:04:05Z",
|
||||||
"action": "push",
|
"action": "push",
|
||||||
"target": {
|
"target": {
|
||||||
"mediaType": "application/vnd.docker.distribution.manifest.v1+prettyjws",
|
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||||
"digest": "sha256:0123456789abcdef0",
|
"digest": "sha256:0123456789abcdef0",
|
||||||
"size": 1,
|
"size": 1,
|
||||||
"length": 1,
|
"length": 1,
|
||||||
|
@ -116,7 +116,7 @@ func TestEventEnvelopeJSONFormat(t *testing.T) {
|
||||||
|
|
||||||
manifestPush := prototype
|
manifestPush := prototype
|
||||||
manifestPush.ID = "asdf-asdf-asdf-asdf-0"
|
manifestPush.ID = "asdf-asdf-asdf-asdf-0"
|
||||||
manifestPush.Target.MediaType = schema1.MediaTypeSignedManifest //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
manifestPush.Target.MediaType = schema2.MediaTypeManifest
|
||||||
manifestPush.Target.Digest = "sha256:0123456789abcdef0"
|
manifestPush.Target.Digest = "sha256:0123456789abcdef0"
|
||||||
manifestPush.Target.Size = 1
|
manifestPush.Target.Size = 1
|
||||||
manifestPush.Target.Length = 1
|
manifestPush.Target.Length = 1
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3/manifest/schema1" //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
"github.com/distribution/distribution/v3/manifest/schema2"
|
||||||
events "github.com/docker/go-events"
|
events "github.com/docker/go-events"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -121,11 +121,11 @@ func TestHTTPSink(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
statusCode: http.StatusOK,
|
statusCode: http.StatusOK,
|
||||||
event: createTestEvent("push", "library/test", schema1.MediaTypeSignedManifest), //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
event: createTestEvent("push", "library/test", schema2.MediaTypeManifest),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
statusCode: http.StatusOK,
|
statusCode: http.StatusOK,
|
||||||
event: createTestEvent("push", "library/test", schema1.MediaTypeSignedManifest), //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
event: createTestEvent("push", "library/test", schema2.MediaTypeManifest),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
statusCode: http.StatusOK,
|
statusCode: http.StatusOK,
|
||||||
|
|
|
@ -1,31 +1,27 @@
|
||||||
package notifications
|
package notifications
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"bytes"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/distribution/distribution/v3"
|
"github.com/distribution/distribution/v3"
|
||||||
"github.com/distribution/distribution/v3/context"
|
dcontext "github.com/distribution/distribution/v3/context"
|
||||||
"github.com/distribution/distribution/v3/manifest"
|
"github.com/distribution/distribution/v3/manifest/schema2"
|
||||||
"github.com/distribution/distribution/v3/manifest/schema1" //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
|
||||||
"github.com/distribution/distribution/v3/reference"
|
"github.com/distribution/distribution/v3/reference"
|
||||||
"github.com/distribution/distribution/v3/registry/storage"
|
"github.com/distribution/distribution/v3/registry/storage"
|
||||||
"github.com/distribution/distribution/v3/registry/storage/cache/memory"
|
"github.com/distribution/distribution/v3/registry/storage/cache/memory"
|
||||||
"github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
|
"github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
|
||||||
"github.com/distribution/distribution/v3/testutil"
|
"github.com/distribution/distribution/v3/testutil"
|
||||||
"github.com/docker/libtrust"
|
|
||||||
"github.com/opencontainers/go-digest"
|
"github.com/opencontainers/go-digest"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestListener(t *testing.T) {
|
func TestListener(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := dcontext.Background()
|
||||||
k, err := libtrust.GenerateECP256PrivateKey()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
registry, err := storage.NewRegistry(ctx, inmemory.New(), storage.BlobDescriptorCacheProvider(memory.NewInMemoryBlobDescriptorCacheProvider(memory.UnlimitedSize)), storage.EnableDelete, storage.EnableRedirect, storage.Schema1SigningKey(k), storage.EnableSchema1)
|
registry, err := storage.NewRegistry(ctx, inmemory.New(),
|
||||||
|
storage.BlobDescriptorCacheProvider(memory.NewInMemoryBlobDescriptorCacheProvider(memory.UnlimitedSize)),
|
||||||
|
storage.EnableDelete, storage.EnableRedirect)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error creating registry: %v", err)
|
t.Fatalf("error creating registry: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -46,15 +42,15 @@ func TestListener(t *testing.T) {
|
||||||
repository, remover = Listen(repository, remover, tl)
|
repository, remover = Listen(repository, remover, tl)
|
||||||
|
|
||||||
// Now take the registry through a number of operations
|
// Now take the registry through a number of operations
|
||||||
checkExerciseRepository(t, repository, remover)
|
checkTestRepository(t, repository, remover)
|
||||||
|
|
||||||
expectedOps := map[string]int{
|
expectedOps := map[string]int{
|
||||||
"manifest:push": 1,
|
"manifest:push": 1,
|
||||||
"manifest:pull": 1,
|
"manifest:pull": 1,
|
||||||
"manifest:delete": 1,
|
"manifest:delete": 1,
|
||||||
"layer:push": 2,
|
"layer:push": 3,
|
||||||
"layer:pull": 2,
|
"layer:pull": 3,
|
||||||
"layer:delete": 2,
|
"layer:delete": 3,
|
||||||
"tag:delete": 1,
|
"tag:delete": 1,
|
||||||
"repo:delete": 1,
|
"repo:delete": 1,
|
||||||
}
|
}
|
||||||
|
@ -113,28 +109,47 @@ func (tl *testListener) RepoDeleted(repo reference.Named) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkExerciseRegistry takes the registry through all of its operations,
|
// checkTestRepository takes the registry through all of its operations,
|
||||||
// carrying out generic checks.
|
// carrying out generic checks.
|
||||||
func checkExerciseRepository(t *testing.T, repository distribution.Repository, remover distribution.RepositoryRemover) {
|
func checkTestRepository(t *testing.T, repository distribution.Repository, remover distribution.RepositoryRemover) {
|
||||||
// TODO(stevvooe): This would be a nice testutil function. Basically, it
|
// TODO(stevvooe): This would be a nice testutil function. Basically, it
|
||||||
// takes the registry through a common set of operations. This could be
|
// takes the registry through a common set of operations. This could be
|
||||||
// used to make cross-cutting updates by changing internals that affect
|
// used to make cross-cutting updates by changing internals that affect
|
||||||
// update counts. Basically, it would make writing tests a lot easier.
|
// update counts. Basically, it would make writing tests a lot easier.
|
||||||
|
// TODO: change this to use Builder
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := dcontext.Background()
|
||||||
tag := "thetag"
|
tag := "thetag"
|
||||||
// todo: change this to use Builder
|
|
||||||
|
|
||||||
m := schema1.Manifest{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
config := []byte(`{"name": "foo"}`)
|
||||||
Versioned: manifest.Versioned{
|
configDgst := digest.FromBytes(config)
|
||||||
SchemaVersion: 1,
|
configReader := bytes.NewReader(config)
|
||||||
},
|
|
||||||
Name: repository.Named().Name(),
|
|
||||||
Tag: tag,
|
|
||||||
}
|
|
||||||
|
|
||||||
var blobDigests []digest.Digest
|
var blobDigests []digest.Digest
|
||||||
|
blobDigests = append(blobDigests, configDgst)
|
||||||
|
|
||||||
blobs := repository.Blobs(ctx)
|
blobs := repository.Blobs(ctx)
|
||||||
|
|
||||||
|
// push config blob
|
||||||
|
if err := testutil.PushBlob(ctx, repository, configReader, configDgst); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then fetch the config blob
|
||||||
|
if rc, err := blobs.Open(ctx, configDgst); err != nil {
|
||||||
|
t.Fatalf("error fetching config: %v", err)
|
||||||
|
} else {
|
||||||
|
defer rc.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
m := schema2.Manifest{
|
||||||
|
Versioned: schema2.SchemaVersion,
|
||||||
|
Config: distribution.Descriptor{
|
||||||
|
MediaType: "foo/bar",
|
||||||
|
Digest: configDgst,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
rs, dgst, err := testutil.CreateRandomTarFile()
|
rs, dgst, err := testutil.CreateRandomTarFile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -142,28 +157,13 @@ func checkExerciseRepository(t *testing.T, repository distribution.Repository, r
|
||||||
}
|
}
|
||||||
blobDigests = append(blobDigests, dgst)
|
blobDigests = append(blobDigests, dgst)
|
||||||
|
|
||||||
wr, err := blobs.Create(ctx)
|
if err := testutil.PushBlob(ctx, repository, rs, dgst); err != nil {
|
||||||
if err != nil {
|
t.Fatal(err)
|
||||||
t.Fatalf("error creating layer upload: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the resumes, as well!
|
m.Layers = append(m.Layers, distribution.Descriptor{
|
||||||
wr, err = blobs.Resume(ctx, wr.ID())
|
MediaType: "application/octet-stream",
|
||||||
if err != nil {
|
Digest: dgst,
|
||||||
t.Fatalf("error resuming layer upload: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
io.Copy(wr, rs)
|
|
||||||
|
|
||||||
if _, err := wr.Commit(ctx, distribution.Descriptor{Digest: dgst}); err != nil {
|
|
||||||
t.Fatalf("unexpected error finishing upload: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
m.FSLayers = append(m.FSLayers, schema1.FSLayer{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
|
||||||
BlobSum: dgst,
|
|
||||||
})
|
|
||||||
m.History = append(m.History, schema1.History{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
|
||||||
V1Compatibility: "",
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Then fetch the blobs
|
// Then fetch the blobs
|
||||||
|
@ -174,14 +174,9 @@ func checkExerciseRepository(t *testing.T, repository distribution.Repository, r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pk, err := libtrust.GenerateECP256PrivateKey()
|
sm, err := schema2.FromStruct(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error generating key: %v", err)
|
t.Fatal(err.Error())
|
||||||
}
|
|
||||||
|
|
||||||
sm, err := schema1.Sign(&m, pk) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error signing manifest: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
manifests, err := repository.Manifests(ctx)
|
manifests, err := repository.Manifests(ctx)
|
||||||
|
@ -194,7 +189,12 @@ func checkExerciseRepository(t *testing.T, repository distribution.Repository, r
|
||||||
t.Fatalf("unexpected error putting the manifest: %v", err)
|
t.Fatalf("unexpected error putting the manifest: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dgst := digest.FromBytes(sm.Canonical)
|
_, canonical, err := sm.Payload()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
dgst := digest.FromBytes(canonical)
|
||||||
if dgst != digestPut {
|
if dgst != digestPut {
|
||||||
t.Fatalf("mismatching digest from payload and put")
|
t.Fatalf("mismatching digest from payload and put")
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ func checkExerciseRepository(t *testing.T, repository distribution.Repository, r
|
||||||
t.Fatalf("unexpected error fetching manifest: %v", err)
|
t.Fatalf("unexpected error fetching manifest: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = repository.Tags(ctx).Untag(ctx, m.Tag)
|
err = repository.Tags(ctx).Untag(ctx, tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error deleting tag: %v", err)
|
t.Fatalf("unexpected error deleting tag: %v", err)
|
||||||
}
|
}
|
||||||
|
|
36
testutil/push.go
Normal file
36
testutil/push.go
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
package testutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/distribution/distribution/v3"
|
||||||
|
"github.com/opencontainers/go-digest"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PushBlob pushes a blob with the given digest to the given repository.
|
||||||
|
func PushBlob(ctx context.Context, repository distribution.Repository, blobReader io.ReadSeeker, dgst digest.Digest) error {
|
||||||
|
blobs := repository.Blobs(ctx)
|
||||||
|
|
||||||
|
wr, err := blobs.Create(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error creating layer upload: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the resumes, as well!
|
||||||
|
wr, err = blobs.Resume(ctx, wr.ID())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error resuming layer upload: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.Copy(wr, blobReader); err != nil {
|
||||||
|
return fmt.Errorf("unexpected error uploading: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := wr.Commit(ctx, distribution.Descriptor{Digest: dgst}); err != nil {
|
||||||
|
return fmt.Errorf("unexpected error finishing upload: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue