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:
Aaron Lehmann 2015-12-15 14:35:23 -08:00
parent e9bcc96ad2
commit e9692b8037
26 changed files with 235 additions and 193 deletions

View file

@ -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")
}