Merge pull request #4007 from milosgajdos/remove-schema1-client
This commit is contained in:
commit
1a4638a06c
1 changed files with 74 additions and 101 deletions
|
@ -19,14 +19,14 @@ import (
|
|||
"github.com/distribution/distribution/v3"
|
||||
"github.com/distribution/distribution/v3/context"
|
||||
"github.com/distribution/distribution/v3/manifest"
|
||||
"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/ocischema"
|
||||
"github.com/distribution/distribution/v3/reference"
|
||||
"github.com/distribution/distribution/v3/registry/api/errcode"
|
||||
v2 "github.com/distribution/distribution/v3/registry/api/v2"
|
||||
"github.com/distribution/distribution/v3/testutil"
|
||||
"github.com/distribution/distribution/v3/uuid"
|
||||
"github.com/docker/libtrust"
|
||||
"github.com/opencontainers/go-digest"
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
func testServer(rrm testutil.RequestResponseMap) (string, func()) {
|
||||
|
@ -917,39 +917,38 @@ func TestBlobMount(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func newRandomSchemaV1Manifest(name reference.Named, tag string, blobCount int) (*schema1.SignedManifest, digest.Digest, []byte) { //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
blobs := make([]schema1.FSLayer, blobCount) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
history := make([]schema1.History, blobCount) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
|
||||
func newRandomOCIManifest(t *testing.T, blobCount int) (*ocischema.Manifest, digest.Digest, []byte) {
|
||||
layers := make([]distribution.Descriptor, blobCount)
|
||||
for i := 0; i < blobCount; i++ {
|
||||
dgst, blob := newRandomBlob((i % 5) * 16)
|
||||
|
||||
blobs[i] = schema1.FSLayer{BlobSum: dgst} //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
history[i] = schema1.History{V1Compatibility: fmt.Sprintf("{\"Hex\": \"%x\"}", blob)} //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
layers[i] = distribution.Descriptor{
|
||||
MediaType: v1.MediaTypeImageLayer,
|
||||
Digest: dgst,
|
||||
Size: int64(len(blob)),
|
||||
}
|
||||
}
|
||||
|
||||
m := schema1.Manifest{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
Name: name.String(),
|
||||
Tag: tag,
|
||||
Architecture: "x86",
|
||||
FSLayers: blobs,
|
||||
History: history,
|
||||
m := ocischema.Manifest{
|
||||
Versioned: manifest.Versioned{
|
||||
SchemaVersion: 1,
|
||||
SchemaVersion: 2,
|
||||
MediaType: v1.MediaTypeImageManifest,
|
||||
},
|
||||
Config: distribution.Descriptor{
|
||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||
Size: 123,
|
||||
MediaType: v1.MediaTypeImageConfig,
|
||||
},
|
||||
Layers: layers,
|
||||
}
|
||||
|
||||
pk, err := libtrust.GenerateECP256PrivateKey()
|
||||
sm, err := ocischema.FromStruct(m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
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 {
|
||||
panic(err)
|
||||
}
|
||||
_, payload, _ := sm.Payload()
|
||||
|
||||
return sm, digest.FromBytes(sm.Canonical), sm.Canonical
|
||||
return &m, digest.FromBytes(payload), payload
|
||||
}
|
||||
|
||||
func addTestManifestWithEtag(repo reference.Named, reference string, content []byte, m *testutil.RequestResponseMap, dgst string) {
|
||||
|
@ -970,7 +969,7 @@ func addTestManifestWithEtag(repo reference.Named, reference string, content []b
|
|||
Headers: http.Header(map[string][]string{
|
||||
"Content-Length": {"0"},
|
||||
"Last-Modified": {time.Now().Add(-1 * time.Second).Format(time.ANSIC)},
|
||||
"Content-Type": {schema1.MediaTypeSignedManifest}, //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
"Content-Type": {v1.MediaTypeImageManifest},
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
|
@ -980,21 +979,13 @@ func addTestManifestWithEtag(repo reference.Named, reference string, content []b
|
|||
Headers: http.Header(map[string][]string{
|
||||
"Content-Length": {fmt.Sprint(len(content))},
|
||||
"Last-Modified": {time.Now().Add(-1 * time.Second).Format(time.ANSIC)},
|
||||
"Content-Type": {schema1.MediaTypeSignedManifest}, //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
"Content-Type": {v1.MediaTypeImageManifest},
|
||||
}),
|
||||
}
|
||||
}
|
||||
*m = append(*m, testutil.RequestResponseMapping{Request: getReqWithEtag, Response: getRespWithEtag})
|
||||
}
|
||||
|
||||
func contentDigestString(mediatype string, content []byte) string {
|
||||
if mediatype == schema1.MediaTypeSignedManifest { //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
m, _, _ := distribution.UnmarshalManifest(mediatype, content)
|
||||
content = m.(*schema1.SignedManifest).Canonical //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
}
|
||||
return digest.Canonical.FromBytes(content).String()
|
||||
}
|
||||
|
||||
func addTestManifest(repo reference.Named, reference string, mediatype string, content []byte, m *testutil.RequestResponseMap) {
|
||||
*m = append(*m, testutil.RequestResponseMapping{
|
||||
Request: testutil.Request{
|
||||
|
@ -1008,7 +999,7 @@ func addTestManifest(repo reference.Named, reference string, mediatype string, c
|
|||
"Content-Length": {fmt.Sprint(len(content))},
|
||||
"Last-Modified": {time.Now().Add(-1 * time.Second).Format(time.ANSIC)},
|
||||
"Content-Type": {mediatype},
|
||||
"Docker-Content-Digest": {contentDigestString(mediatype, content)},
|
||||
"Docker-Content-Digest": {digest.FromBytes(content).String()},
|
||||
}),
|
||||
},
|
||||
})
|
||||
|
@ -1061,43 +1052,27 @@ func addTestManifestWithoutDigestHeader(repo reference.Named, reference string,
|
|||
})
|
||||
}
|
||||
|
||||
func checkEqualManifest(m1, m2 *schema1.SignedManifest) error { //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
if m1.Name != m2.Name {
|
||||
return fmt.Errorf("name does not match %q != %q", m1.Name, m2.Name)
|
||||
func checkEqualManifest(m1, m2 *ocischema.DeserializedManifest) error {
|
||||
if !reflect.DeepEqual(m1.Versioned, m2.Versioned) {
|
||||
return fmt.Errorf("versions do not match: %v != %v", m1.Versioned, m2.Versioned)
|
||||
}
|
||||
if m1.Tag != m2.Tag {
|
||||
return fmt.Errorf("tag does not match %q != %q", m1.Tag, m2.Tag)
|
||||
}
|
||||
if len(m1.FSLayers) != len(m2.FSLayers) {
|
||||
return fmt.Errorf("fs blob length does not match %d != %d", len(m1.FSLayers), len(m2.FSLayers))
|
||||
}
|
||||
for i := range m1.FSLayers {
|
||||
if m1.FSLayers[i].BlobSum != m2.FSLayers[i].BlobSum {
|
||||
return fmt.Errorf("blobsum does not match %q != %q", m1.FSLayers[i].BlobSum, m2.FSLayers[i].BlobSum)
|
||||
}
|
||||
}
|
||||
if len(m1.History) != len(m2.History) {
|
||||
return fmt.Errorf("history length does not match %d != %d", len(m1.History), len(m2.History))
|
||||
}
|
||||
for i := range m1.History {
|
||||
if m1.History[i].V1Compatibility != m2.History[i].V1Compatibility {
|
||||
return fmt.Errorf("blobsum does not match %q != %q", m1.History[i].V1Compatibility, m2.History[i].V1Compatibility)
|
||||
if !reflect.DeepEqual(m1.Config, m2.Config) {
|
||||
return fmt.Errorf("config do not match: %v != %v", m1.Config, m2.Config)
|
||||
}
|
||||
if !reflect.DeepEqual(m1.Layers, m2.Layers) {
|
||||
return fmt.Errorf("layers do not match: %v != %v", m1.Layers, m2.Layers)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestV1ManifestFetch(t *testing.T) {
|
||||
func TestOCIManifestFetch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
repo, _ := reference.WithName("test.example.com/repo")
|
||||
m1, dgst, _ := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
m1, dgst, pl := newRandomOCIManifest(t, 6)
|
||||
var m testutil.RequestResponseMap
|
||||
_, pl, err := m1.Payload() //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
addTestManifest(repo, dgst.String(), schema1.MediaTypeSignedManifest, pl, &m) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
addTestManifest(repo, "latest", schema1.MediaTypeSignedManifest, pl, &m) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
addTestManifest(repo, dgst.String(), v1.MediaTypeImageManifest, pl, &m)
|
||||
addTestManifest(repo, "latest", v1.MediaTypeImageManifest, pl, &m)
|
||||
addTestManifest(repo, "badcontenttype", "text/html", pl, &m)
|
||||
|
||||
e, c := testServer(m)
|
||||
|
@ -1124,12 +1099,17 @@ func TestV1ManifestFetch(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
v1manifest, ok := manifest.(*schema1.SignedManifest) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
ociManifest, ok := manifest.(*ocischema.DeserializedManifest)
|
||||
if !ok {
|
||||
t.Fatalf("Unexpected manifest type from Get: %T", manifest)
|
||||
}
|
||||
|
||||
if err := checkEqualManifest(v1manifest, m1); err != nil {
|
||||
dm1, err := ocischema.FromStruct(*m1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := checkEqualManifest(ociManifest, dm1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -1138,12 +1118,12 @@ func TestV1ManifestFetch(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
v1manifest, ok = manifest.(*schema1.SignedManifest) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
ociManifest, ok = manifest.(*ocischema.DeserializedManifest)
|
||||
if !ok {
|
||||
t.Fatalf("Unexpected manifest type from Get: %T", manifest)
|
||||
}
|
||||
|
||||
if err = checkEqualManifest(v1manifest, m1); err != nil {
|
||||
if err = checkEqualManifest(ociManifest, dm1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -1151,23 +1131,19 @@ func TestV1ManifestFetch(t *testing.T) {
|
|||
t.Fatalf("Unexpected returned content digest %v, expected %v", contentDigest, dgst)
|
||||
}
|
||||
|
||||
manifest, err = ms.Get(ctx, dgst, distribution.WithTag("badcontenttype"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
v1manifest, ok = manifest.(*schema1.SignedManifest) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
if !ok {
|
||||
t.Fatalf("Unexpected manifest type from Get: %T", manifest)
|
||||
}
|
||||
|
||||
if err = checkEqualManifest(v1manifest, m1); err != nil {
|
||||
t.Fatal(err)
|
||||
// TODO(milosgajdos): once the schema1 manifest package is removed we need to
|
||||
// return some predefined error from distribution.UnmarshalManifest() for the cases
|
||||
// where empty mediaType/ctHeader is provided; currently this is handled by schema1 unmarshaler.
|
||||
// Ideally we'd like to returns something like UnsupportedManifest error and assert it in this test.
|
||||
_, err = ms.Get(ctx, dgst, distribution.WithTag("badcontenttype"))
|
||||
if err == nil {
|
||||
t.Fatal("expected to fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestManifestFetchWithEtag(t *testing.T) {
|
||||
repo, _ := reference.WithName("test.example.com/repo/by/tag")
|
||||
_, d1, p1 := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
_, d1, p1 := newRandomOCIManifest(t, 6)
|
||||
var m testutil.RequestResponseMap
|
||||
addTestManifestWithEtag(repo, "latest", p1, &m, d1.String())
|
||||
|
||||
|
@ -1198,7 +1174,7 @@ func TestManifestFetchWithEtag(t *testing.T) {
|
|||
func TestManifestFetchWithAccept(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
repo, _ := reference.WithName("test.example.com/repo")
|
||||
_, dgst, _ := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
_, dgst, _ := newRandomOCIManifest(t, 6)
|
||||
headers := make(chan []string, 1)
|
||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
headers <- req.Header["Accept"]
|
||||
|
@ -1242,6 +1218,10 @@ func TestManifestFetchWithAccept(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
// NOTE(milosgajdos): we are not checking error values here because this test
|
||||
// is not storing any manifests, so this will inevitably error out.
|
||||
// This test is about checking if the Accept headers are returned as expected.
|
||||
// nolint:errcheck
|
||||
ms.Get(ctx, dgst, distribution.WithManifestMediaTypes(testCase.mediaTypes))
|
||||
actual := <-headers
|
||||
if testCase.sort {
|
||||
|
@ -1256,8 +1236,8 @@ func TestManifestFetchWithAccept(t *testing.T) {
|
|||
|
||||
func TestManifestDelete(t *testing.T) {
|
||||
repo, _ := reference.WithName("test.example.com/repo/delete")
|
||||
_, dgst1, _ := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
_, dgst2, _ := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
_, dgst1, _ := newRandomOCIManifest(t, 6)
|
||||
_, dgst2, _ := newRandomOCIManifest(t, 6)
|
||||
var m testutil.RequestResponseMap
|
||||
m = append(m, testutil.RequestResponseMapping{
|
||||
Request: testutil.Request{
|
||||
|
@ -1291,23 +1271,17 @@ func TestManifestDelete(t *testing.T) {
|
|||
if err := ms.Delete(ctx, dgst2); err == nil {
|
||||
t.Fatal("Expected error deleting unknown manifest")
|
||||
}
|
||||
// TODO(dmcgowan): Check for specific unknown error
|
||||
}
|
||||
|
||||
func TestManifestPut(t *testing.T) {
|
||||
repo, _ := reference.WithName("test.example.com/repo/delete")
|
||||
m1, dgst, _ := newRandomSchemaV1Manifest(repo, "other", 6)
|
||||
|
||||
_, payload, err := m1.Payload() //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m1, dgst, payload := newRandomOCIManifest(t, 6)
|
||||
|
||||
var m testutil.RequestResponseMap
|
||||
m = append(m, testutil.RequestResponseMapping{
|
||||
Request: testutil.Request{
|
||||
Method: http.MethodPut,
|
||||
Route: "/v2/" + repo.Name() + "/manifests/other",
|
||||
Route: "/v2/" + repo.Name() + "/manifests/sometag",
|
||||
Body: payload,
|
||||
},
|
||||
Response: testutil.Response{
|
||||
|
@ -1319,7 +1293,7 @@ func TestManifestPut(t *testing.T) {
|
|||
},
|
||||
})
|
||||
|
||||
putDgst := digest.FromBytes(m1.Canonical)
|
||||
putDgst := digest.FromBytes(payload)
|
||||
m = append(m, testutil.RequestResponseMapping{
|
||||
Request: testutil.Request{
|
||||
Method: http.MethodPut,
|
||||
|
@ -1348,15 +1322,18 @@ func TestManifestPut(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := ms.Put(ctx, m1, distribution.WithTag(m1.Tag)); err != nil {
|
||||
dm, err := ocischema.FromStruct(*m1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := ms.Put(ctx, m1); err != nil {
|
||||
if _, err := ms.Put(ctx, dm, distribution.WithTag("sometag")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// TODO(dmcgowan): Check for invalid input error
|
||||
if _, err := ms.Put(ctx, dm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestManifestTags(t *testing.T) {
|
||||
|
@ -1424,7 +1401,7 @@ func TestManifestTags(t *testing.T) {
|
|||
func TestTagDelete(t *testing.T) {
|
||||
tag := "latest"
|
||||
repo, _ := reference.WithName("test.example.com/repo/delete")
|
||||
newRandomSchemaV1Manifest(repo, tag, 1)
|
||||
newRandomOCIManifest(t, 1)
|
||||
|
||||
var m testutil.RequestResponseMap
|
||||
m = append(m, testutil.RequestResponseMapping{
|
||||
|
@ -1505,12 +1482,8 @@ func TestObtainsManifestForTagWithoutHeaders(t *testing.T) {
|
|||
repo, _ := reference.WithName("test.example.com/repo")
|
||||
|
||||
var m testutil.RequestResponseMap
|
||||
m1, dgst, _ := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
_, pl, err := m1.Payload() //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
addTestManifestWithoutDigestHeader(repo, "1.0.0", schema1.MediaTypeSignedManifest, pl, &m) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
_, dgst, pl := newRandomOCIManifest(t, 6)
|
||||
addTestManifestWithoutDigestHeader(repo, "1.0.0", v1.MediaTypeImageManifest, pl, &m)
|
||||
|
||||
e, c := testServer(m)
|
||||
defer c()
|
||||
|
@ -1620,7 +1593,7 @@ func TestManifestTagsPaginated(t *testing.T) {
|
|||
|
||||
func TestManifestUnauthorized(t *testing.T) {
|
||||
repo, _ := reference.WithName("test.example.com/repo")
|
||||
_, dgst, _ := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
_, dgst, _ := newRandomOCIManifest(t, 6)
|
||||
var m testutil.RequestResponseMap
|
||||
|
||||
m = append(m, testutil.RequestResponseMapping{
|
||||
|
|
Loading…
Reference in a new issue