Use reference package internally
Most places in the registry were using string types to refer to repository names. This changes them to use reference.Named, so the type system can enforce validation of the naming rules. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
This commit is contained in:
parent
e9bcc96ad2
commit
e9692b8037
26 changed files with 235 additions and 193 deletions
|
@ -26,6 +26,7 @@ import (
|
|||
"github.com/docker/distribution/manifest/manifestlist"
|
||||
"github.com/docker/distribution/manifest/schema1"
|
||||
"github.com/docker/distribution/manifest/schema2"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
"github.com/docker/distribution/registry/api/v2"
|
||||
_ "github.com/docker/distribution/registry/storage/driver/inmemory"
|
||||
|
@ -251,7 +252,7 @@ func TestURLPrefix(t *testing.T) {
|
|||
}
|
||||
|
||||
type blobArgs struct {
|
||||
imageName string
|
||||
imageName reference.Named
|
||||
layerFile io.ReadSeeker
|
||||
layerDigest digest.Digest
|
||||
}
|
||||
|
@ -263,10 +264,10 @@ func makeBlobArgs(t *testing.T) blobArgs {
|
|||
}
|
||||
|
||||
args := blobArgs{
|
||||
imageName: "foo/bar",
|
||||
layerFile: layerFile,
|
||||
layerDigest: layerDigest,
|
||||
}
|
||||
args.imageName, _ = reference.ParseNamed("foo/bar")
|
||||
return args
|
||||
}
|
||||
|
||||
|
@ -609,7 +610,7 @@ func testBlobDelete(t *testing.T, env *testEnv, args blobArgs) {
|
|||
func TestDeleteDisabled(t *testing.T) {
|
||||
env := newTestEnv(t, false)
|
||||
|
||||
imageName := "foo/bar"
|
||||
imageName, _ := reference.ParseNamed("foo/bar")
|
||||
// "build" our layer file
|
||||
layerFile, layerDigest, err := testutil.CreateRandomTarFile()
|
||||
if err != nil {
|
||||
|
@ -634,7 +635,7 @@ func TestDeleteDisabled(t *testing.T) {
|
|||
func TestDeleteReadOnly(t *testing.T) {
|
||||
env := newTestEnv(t, true)
|
||||
|
||||
imageName := "foo/bar"
|
||||
imageName, _ := reference.ParseNamed("foo/bar")
|
||||
// "build" our layer file
|
||||
layerFile, layerDigest, err := testutil.CreateRandomTarFile()
|
||||
if err != nil {
|
||||
|
@ -662,7 +663,7 @@ func TestStartPushReadOnly(t *testing.T) {
|
|||
env := newTestEnv(t, true)
|
||||
env.app.readOnly = true
|
||||
|
||||
imageName := "foo/bar"
|
||||
imageName, _ := reference.ParseNamed("foo/bar")
|
||||
|
||||
layerUploadURL, err := env.builder.BuildBlobUploadURL(imageName)
|
||||
if err != nil {
|
||||
|
@ -693,42 +694,49 @@ func httpDelete(url string) (*http.Response, error) {
|
|||
}
|
||||
|
||||
type manifestArgs struct {
|
||||
imageName string
|
||||
imageName reference.Named
|
||||
mediaType string
|
||||
manifest distribution.Manifest
|
||||
dgst digest.Digest
|
||||
}
|
||||
|
||||
func TestManifestAPI(t *testing.T) {
|
||||
schema1Repo, _ := reference.ParseNamed("foo/schema1")
|
||||
schema2Repo, _ := reference.ParseNamed("foo/schema2")
|
||||
|
||||
deleteEnabled := false
|
||||
env := newTestEnv(t, deleteEnabled)
|
||||
testManifestAPISchema1(t, env, "foo/schema1")
|
||||
schema2Args := testManifestAPISchema2(t, env, "foo/schema2")
|
||||
testManifestAPISchema1(t, env, schema1Repo)
|
||||
schema2Args := testManifestAPISchema2(t, env, schema2Repo)
|
||||
testManifestAPIManifestList(t, env, schema2Args)
|
||||
|
||||
deleteEnabled = true
|
||||
env = newTestEnv(t, deleteEnabled)
|
||||
testManifestAPISchema1(t, env, "foo/schema1")
|
||||
schema2Args = testManifestAPISchema2(t, env, "foo/schema2")
|
||||
testManifestAPISchema1(t, env, schema1Repo)
|
||||
schema2Args = testManifestAPISchema2(t, env, schema2Repo)
|
||||
testManifestAPIManifestList(t, env, schema2Args)
|
||||
}
|
||||
|
||||
func TestManifestDelete(t *testing.T) {
|
||||
schema1Repo, _ := reference.ParseNamed("foo/schema1")
|
||||
schema2Repo, _ := reference.ParseNamed("foo/schema2")
|
||||
|
||||
deleteEnabled := true
|
||||
env := newTestEnv(t, deleteEnabled)
|
||||
schema1Args := testManifestAPISchema1(t, env, "foo/schema1")
|
||||
schema1Args := testManifestAPISchema1(t, env, schema1Repo)
|
||||
testManifestDelete(t, env, schema1Args)
|
||||
schema2Args := testManifestAPISchema2(t, env, "foo/schema2")
|
||||
schema2Args := testManifestAPISchema2(t, env, schema2Repo)
|
||||
testManifestDelete(t, env, schema2Args)
|
||||
}
|
||||
|
||||
func TestManifestDeleteDisabled(t *testing.T) {
|
||||
schema1Repo, _ := reference.ParseNamed("foo/schema1")
|
||||
deleteEnabled := false
|
||||
env := newTestEnv(t, deleteEnabled)
|
||||
testManifestDeleteDisabled(t, env, "foo/schema1")
|
||||
testManifestDeleteDisabled(t, env, schema1Repo)
|
||||
}
|
||||
|
||||
func testManifestDeleteDisabled(t *testing.T, env *testEnv, imageName string) {
|
||||
func testManifestDeleteDisabled(t *testing.T, env *testEnv, imageName reference.Named) {
|
||||
manifestURL, err := env.builder.BuildManifestURL(imageName, digest.DigestSha256EmptyTar)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting manifest url: %v", err)
|
||||
|
@ -743,7 +751,7 @@ func testManifestDeleteDisabled(t *testing.T, env *testEnv, imageName string) {
|
|||
checkResponse(t, "status of disabled delete of manifest", resp, http.StatusMethodNotAllowed)
|
||||
}
|
||||
|
||||
func testManifestAPISchema1(t *testing.T, env *testEnv, imageName string) manifestArgs {
|
||||
func testManifestAPISchema1(t *testing.T, env *testEnv, imageName reference.Named) manifestArgs {
|
||||
tag := "thetag"
|
||||
args := manifestArgs{imageName: imageName}
|
||||
|
||||
|
@ -784,7 +792,7 @@ func testManifestAPISchema1(t *testing.T, env *testEnv, imageName string) manife
|
|||
Versioned: manifest.Versioned{
|
||||
SchemaVersion: 1,
|
||||
},
|
||||
Name: imageName,
|
||||
Name: imageName.Name(),
|
||||
Tag: tag,
|
||||
FSLayers: []schema1.FSLayer{
|
||||
{
|
||||
|
@ -1032,8 +1040,8 @@ func testManifestAPISchema1(t *testing.T, env *testEnv, imageName string) manife
|
|||
t.Fatalf("unexpected error decoding error response: %v", err)
|
||||
}
|
||||
|
||||
if tagsResponse.Name != imageName {
|
||||
t.Fatalf("tags name should match image name: %v != %v", tagsResponse.Name, imageName)
|
||||
if tagsResponse.Name != imageName.Name() {
|
||||
t.Fatalf("tags name should match image name: %v != %v", tagsResponse.Name, imageName.Name())
|
||||
}
|
||||
|
||||
if len(tagsResponse.Tags) != 1 {
|
||||
|
@ -1060,7 +1068,7 @@ func testManifestAPISchema1(t *testing.T, env *testEnv, imageName string) manife
|
|||
return args
|
||||
}
|
||||
|
||||
func testManifestAPISchema2(t *testing.T, env *testEnv, imageName string) manifestArgs {
|
||||
func testManifestAPISchema2(t *testing.T, env *testEnv, imageName reference.Named) manifestArgs {
|
||||
tag := "schema2tag"
|
||||
args := manifestArgs{
|
||||
imageName: imageName,
|
||||
|
@ -1340,7 +1348,7 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName string) manife
|
|||
t.Fatalf("unexpected error decoding error response: %v", err)
|
||||
}
|
||||
|
||||
if tagsResponse.Name != imageName {
|
||||
if tagsResponse.Name != imageName.Name() {
|
||||
t.Fatalf("tags name should match image name: %v != %v", tagsResponse.Name, imageName)
|
||||
}
|
||||
|
||||
|
@ -1379,7 +1387,7 @@ func testManifestAPISchema2(t *testing.T, env *testEnv, imageName string) manife
|
|||
if fetchedSchema1Manifest.Architecture != "amd64" {
|
||||
t.Fatal("wrong architecture")
|
||||
}
|
||||
if fetchedSchema1Manifest.Name != imageName {
|
||||
if fetchedSchema1Manifest.Name != imageName.Name() {
|
||||
t.Fatal("wrong image name")
|
||||
}
|
||||
if fetchedSchema1Manifest.Tag != tag {
|
||||
|
@ -1602,7 +1610,7 @@ func testManifestAPIManifestList(t *testing.T, env *testEnv, args manifestArgs)
|
|||
if fetchedSchema1Manifest.Architecture != "amd64" {
|
||||
t.Fatal("wrong architecture")
|
||||
}
|
||||
if fetchedSchema1Manifest.Name != imageName {
|
||||
if fetchedSchema1Manifest.Name != imageName.Name() {
|
||||
t.Fatal("wrong image name")
|
||||
}
|
||||
if fetchedSchema1Manifest.Tag != tag {
|
||||
|
@ -1715,7 +1723,7 @@ func testManifestDelete(t *testing.T, env *testEnv, args manifestArgs) {
|
|||
t.Fatalf("unexpected error decoding error response: %v", err)
|
||||
}
|
||||
|
||||
if tagsResponse.Name != imageName {
|
||||
if tagsResponse.Name != imageName.Name() {
|
||||
t.Fatalf("tags name should match image name: %v != %v", tagsResponse.Name, imageName)
|
||||
}
|
||||
|
||||
|
@ -1749,7 +1757,7 @@ func testManifestDelete(t *testing.T, env *testEnv, args manifestArgs) {
|
|||
t.Fatalf("unexpected error decoding error response: %v", err)
|
||||
}
|
||||
|
||||
if tagsResponse.Name != imageName {
|
||||
if tagsResponse.Name != imageName.Name() {
|
||||
t.Fatalf("tags name should match image name: %v != %v", tagsResponse.Name, imageName)
|
||||
}
|
||||
|
||||
|
@ -1863,7 +1871,7 @@ func putManifest(t *testing.T, msg, url, contentType string, v interface{}) *htt
|
|||
return resp
|
||||
}
|
||||
|
||||
func startPushLayer(t *testing.T, ub *v2.URLBuilder, name string) (location string, uuid string) {
|
||||
func startPushLayer(t *testing.T, ub *v2.URLBuilder, name reference.Named) (location string, uuid string) {
|
||||
layerUploadURL, err := ub.BuildBlobUploadURL(name)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error building layer upload url: %v", err)
|
||||
|
@ -1875,7 +1883,7 @@ func startPushLayer(t *testing.T, ub *v2.URLBuilder, name string) (location stri
|
|||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
checkResponse(t, fmt.Sprintf("pushing starting layer push %v", name), resp, http.StatusAccepted)
|
||||
checkResponse(t, fmt.Sprintf("pushing starting layer push %v", name.String()), resp, http.StatusAccepted)
|
||||
|
||||
u, err := url.Parse(resp.Header.Get("Location"))
|
||||
if err != nil {
|
||||
|
@ -1894,7 +1902,7 @@ func startPushLayer(t *testing.T, ub *v2.URLBuilder, name string) (location stri
|
|||
|
||||
// doPushLayer pushes the layer content returning the url on success returning
|
||||
// the response. If you're only expecting a successful response, use pushLayer.
|
||||
func doPushLayer(t *testing.T, ub *v2.URLBuilder, name string, dgst digest.Digest, uploadURLBase string, body io.Reader) (*http.Response, error) {
|
||||
func doPushLayer(t *testing.T, ub *v2.URLBuilder, name reference.Named, dgst digest.Digest, uploadURLBase string, body io.Reader) (*http.Response, error) {
|
||||
u, err := url.Parse(uploadURLBase)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error parsing pushLayer url: %v", err)
|
||||
|
@ -1918,7 +1926,7 @@ func doPushLayer(t *testing.T, ub *v2.URLBuilder, name string, dgst digest.Diges
|
|||
}
|
||||
|
||||
// pushLayer pushes the layer content returning the url on success.
|
||||
func pushLayer(t *testing.T, ub *v2.URLBuilder, name string, dgst digest.Digest, uploadURLBase string, body io.Reader) string {
|
||||
func pushLayer(t *testing.T, ub *v2.URLBuilder, name reference.Named, dgst digest.Digest, uploadURLBase string, body io.Reader) string {
|
||||
digester := digest.Canonical.New()
|
||||
|
||||
resp, err := doPushLayer(t, ub, name, dgst, uploadURLBase, io.TeeReader(body, digester.Hash()))
|
||||
|
@ -1949,7 +1957,7 @@ func pushLayer(t *testing.T, ub *v2.URLBuilder, name string, dgst digest.Digest,
|
|||
return resp.Header.Get("Location")
|
||||
}
|
||||
|
||||
func finishUpload(t *testing.T, ub *v2.URLBuilder, name string, uploadURLBase string, dgst digest.Digest) string {
|
||||
func finishUpload(t *testing.T, ub *v2.URLBuilder, name reference.Named, uploadURLBase string, dgst digest.Digest) string {
|
||||
resp, err := doPushLayer(t, ub, name, dgst, uploadURLBase, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error doing push layer request: %v", err)
|
||||
|
@ -1997,7 +2005,7 @@ func doPushChunk(t *testing.T, uploadURLBase string, body io.Reader) (*http.Resp
|
|||
return resp, digester.Digest(), err
|
||||
}
|
||||
|
||||
func pushChunk(t *testing.T, ub *v2.URLBuilder, name string, uploadURLBase string, body io.Reader, length int64) (string, digest.Digest) {
|
||||
func pushChunk(t *testing.T, ub *v2.URLBuilder, name reference.Named, uploadURLBase string, body io.Reader, length int64) (string, digest.Digest) {
|
||||
resp, dgst, err := doPushChunk(t, uploadURLBase, body)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error doing push layer request: %v", err)
|
||||
|
@ -2133,6 +2141,11 @@ func checkErr(t *testing.T, err error, msg string) {
|
|||
}
|
||||
|
||||
func createRepository(env *testEnv, t *testing.T, imageName string, tag string) digest.Digest {
|
||||
imageNameRef, err := reference.ParseNamed(imageName)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse reference: %v", err)
|
||||
}
|
||||
|
||||
unsignedManifest := &schema1.Manifest{
|
||||
Versioned: manifest.Versioned{
|
||||
SchemaVersion: 1,
|
||||
|
@ -2164,8 +2177,8 @@ func createRepository(env *testEnv, t *testing.T, imageName string, tag string)
|
|||
expectedLayers[dgst] = rs
|
||||
unsignedManifest.FSLayers[i].BlobSum = dgst
|
||||
|
||||
uploadURLBase, _ := startPushLayer(t, env.builder, imageName)
|
||||
pushLayer(t, env.builder, imageName, dgst, uploadURLBase, rs)
|
||||
uploadURLBase, _ := startPushLayer(t, env.builder, imageNameRef)
|
||||
pushLayer(t, env.builder, imageNameRef, dgst, uploadURLBase, rs)
|
||||
}
|
||||
|
||||
signedManifest, err := schema1.Sign(unsignedManifest, env.pk)
|
||||
|
@ -2176,10 +2189,10 @@ func createRepository(env *testEnv, t *testing.T, imageName string, tag string)
|
|||
dgst := digest.FromBytes(signedManifest.Canonical)
|
||||
|
||||
// Create this repository by tag to ensure the tag mapping is made in the registry
|
||||
manifestDigestURL, err := env.builder.BuildManifestURL(imageName, tag)
|
||||
manifestDigestURL, err := env.builder.BuildManifestURL(imageNameRef, tag)
|
||||
checkErr(t, err, "building manifest url")
|
||||
|
||||
location, err := env.builder.BuildManifestURL(imageName, dgst.String())
|
||||
location, err := env.builder.BuildManifestURL(imageNameRef, dgst.String())
|
||||
checkErr(t, err, "building location URL")
|
||||
|
||||
resp := putManifest(t, "putting signed manifest", manifestDigestURL, "", signedManifest)
|
||||
|
@ -2197,7 +2210,7 @@ func TestRegistryAsCacheMutationAPIs(t *testing.T) {
|
|||
deleteEnabled := true
|
||||
env := newTestEnvMirror(t, deleteEnabled)
|
||||
|
||||
imageName := "foo/bar"
|
||||
imageName, _ := reference.ParseNamed("foo/bar")
|
||||
tag := "latest"
|
||||
manifestURL, err := env.builder.BuildManifestURL(imageName, tag)
|
||||
if err != nil {
|
||||
|
@ -2209,7 +2222,7 @@ func TestRegistryAsCacheMutationAPIs(t *testing.T) {
|
|||
Versioned: manifest.Versioned{
|
||||
SchemaVersion: 1,
|
||||
},
|
||||
Name: imageName,
|
||||
Name: imageName.Name(),
|
||||
Tag: tag,
|
||||
FSLayers: []schema1.FSLayer{},
|
||||
History: []schema1.History{},
|
||||
|
@ -2284,12 +2297,12 @@ func TestProxyManifestGetByTag(t *testing.T) {
|
|||
}
|
||||
truthConfig.HTTP.Headers = headerConfig
|
||||
|
||||
imageName := "foo/bar"
|
||||
imageName, _ := reference.ParseNamed("foo/bar")
|
||||
tag := "latest"
|
||||
|
||||
truthEnv := newTestEnvWithConfig(t, &truthConfig)
|
||||
// create a repository in the truth registry
|
||||
dgst := createRepository(truthEnv, t, imageName, tag)
|
||||
dgst := createRepository(truthEnv, t, imageName.Name(), tag)
|
||||
|
||||
proxyConfig := configuration.Configuration{
|
||||
Storage: configuration.Storage{
|
||||
|
@ -2322,7 +2335,7 @@ func TestProxyManifestGetByTag(t *testing.T) {
|
|||
})
|
||||
|
||||
// Create another manifest in the remote with the same image/tag pair
|
||||
newDigest := createRepository(truthEnv, t, imageName, tag)
|
||||
newDigest := createRepository(truthEnv, t, imageName.Name(), tag)
|
||||
if dgst == newDigest {
|
||||
t.Fatalf("non-random test data")
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue