diff --git a/api_test.go b/api_test.go index 41f3de695..15ba0ca6f 100644 --- a/api_test.go +++ b/api_test.go @@ -195,6 +195,32 @@ func TestManifestAPI(t *testing.T) { t.Fatalf("expected manifest unknown error: got %v", respErrs) } + tagsURL, err := 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) + dec = json.NewDecoder(resp.Body) + if err := dec.Decode(&respErrs); err != nil { + t.Fatalf("unexpected error decoding error response: %v", err) + } + + if len(respErrs.Errors) == 0 { + t.Fatalf("expected errors in response") + } + + if respErrs.Errors[0].Code != ErrorCodeUnknownRepository { + t.Fatalf("expected respository unknown error: got %v", respErrs) + } + // -------------------------------- // Attempt to push unsigned manifest with missing layers unsignedManifest := &storage.Manifest{ @@ -300,6 +326,35 @@ func TestManifestAPI(t *testing.T) { if !bytes.Equal(fetchedManifest.Raw, signedManifest.Raw) { t.Fatalf("manifests do not match") } + + // 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() + + // Check that we get an unknown repository error when asking for tags + checkResponse(t, "getting unknown manifest 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 { + t.Fatalf("tags name should match image name: %v != %v", tagsResponse.Name, imageName) + } + + 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) + } } func putManifest(t *testing.T, msg, url string, v interface{}) *http.Response { diff --git a/urls.go b/urls.go index d9e77f5e8..8f34a5b1e 100644 --- a/urls.go +++ b/urls.go @@ -39,6 +39,20 @@ func newURLBuilderFromString(root string) (*urlBuilder, error) { return newURLBuilder(u), nil } +func (ub *urlBuilder) buildTagsURL(name string) (string, error) { + route := clonedRoute(ub.router, routeNameTags) + + tagsURL, err := route. + Schemes(ub.url.Scheme). + Host(ub.url.Host). + URL("name", name) + if err != nil { + return "", err + } + + return tagsURL.String(), nil +} + func (ub *urlBuilder) forManifest(m *storage.Manifest) (string, error) { return ub.buildManifestURL(m.Name, m.Tag) }