forked from TrueCloudLab/distribution
Remove references to schema1 pacakge from handlers
schema1 package was deprecated a while ago so we are removing any references to it from handlers. in preparation to removing it from the codebase altogether. Signed-off-by: Milos Gajdos <milosthegajdos@gmail.com>
This commit is contained in:
parent
6ccc551f96
commit
7e39a7c6dc
3 changed files with 97 additions and 634 deletions
|
@ -23,7 +23,6 @@ import (
|
|||
"github.com/distribution/distribution/v3/configuration"
|
||||
"github.com/distribution/distribution/v3/manifest"
|
||||
"github.com/distribution/distribution/v3/manifest/manifestlist"
|
||||
"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"
|
||||
"github.com/distribution/distribution/v3/reference"
|
||||
"github.com/distribution/distribution/v3/registry/api/errcode"
|
||||
|
@ -421,7 +420,8 @@ func TestCatalogAPI(t *testing.T) {
|
|||
|
||||
envWithLessImages := newTestEnv(t, false)
|
||||
for _, image := range allCatalog[0:(maxEntries - 1)] {
|
||||
createRepository(envWithLessImages, t, image, "sometag")
|
||||
imageName, _ := reference.WithName(image)
|
||||
testManifestAPISchema2(t, envWithLessImages, imageName, "sometag")
|
||||
}
|
||||
|
||||
catalogURL, err = envWithLessImages.builder.BuildCatalogURL(values)
|
||||
|
@ -1245,21 +1245,18 @@ type manifestArgs struct {
|
|||
}
|
||||
|
||||
func TestManifestAPI(t *testing.T) {
|
||||
schema1Repo, _ := reference.WithName("foo/schema1")
|
||||
schema2Repo, _ := reference.WithName("foo/schema2")
|
||||
|
||||
deleteEnabled := false
|
||||
env1 := newTestEnv(t, deleteEnabled)
|
||||
defer env1.Shutdown()
|
||||
testManifestAPISchema1(t, env1, schema1Repo)
|
||||
schema2Args := testManifestAPISchema2(t, env1, schema2Repo)
|
||||
schema2Args := testManifestAPISchema2(t, env1, schema2Repo, "schema2tag")
|
||||
testManifestAPIManifestList(t, env1, schema2Args)
|
||||
|
||||
deleteEnabled = true
|
||||
env2 := newTestEnv(t, deleteEnabled)
|
||||
defer env2.Shutdown()
|
||||
testManifestAPISchema1(t, env2, schema1Repo)
|
||||
schema2Args = testManifestAPISchema2(t, env2, schema2Repo)
|
||||
schema2Args = testManifestAPISchema2(t, env2, schema2Repo, "schema2tag")
|
||||
testManifestAPIManifestList(t, env2, schema2Args)
|
||||
}
|
||||
|
||||
|
@ -1438,24 +1435,21 @@ func TestGetManifestWithStorageError(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestManifestDelete(t *testing.T) {
|
||||
schema1Repo, _ := reference.WithName("foo/schema1")
|
||||
schema2Repo, _ := reference.WithName("foo/schema2")
|
||||
|
||||
deleteEnabled := true
|
||||
env := newTestEnv(t, deleteEnabled)
|
||||
defer env.Shutdown()
|
||||
schema1Args := testManifestAPISchema1(t, env, schema1Repo)
|
||||
testManifestDelete(t, env, schema1Args)
|
||||
schema2Args := testManifestAPISchema2(t, env, schema2Repo)
|
||||
schema2Args := testManifestAPISchema2(t, env, schema2Repo, "schema2tag")
|
||||
testManifestDelete(t, env, schema2Args)
|
||||
}
|
||||
|
||||
func TestManifestDeleteDisabled(t *testing.T) {
|
||||
schema1Repo, _ := reference.WithName("foo/schema1")
|
||||
schema2Repo, _ := reference.WithName("foo/schema2")
|
||||
deleteEnabled := false
|
||||
env := newTestEnv(t, deleteEnabled)
|
||||
defer env.Shutdown()
|
||||
testManifestDeleteDisabled(t, env, schema1Repo)
|
||||
testManifestDeleteDisabled(t, env, schema2Repo)
|
||||
}
|
||||
|
||||
func testManifestDeleteDisabled(t *testing.T, env *testEnv, imageName reference.Named) {
|
||||
|
@ -1493,324 +1487,7 @@ func testManifestWithStorageError(t *testing.T, env *testEnv, imageName referenc
|
|||
checkBodyHasErrorCodes(t, "getting non-existent manifest", resp, expectedErrorCode)
|
||||
}
|
||||
|
||||
func testManifestAPISchema1(t *testing.T, env *testEnv, imageName reference.Named) manifestArgs {
|
||||
tag := "thetag"
|
||||
args := manifestArgs{imageName: imageName}
|
||||
|
||||
tagRef, _ := reference.WithTag(imageName, tag)
|
||||
manifestURL, err := env.builder.BuildManifestURL(tagRef)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting manifest url: %v", err)
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// Attempt to fetch the manifest
|
||||
resp, err := http.Get(manifestURL)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting manifest: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
checkResponse(t, "getting non-existent manifest", resp, http.StatusNotFound)
|
||||
checkBodyHasErrorCodes(t, "getting non-existent manifest", resp, v2.ErrorCodeManifestUnknown)
|
||||
|
||||
tagsURL, err := env.builder.BuildTagsURL(imageName)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error building tags url: %v", err)
|
||||
}
|
||||
|
||||
resp, err = http.Get(tagsURL)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting unknown tags: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Check that we get an unknown repository error when asking for tags
|
||||
checkResponse(t, "getting unknown manifest tags", resp, http.StatusNotFound)
|
||||
checkBodyHasErrorCodes(t, "getting unknown manifest tags", resp, v2.ErrorCodeNameUnknown)
|
||||
|
||||
// --------------------------------
|
||||
// Attempt to push unsigned manifest with missing layers
|
||||
unsignedManifest := &schema1.Manifest{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
Versioned: manifest.Versioned{
|
||||
SchemaVersion: 1,
|
||||
},
|
||||
Name: imageName.Name(),
|
||||
Tag: tag,
|
||||
FSLayers: []schema1.FSLayer{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
{
|
||||
BlobSum: "asdf",
|
||||
},
|
||||
{
|
||||
BlobSum: "qwer",
|
||||
},
|
||||
},
|
||||
History: []schema1.History{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
{
|
||||
V1Compatibility: "",
|
||||
},
|
||||
{
|
||||
V1Compatibility: "",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resp = putManifest(t, "putting unsigned manifest", manifestURL, "", unsignedManifest)
|
||||
defer resp.Body.Close()
|
||||
checkResponse(t, "putting unsigned manifest", resp, http.StatusBadRequest)
|
||||
_, p, counts := checkBodyHasErrorCodes(t, "putting unsigned manifest", resp, v2.ErrorCodeManifestInvalid)
|
||||
|
||||
expectedCounts := map[errcode.ErrorCode]int{
|
||||
v2.ErrorCodeManifestInvalid: 1,
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(counts, expectedCounts) {
|
||||
t.Fatalf("unexpected number of error codes encountered: %v\n!=\n%v\n---\n%s", counts, expectedCounts, string(p))
|
||||
}
|
||||
|
||||
// sign the manifest and still get some interesting errors.
|
||||
sm, err := schema1.Sign(unsignedManifest, env.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("error signing manifest: %v", err)
|
||||
}
|
||||
|
||||
resp = putManifest(t, "putting signed manifest with errors", manifestURL, "", sm)
|
||||
defer resp.Body.Close()
|
||||
checkResponse(t, "putting signed manifest with errors", resp, http.StatusBadRequest)
|
||||
_, p, counts = checkBodyHasErrorCodes(t, "putting signed manifest with errors", resp,
|
||||
v2.ErrorCodeManifestBlobUnknown, v2.ErrorCodeDigestInvalid)
|
||||
|
||||
expectedCounts = map[errcode.ErrorCode]int{
|
||||
v2.ErrorCodeManifestBlobUnknown: 2,
|
||||
v2.ErrorCodeDigestInvalid: 2,
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(counts, expectedCounts) {
|
||||
t.Fatalf("unexpected number of error codes encountered: %v\n!=\n%v\n---\n%s", counts, expectedCounts, string(p))
|
||||
}
|
||||
|
||||
// TODO(stevvooe): Add a test case where we take a mostly valid registry,
|
||||
// tamper with the content and ensure that we get an unverified manifest
|
||||
// error.
|
||||
|
||||
// Push 2 random layers
|
||||
expectedLayers := make(map[digest.Digest]io.ReadSeeker)
|
||||
|
||||
for i := range unsignedManifest.FSLayers {
|
||||
rs, dgst, err := testutil.CreateRandomTarFile()
|
||||
if err != nil {
|
||||
t.Fatalf("error creating random layer %d: %v", i, err)
|
||||
}
|
||||
|
||||
expectedLayers[dgst] = rs
|
||||
unsignedManifest.FSLayers[i].BlobSum = dgst
|
||||
|
||||
uploadURLBase, _ := startPushLayer(t, env, imageName)
|
||||
pushLayer(t, env.builder, imageName, dgst, uploadURLBase, rs)
|
||||
}
|
||||
|
||||
// -------------------
|
||||
// Push the signed manifest with all layers pushed.
|
||||
signedManifest, err := schema1.Sign(unsignedManifest, env.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)
|
||||
}
|
||||
|
||||
dgst := digest.FromBytes(signedManifest.Canonical)
|
||||
args.manifest = signedManifest
|
||||
args.dgst = dgst
|
||||
|
||||
digestRef, _ := reference.WithDigest(imageName, dgst)
|
||||
manifestDigestURL, err := env.builder.BuildManifestURL(digestRef)
|
||||
checkErr(t, err, "building manifest url")
|
||||
|
||||
resp = putManifest(t, "putting signed manifest no error", manifestURL, "", signedManifest)
|
||||
checkResponse(t, "putting signed manifest no error", resp, http.StatusCreated)
|
||||
checkHeaders(t, resp, http.Header{
|
||||
"Location": []string{manifestDigestURL},
|
||||
"Docker-Content-Digest": []string{dgst.String()},
|
||||
})
|
||||
|
||||
// --------------------
|
||||
// Push by digest -- should get same result
|
||||
resp = putManifest(t, "putting signed manifest", manifestDigestURL, "", signedManifest)
|
||||
checkResponse(t, "putting signed manifest", resp, http.StatusCreated)
|
||||
checkHeaders(t, resp, http.Header{
|
||||
"Location": []string{manifestDigestURL},
|
||||
"Docker-Content-Digest": []string{dgst.String()},
|
||||
})
|
||||
|
||||
// ------------------
|
||||
// Fetch by tag name
|
||||
resp, err = http.Get(manifestURL)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error fetching manifest: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
checkResponse(t, "fetching uploaded manifest", resp, http.StatusOK)
|
||||
checkHeaders(t, resp, http.Header{
|
||||
"Docker-Content-Digest": []string{dgst.String()},
|
||||
"ETag": []string{fmt.Sprintf(`"%s"`, dgst)},
|
||||
})
|
||||
|
||||
var fetchedManifest schema1.SignedManifest //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
dec := json.NewDecoder(resp.Body)
|
||||
|
||||
if err := dec.Decode(&fetchedManifest); err != nil {
|
||||
t.Fatalf("error decoding fetched manifest: %v", err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(fetchedManifest.Canonical, signedManifest.Canonical) {
|
||||
t.Fatalf("manifests do not match")
|
||||
}
|
||||
|
||||
// ---------------
|
||||
// Fetch by digest
|
||||
resp, err = http.Get(manifestDigestURL)
|
||||
checkErr(t, err, "fetching manifest by digest")
|
||||
defer resp.Body.Close()
|
||||
|
||||
checkResponse(t, "fetching uploaded manifest", resp, http.StatusOK)
|
||||
checkHeaders(t, resp, http.Header{
|
||||
"Docker-Content-Digest": []string{dgst.String()},
|
||||
"ETag": []string{fmt.Sprintf(`"%s"`, dgst)},
|
||||
})
|
||||
|
||||
var fetchedManifestByDigest schema1.SignedManifest //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
dec = json.NewDecoder(resp.Body)
|
||||
if err := dec.Decode(&fetchedManifestByDigest); err != nil {
|
||||
t.Fatalf("error decoding fetched manifest: %v", err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(fetchedManifestByDigest.Canonical, signedManifest.Canonical) {
|
||||
t.Fatalf("manifests do not match")
|
||||
}
|
||||
|
||||
// check signature was roundtripped
|
||||
signatures, err := fetchedManifestByDigest.Signatures() //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)
|
||||
}
|
||||
|
||||
if len(signatures) != 1 {
|
||||
t.Fatalf("expected 1 signature from manifest, got: %d", len(signatures))
|
||||
}
|
||||
|
||||
// Re-sign, push and pull the same digest
|
||||
sm2, err := schema1.Sign(&fetchedManifestByDigest.Manifest, env.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.Fatal(err)
|
||||
}
|
||||
|
||||
// Re-push with a few different Content-Types. The official schema1
|
||||
// content type should work, as should application/json with/without a
|
||||
// charset.
|
||||
resp = putManifest(t, "re-putting signed manifest", manifestDigestURL, schema1.MediaTypeSignedManifest, sm2) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
checkResponse(t, "re-putting signed manifest", resp, http.StatusCreated)
|
||||
resp = putManifest(t, "re-putting signed manifest", manifestDigestURL, "application/json", sm2)
|
||||
checkResponse(t, "re-putting signed manifest", resp, http.StatusCreated)
|
||||
resp = putManifest(t, "re-putting signed manifest", manifestDigestURL, "application/json", sm2)
|
||||
checkResponse(t, "re-putting signed manifest", resp, http.StatusCreated)
|
||||
|
||||
resp, err = http.Get(manifestDigestURL)
|
||||
checkErr(t, err, "re-fetching manifest by digest")
|
||||
defer resp.Body.Close()
|
||||
|
||||
checkResponse(t, "re-fetching uploaded manifest", resp, http.StatusOK)
|
||||
checkHeaders(t, resp, http.Header{
|
||||
"Docker-Content-Digest": []string{dgst.String()},
|
||||
"ETag": []string{fmt.Sprintf(`"%s"`, dgst)},
|
||||
})
|
||||
|
||||
dec = json.NewDecoder(resp.Body)
|
||||
if err := dec.Decode(&fetchedManifestByDigest); err != nil {
|
||||
t.Fatalf("error decoding fetched manifest: %v", err)
|
||||
}
|
||||
|
||||
// check only 1 signature is returned
|
||||
signatures, err = fetchedManifestByDigest.Signatures() //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)
|
||||
}
|
||||
|
||||
if len(signatures) != 1 {
|
||||
t.Fatalf("expected 2 signature from manifest, got: %d", len(signatures))
|
||||
}
|
||||
|
||||
// Get by name with etag, gives 304
|
||||
etag := resp.Header.Get("Etag")
|
||||
req, err := http.NewRequest(http.MethodGet, manifestURL, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error constructing request: %s", err)
|
||||
}
|
||||
req.Header.Set("If-None-Match", etag)
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatalf("Error constructing request: %s", err)
|
||||
}
|
||||
|
||||
checkResponse(t, "fetching manifest by name with etag", resp, http.StatusNotModified)
|
||||
|
||||
// Get by digest with etag, gives 304
|
||||
req, err = http.NewRequest(http.MethodGet, manifestDigestURL, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error constructing request: %s", err)
|
||||
}
|
||||
req.Header.Set("If-None-Match", etag)
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatalf("Error constructing request: %s", err)
|
||||
}
|
||||
|
||||
checkResponse(t, "fetching manifest by dgst with etag", resp, http.StatusNotModified)
|
||||
|
||||
// Ensure that the tag is listed.
|
||||
resp, err = http.Get(tagsURL)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting unknown tags: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
checkResponse(t, "getting tags", resp, http.StatusOK)
|
||||
dec = json.NewDecoder(resp.Body)
|
||||
|
||||
var tagsResponse tagsAPIResponse
|
||||
|
||||
if err := dec.Decode(&tagsResponse); err != nil {
|
||||
t.Fatalf("unexpected error decoding error response: %v", err)
|
||||
}
|
||||
|
||||
if tagsResponse.Name != imageName.Name() {
|
||||
t.Fatalf("tags name should match image name: %v != %v", tagsResponse.Name, imageName.Name())
|
||||
}
|
||||
|
||||
if len(tagsResponse.Tags) != 1 {
|
||||
t.Fatalf("expected some tags in response: %v", tagsResponse.Tags)
|
||||
}
|
||||
|
||||
if tagsResponse.Tags[0] != tag {
|
||||
t.Fatalf("tag not as expected: %q != %q", tagsResponse.Tags[0], tag)
|
||||
}
|
||||
|
||||
// Attempt to put a manifest with mismatching FSLayer and History array cardinalities
|
||||
|
||||
unsignedManifest.History = append(unsignedManifest.History, schema1.History{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
V1Compatibility: "",
|
||||
})
|
||||
invalidSigned, err := schema1.Sign(unsignedManifest, env.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("error signing manifest")
|
||||
}
|
||||
|
||||
resp = putManifest(t, "putting invalid signed manifest", manifestDigestURL, "", invalidSigned)
|
||||
checkResponse(t, "putting invalid signed manifest", resp, http.StatusBadRequest)
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Named) manifestArgs {
|
||||
tag := "schema2tag"
|
||||
func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Named, tag string) manifestArgs {
|
||||
args := manifestArgs{
|
||||
imageName: imageName,
|
||||
mediaType: schema2.MediaTypeManifest,
|
||||
|
@ -2101,63 +1778,6 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Name
|
|||
t.Fatalf("tag not as expected: %q != %q", tagsResponse.Tags[0], tag)
|
||||
}
|
||||
|
||||
// ------------------
|
||||
// Fetch as a schema1 manifest
|
||||
resp, err = http.Get(manifestURL)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error fetching manifest as schema1: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
manifestBytes, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("error reading response body: %v", err)
|
||||
}
|
||||
|
||||
checkResponse(t, "fetching uploaded manifest as schema1", resp, http.StatusOK)
|
||||
|
||||
m, desc, err := distribution.UnmarshalManifest(schema1.MediaTypeManifest, manifestBytes) //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 unmarshalling manifest: %v", err)
|
||||
}
|
||||
|
||||
fetchedSchema1Manifest, ok := m.(*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("expecting schema1 manifest")
|
||||
}
|
||||
|
||||
checkHeaders(t, resp, http.Header{
|
||||
"Docker-Content-Digest": []string{desc.Digest.String()},
|
||||
"ETag": []string{fmt.Sprintf(`"%s"`, desc.Digest)},
|
||||
})
|
||||
|
||||
if fetchedSchema1Manifest.Manifest.SchemaVersion != 1 {
|
||||
t.Fatal("wrong schema version")
|
||||
}
|
||||
if fetchedSchema1Manifest.Architecture != "amd64" {
|
||||
t.Fatal("wrong architecture")
|
||||
}
|
||||
if fetchedSchema1Manifest.Name != imageName.Name() {
|
||||
t.Fatal("wrong image name")
|
||||
}
|
||||
if fetchedSchema1Manifest.Tag != tag {
|
||||
t.Fatal("wrong tag")
|
||||
}
|
||||
if len(fetchedSchema1Manifest.FSLayers) != 2 {
|
||||
t.Fatal("wrong number of FSLayers")
|
||||
}
|
||||
for i := range manifest.Layers {
|
||||
if fetchedSchema1Manifest.FSLayers[i].BlobSum != manifest.Layers[len(manifest.Layers)-i-1].Digest {
|
||||
t.Fatalf("blob digest mismatch in schema1 manifest for layer %d", i)
|
||||
}
|
||||
}
|
||||
if len(fetchedSchema1Manifest.History) != 2 {
|
||||
t.Fatal("wrong number of History entries")
|
||||
}
|
||||
|
||||
// Don't check V1Compatibility fields because we're using randomly-generated
|
||||
// layers.
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
|
@ -2246,7 +1866,7 @@ func testManifestAPIManifestList(t *testing.T, env *testEnv, args manifestArgs)
|
|||
t.Fatalf("Error constructing request: %s", err)
|
||||
}
|
||||
// multiple headers in mixed list format to ensure we parse correctly server-side
|
||||
req.Header.Set("Accept", fmt.Sprintf(` %s ; q=0.8 , %s ; q=0.5 `, manifestlist.MediaTypeManifestList, schema1.MediaTypeSignedManifest)) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
req.Header.Set("Accept", fmt.Sprintf(` %s ; q=0.8 `, manifestlist.MediaTypeManifestList))
|
||||
req.Header.Add("Accept", schema2.MediaTypeManifest)
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
|
@ -2334,64 +1954,6 @@ func testManifestAPIManifestList(t *testing.T, env *testEnv, args manifestArgs)
|
|||
}
|
||||
|
||||
checkResponse(t, "fetching manifest by dgst with etag", resp, http.StatusNotModified)
|
||||
|
||||
// ------------------
|
||||
// Fetch as a schema1 manifest
|
||||
resp, err = http.Get(manifestURL)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error fetching manifest list as schema1: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
manifestBytes, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("error reading response body: %v", err)
|
||||
}
|
||||
|
||||
checkResponse(t, "fetching uploaded manifest list as schema1", resp, http.StatusOK)
|
||||
|
||||
m, desc, err := distribution.UnmarshalManifest(schema1.MediaTypeManifest, manifestBytes) //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 unmarshalling manifest: %v", err)
|
||||
}
|
||||
|
||||
fetchedSchema1Manifest, ok := m.(*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("expecting schema1 manifest")
|
||||
}
|
||||
|
||||
checkHeaders(t, resp, http.Header{
|
||||
"Docker-Content-Digest": []string{desc.Digest.String()},
|
||||
"ETag": []string{fmt.Sprintf(`"%s"`, desc.Digest)},
|
||||
})
|
||||
|
||||
if fetchedSchema1Manifest.Manifest.SchemaVersion != 1 {
|
||||
t.Fatal("wrong schema version")
|
||||
}
|
||||
if fetchedSchema1Manifest.Architecture != "amd64" {
|
||||
t.Fatal("wrong architecture")
|
||||
}
|
||||
if fetchedSchema1Manifest.Name != imageName.Name() {
|
||||
t.Fatal("wrong image name")
|
||||
}
|
||||
if fetchedSchema1Manifest.Tag != tag {
|
||||
t.Fatal("wrong tag")
|
||||
}
|
||||
if len(fetchedSchema1Manifest.FSLayers) != 2 {
|
||||
t.Fatal("wrong number of FSLayers")
|
||||
}
|
||||
layers := args.manifest.(*schema2.DeserializedManifest).Layers
|
||||
for i := range layers {
|
||||
if fetchedSchema1Manifest.FSLayers[i].BlobSum != layers[len(layers)-i-1].Digest {
|
||||
t.Fatalf("blob digest mismatch in schema1 manifest for layer %d", i)
|
||||
}
|
||||
}
|
||||
if len(fetchedSchema1Manifest.History) != 2 {
|
||||
t.Fatal("wrong number of History entries")
|
||||
}
|
||||
|
||||
// Don't check V1Compatibility fields because we're using randomly-generated
|
||||
// layers.
|
||||
}
|
||||
|
||||
func testManifestDelete(t *testing.T, env *testEnv, args manifestArgs) {
|
||||
|
@ -2556,7 +2118,6 @@ func newTestEnvMirror(t *testing.T, deleteEnabled bool) *testEnv {
|
|||
MaxEntries: 5,
|
||||
},
|
||||
}
|
||||
config.Compatibility.Schema1.Enabled = true //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
|
||||
return newTestEnvWithConfig(t, &config)
|
||||
}
|
||||
|
@ -2575,7 +2136,6 @@ func newTestEnv(t *testing.T, deleteEnabled bool) *testEnv {
|
|||
},
|
||||
}
|
||||
|
||||
config.Compatibility.Schema1.Enabled = true //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
config.HTTP.Headers = headerConfig
|
||||
|
||||
return newTestEnvWithConfig(t, &config)
|
||||
|
@ -2615,12 +2175,6 @@ func putManifest(t *testing.T, msg, url, contentType string, v interface{}) *htt
|
|||
var body []byte
|
||||
|
||||
switch m := v.(type) {
|
||||
case *schema1.SignedManifest: //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
_, pl, err := m.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.Fatalf("error getting payload: %v", err)
|
||||
}
|
||||
body = pl
|
||||
case *manifestlist.DeserializedManifestList:
|
||||
_, pl, err := m.Payload()
|
||||
if err != nil {
|
||||
|
@ -2968,61 +2522,89 @@ func createRepository(env *testEnv, t *testing.T, imageName string, tag string)
|
|||
t.Fatalf("unable to parse reference: %v", err)
|
||||
}
|
||||
|
||||
unsignedManifest := &schema1.Manifest{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
tagRef, _ := reference.WithTag(imageNameRef, tag)
|
||||
manifestURL, err := env.builder.BuildManifestURL(tagRef)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting manifest url: %v", err)
|
||||
}
|
||||
|
||||
manifest := &schema2.Manifest{
|
||||
Versioned: manifest.Versioned{
|
||||
SchemaVersion: 1,
|
||||
SchemaVersion: 2,
|
||||
MediaType: schema2.MediaTypeManifest,
|
||||
},
|
||||
Name: imageName,
|
||||
Tag: tag,
|
||||
FSLayers: []schema1.FSLayer{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
Config: distribution.Descriptor{
|
||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||
Size: 3253,
|
||||
MediaType: schema2.MediaTypeImageConfig,
|
||||
},
|
||||
Layers: []distribution.Descriptor{
|
||||
{
|
||||
BlobSum: "asdf",
|
||||
},
|
||||
},
|
||||
History: []schema1.History{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
{
|
||||
V1Compatibility: "",
|
||||
Digest: "sha256:463434349086340864309863409683460843608348608934092322395278926a",
|
||||
Size: 6323,
|
||||
MediaType: schema2.MediaTypeLayer,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Push 2 random layers
|
||||
expectedLayers := make(map[digest.Digest]io.ReadSeeker)
|
||||
// Push a config, and reference it in the manifest
|
||||
sampleConfig := []byte(`{
|
||||
"architecture": "amd64",
|
||||
"history": [
|
||||
{
|
||||
"created": "2015-10-31T22:22:54.690851953Z",
|
||||
"created_by": "/bin/sh -c #(nop) ADD file:a3bc1e842b69636f9df5256c49c5374fb4eef1e281fe3f282c65fb853ee171c5 in /"
|
||||
},
|
||||
],
|
||||
"rootfs": {
|
||||
"diff_ids": [
|
||||
"sha256:c6f988f4874bb0add23a778f753c65efe992244e148a1d2ec2a8b664fb66bbd1",
|
||||
],
|
||||
"type": "layers"
|
||||
}
|
||||
}`)
|
||||
sampleConfigDigest := digest.FromBytes(sampleConfig)
|
||||
|
||||
for i := range unsignedManifest.FSLayers {
|
||||
uploadURLBase, _ := startPushLayer(t, env, imageNameRef)
|
||||
pushLayer(t, env.builder, imageNameRef, sampleConfigDigest, uploadURLBase, bytes.NewReader(sampleConfig))
|
||||
manifest.Config.Digest = sampleConfigDigest
|
||||
manifest.Config.Size = int64(len(sampleConfig))
|
||||
|
||||
// Push random layers
|
||||
|
||||
for i := range manifest.Layers {
|
||||
rs, dgst, err := testutil.CreateRandomTarFile()
|
||||
if err != nil {
|
||||
t.Fatalf("error creating random layer %d: %v", i, err)
|
||||
}
|
||||
manifest.Layers[i].Digest = dgst
|
||||
|
||||
expectedLayers[dgst] = rs
|
||||
unsignedManifest.FSLayers[i].BlobSum = dgst
|
||||
uploadURLBase, _ := startPushLayer(t, env, imageNameRef)
|
||||
pushLayer(t, env.builder, imageNameRef, dgst, uploadURLBase, rs)
|
||||
}
|
||||
|
||||
signedManifest, err := schema1.Sign(unsignedManifest, env.pk) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
// -------------------
|
||||
// Push the manifest with all layers pushed.
|
||||
deserializedManifest, err := schema2.FromStruct(*manifest)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error signing manifest: %v", err)
|
||||
t.Fatalf("could not create DeserializedManifest: %v", err)
|
||||
}
|
||||
|
||||
dgst := digest.FromBytes(signedManifest.Canonical)
|
||||
|
||||
// Create this repository by tag to ensure the tag mapping is made in the registry
|
||||
tagRef, _ := reference.WithTag(imageNameRef, tag)
|
||||
manifestDigestURL, err := env.builder.BuildManifestURL(tagRef)
|
||||
_, canonical, err := deserializedManifest.Payload()
|
||||
if err != nil {
|
||||
t.Fatalf("could not get manifest payload: %v", err)
|
||||
}
|
||||
dgst := digest.FromBytes(canonical)
|
||||
digestRef, _ := reference.WithDigest(imageNameRef, dgst)
|
||||
manifestDigestURL, err := env.builder.BuildManifestURL(digestRef)
|
||||
checkErr(t, err, "building manifest url")
|
||||
|
||||
digestRef, _ := reference.WithDigest(imageNameRef, dgst)
|
||||
location, err := env.builder.BuildManifestURL(digestRef)
|
||||
checkErr(t, err, "building location URL")
|
||||
|
||||
resp := putManifest(t, "putting signed manifest", manifestDigestURL, "", signedManifest)
|
||||
checkResponse(t, "putting signed manifest", resp, http.StatusCreated)
|
||||
resp := putManifest(t, "putting manifest no error", manifestURL, schema2.MediaTypeManifest, manifest)
|
||||
checkResponse(t, "putting manifest no error", resp, http.StatusCreated)
|
||||
checkHeaders(t, resp, http.Header{
|
||||
"Location": []string{location},
|
||||
"Location": []string{manifestDigestURL},
|
||||
"Docker-Content-Digest": []string{dgst.String()},
|
||||
})
|
||||
|
||||
return dgst
|
||||
}
|
||||
|
||||
|
@ -3042,27 +2624,36 @@ func TestRegistryAsCacheMutationAPIs(t *testing.T) {
|
|||
}
|
||||
|
||||
// Manifest upload
|
||||
m := &schema1.Manifest{ //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
manifest := &schema2.Manifest{
|
||||
Versioned: manifest.Versioned{
|
||||
SchemaVersion: 1,
|
||||
SchemaVersion: 2,
|
||||
MediaType: schema2.MediaTypeManifest,
|
||||
},
|
||||
Config: distribution.Descriptor{
|
||||
Digest: "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b",
|
||||
Size: 3253,
|
||||
MediaType: schema2.MediaTypeImageConfig,
|
||||
},
|
||||
Layers: []distribution.Descriptor{
|
||||
{
|
||||
Digest: "sha256:463434349086340864309863409683460843608348608934092322395278926a",
|
||||
Size: 6323,
|
||||
MediaType: schema2.MediaTypeLayer,
|
||||
},
|
||||
{
|
||||
Digest: "sha256:630923423623623423352523525237238023652897356239852383652aaaaaaa",
|
||||
Size: 6863,
|
||||
MediaType: schema2.MediaTypeLayer,
|
||||
},
|
||||
},
|
||||
Name: imageName.Name(),
|
||||
Tag: tag,
|
||||
FSLayers: []schema1.FSLayer{}, //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
History: []schema1.History{}, //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
}
|
||||
|
||||
sm, err := schema1.Sign(m, env.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("error signing manifest: %v", err)
|
||||
}
|
||||
|
||||
resp := putManifest(t, "putting unsigned manifest", manifestURL, "", sm)
|
||||
checkResponse(t, "putting signed manifest to cache", resp, errcode.ErrorCodeUnsupported.Descriptor().HTTPStatusCode)
|
||||
resp := putManifest(t, "putting missing config manifest", manifestURL, schema2.MediaTypeManifest, manifest)
|
||||
checkResponse(t, "putting missing config manifest", resp, errcode.ErrorCodeUnsupported.Descriptor().HTTPStatusCode)
|
||||
|
||||
// Manifest Delete
|
||||
resp, _ = httpDelete(manifestURL)
|
||||
checkResponse(t, "deleting signed manifest from cache", resp, errcode.ErrorCodeUnsupported.Descriptor().HTTPStatusCode)
|
||||
checkResponse(t, "deleting config manifest from cache", resp, errcode.ErrorCodeUnsupported.Descriptor().HTTPStatusCode)
|
||||
|
||||
// Blob upload initialization
|
||||
layerUploadURL, err := env.builder.BuildBlobUploadURL(imageName)
|
||||
|
@ -3094,7 +2685,6 @@ func TestProxyManifestGetByTag(t *testing.T) {
|
|||
}},
|
||||
},
|
||||
}
|
||||
truthConfig.Compatibility.Schema1.Enabled = true //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
truthConfig.HTTP.Headers = headerConfig
|
||||
|
||||
imageName, _ := reference.WithName("foo/bar")
|
||||
|
@ -3113,7 +2703,6 @@ func TestProxyManifestGetByTag(t *testing.T) {
|
|||
RemoteURL: truthEnv.server.URL,
|
||||
},
|
||||
}
|
||||
proxyConfig.Compatibility.Schema1.Enabled = true //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
proxyConfig.HTTP.Headers = headerConfig
|
||||
|
||||
proxyEnv := newTestEnvWithConfig(t, &proxyConfig)
|
||||
|
|
|
@ -40,7 +40,6 @@ import (
|
|||
"github.com/distribution/distribution/v3/version"
|
||||
events "github.com/docker/go-events"
|
||||
"github.com/docker/go-metrics"
|
||||
"github.com/docker/libtrust"
|
||||
"github.com/gomodule/redigo/redis"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -79,11 +78,6 @@ type App struct {
|
|||
|
||||
redis *redis.Pool
|
||||
|
||||
// trustKey is a deprecated key used to sign manifests converted to
|
||||
// schema1 for backward compatibility. It should not be used for any
|
||||
// other purposes.
|
||||
trustKey libtrust.PrivateKey
|
||||
|
||||
// isCache is true if this registry is configured as a pull through cache
|
||||
isCache bool
|
||||
|
||||
|
@ -164,25 +158,6 @@ func NewApp(ctx context.Context, config *configuration.Configuration) *App {
|
|||
app.configureLogHook(config)
|
||||
|
||||
options := registrymiddleware.GetRegistryOptions()
|
||||
if config.Compatibility.Schema1.TrustKey != "" {
|
||||
app.trustKey, err = libtrust.LoadKeyFile(config.Compatibility.Schema1.TrustKey)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf(`could not load schema1 "signingkey" parameter: %v`, err))
|
||||
}
|
||||
} else {
|
||||
// Generate an ephemeral key to be used for signing converted manifests
|
||||
// for clients that don't support schema2.
|
||||
app.trustKey, err = libtrust.GenerateECP256PrivateKey()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
options = append(options, storage.Schema1SigningKey(app.trustKey))
|
||||
|
||||
if config.Compatibility.Schema1.Enabled {
|
||||
options = append(options, storage.EnableSchema1)
|
||||
}
|
||||
|
||||
if config.HTTP.Host != "" {
|
||||
u, err := url.Parse(config.HTTP.Host)
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
dcontext "github.com/distribution/distribution/v3/context"
|
||||
"github.com/distribution/distribution/v3/manifest/manifestlist"
|
||||
"github.com/distribution/distribution/v3/manifest/ocischema"
|
||||
"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"
|
||||
"github.com/distribution/distribution/v3/reference"
|
||||
"github.com/distribution/distribution/v3/registry/api/errcode"
|
||||
|
@ -23,11 +22,7 @@ import (
|
|||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// These constants determine which architecture and OS to choose from a
|
||||
// manifest list when downconverting it to a schema1 manifest.
|
||||
const (
|
||||
defaultArch = "amd64"
|
||||
defaultOS = "linux"
|
||||
maxManifestBodySize = 4 << 20
|
||||
imageClass = "image"
|
||||
)
|
||||
|
@ -35,12 +30,11 @@ const (
|
|||
type storageType int
|
||||
|
||||
const (
|
||||
manifestSchema1 storageType = iota // 0
|
||||
manifestSchema2 // 1
|
||||
manifestlistSchema // 2
|
||||
ociSchema // 3
|
||||
ociImageIndexSchema // 4
|
||||
numStorageTypes // 5
|
||||
manifestSchema2 storageType = iota // 0
|
||||
manifestlistSchema // 1
|
||||
ociSchema // 2
|
||||
ociImageIndexSchema // 3
|
||||
numStorageTypes // 4
|
||||
)
|
||||
|
||||
// manifestDispatcher takes the request context and builds the
|
||||
|
@ -151,12 +145,9 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
|
|||
return
|
||||
}
|
||||
// determine the type of the returned manifest
|
||||
manifestType := manifestSchema1
|
||||
schema2Manifest, isSchema2 := manifest.(*schema2.DeserializedManifest)
|
||||
manifestType := manifestSchema2
|
||||
manifestList, isManifestList := manifest.(*manifestlist.DeserializedManifestList)
|
||||
if isSchema2 {
|
||||
manifestType = manifestSchema2
|
||||
} else if _, isOCImanifest := manifest.(*ocischema.DeserializedManifest); isOCImanifest {
|
||||
if _, isOCImanifest := manifest.(*ocischema.DeserializedManifest); isOCImanifest {
|
||||
manifestType = ociSchema
|
||||
} else if isManifestList {
|
||||
if manifestList.MediaType == manifestlist.MediaTypeManifestList {
|
||||
|
@ -174,56 +165,6 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
|
|||
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithMessage("OCI index found, but accept header does not support OCI indexes"))
|
||||
return
|
||||
}
|
||||
// Only rewrite schema2 manifests when they are being fetched by tag.
|
||||
// If they are being fetched by digest, we can't return something not
|
||||
// matching the digest.
|
||||
if imh.Tag != "" && manifestType == manifestSchema2 && !supports[manifestSchema2] {
|
||||
// Rewrite manifest in schema1 format
|
||||
dcontext.GetLogger(imh).Infof("rewriting manifest %s in schema1 format to support old client", imh.Digest.String())
|
||||
|
||||
manifest, err = imh.convertSchema2Manifest(schema2Manifest)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else if imh.Tag != "" && manifestType == manifestlistSchema && !supports[manifestlistSchema] {
|
||||
// Rewrite manifest in schema1 format
|
||||
dcontext.GetLogger(imh).Infof("rewriting manifest list %s in schema1 format to support old client", imh.Digest.String())
|
||||
|
||||
// Find the image manifest corresponding to the default
|
||||
// platform
|
||||
var manifestDigest digest.Digest
|
||||
for _, manifestDescriptor := range manifestList.Manifests {
|
||||
if manifestDescriptor.Platform.Architecture == defaultArch && manifestDescriptor.Platform.OS == defaultOS {
|
||||
manifestDigest = manifestDescriptor.Digest
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if manifestDigest == "" {
|
||||
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown)
|
||||
return
|
||||
}
|
||||
|
||||
manifest, err = manifests.Get(imh, manifestDigest)
|
||||
if err != nil {
|
||||
if _, ok := err.(distribution.ErrManifestUnknownRevision); ok {
|
||||
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestUnknown.WithDetail(err))
|
||||
} else {
|
||||
imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// If necessary, convert the image manifest
|
||||
if schema2Manifest, isSchema2 := manifest.(*schema2.DeserializedManifest); isSchema2 && !supports[manifestSchema2] {
|
||||
manifest, err = imh.convertSchema2Manifest(schema2Manifest)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
imh.Digest = manifestDigest
|
||||
}
|
||||
}
|
||||
|
||||
ct, p, err := manifest.Payload()
|
||||
if err != nil {
|
||||
|
@ -237,46 +178,6 @@ func (imh *manifestHandler) GetManifest(w http.ResponseWriter, r *http.Request)
|
|||
w.Write(p)
|
||||
}
|
||||
|
||||
func (imh *manifestHandler) convertSchema2Manifest(schema2Manifest *schema2.DeserializedManifest) (distribution.Manifest, error) {
|
||||
targetDescriptor := schema2Manifest.Target()
|
||||
blobs := imh.Repository.Blobs(imh)
|
||||
configJSON, err := blobs.Get(imh, targetDescriptor.Digest)
|
||||
if err != nil {
|
||||
if err == distribution.ErrBlobUnknown {
|
||||
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestInvalid.WithDetail(err))
|
||||
} else {
|
||||
imh.Errors = append(imh.Errors, errcode.ErrorCodeUnknown.WithDetail(err))
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ref := imh.Repository.Named()
|
||||
|
||||
if imh.Tag != "" {
|
||||
ref, err = reference.WithTag(ref, imh.Tag)
|
||||
if err != nil {
|
||||
imh.Errors = append(imh.Errors, v2.ErrorCodeTagInvalid.WithDetail(err))
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
builder := schema1.NewConfigManifestBuilder(imh.Repository.Blobs(imh), imh.Context.App.trustKey, ref, configJSON) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
for _, d := range schema2Manifest.Layers {
|
||||
if err := builder.AppendReference(d); err != nil {
|
||||
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestInvalid.WithDetail(err))
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
manifest, err := builder.Build(imh)
|
||||
if err != nil {
|
||||
imh.Errors = append(imh.Errors, v2.ErrorCodeManifestInvalid.WithDetail(err))
|
||||
return nil, err
|
||||
}
|
||||
imh.Digest = digest.FromBytes(manifest.(*schema1.SignedManifest).Canonical) //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
|
||||
return manifest, nil
|
||||
}
|
||||
|
||||
func etagMatch(r *http.Request, etag string) bool {
|
||||
for _, headerVal := range r.Header["If-None-Match"] {
|
||||
if headerVal == etag || headerVal == fmt.Sprintf(`"%s"`, etag) { // allow quoted or unquoted
|
||||
|
@ -421,8 +322,6 @@ func (imh *manifestHandler) applyResourcePolicy(manifest distribution.Manifest)
|
|||
|
||||
var class string
|
||||
switch m := manifest.(type) {
|
||||
case *schema1.SignedManifest: //nolint:staticcheck // Ignore SA1019: "github.com/distribution/distribution/v3/manifest/schema1" is deprecated, as it's used for backward compatibility.
|
||||
class = imageClass
|
||||
case *schema2.DeserializedManifest:
|
||||
switch m.Config.MediaType {
|
||||
case schema2.MediaTypeImageConfig:
|
||||
|
|
Loading…
Reference in a new issue