feat(master): suggest newer version tags for third-party images (#11) (#31)
Docker Build / docker (push) Successful in 45s
Docker Build / docker (push) Successful in 45s
This commit was merged in pull request #31.
This commit is contained in:
@@ -134,6 +134,8 @@ func TestDigestIgnoresDigestSuffix(t *testing.T) {
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
// Digest asks the manifest endpoint with HEAD only; the one other request is
|
||||
// the GET /v2/ ping that every client sends first.
|
||||
func TestDigestUsesHeadOnly(t *testing.T) {
|
||||
dockerConfig(t, "")
|
||||
reg := newTestRegistry(t, "", "")
|
||||
@@ -236,7 +238,7 @@ func TestCredsStoreWithoutHelperFailsTheLookup(t *testing.T) {
|
||||
}
|
||||
|
||||
// A registry that leaves out Docker-Content-Digest must not make the client
|
||||
// retry with a manifest download, which Docker Hub counts as a pull.
|
||||
// retry with a manifest GET, which Docker Hub counts as a pull.
|
||||
func TestMissingDigestHeaderDoesNotFallBackToDownload(t *testing.T) {
|
||||
dockerConfig(t, "")
|
||||
var mu sync.Mutex
|
||||
@@ -334,3 +336,101 @@ func TestClassify(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// pushTags stores a random index under each tag of repo.
|
||||
func (tr *testRegistry) pushTags(t *testing.T, repo string, tags ...string) {
|
||||
t.Helper()
|
||||
for _, tag := range tags {
|
||||
tr.pushIndex(t, repo, tag)
|
||||
}
|
||||
}
|
||||
|
||||
// Digest and Tags together never GET a manifest: every manifest request is a
|
||||
// HEAD, and the only other requests are the /v2/ ping and tags/list.
|
||||
func TestNoManifestGet(t *testing.T) {
|
||||
dockerConfig(t, "")
|
||||
reg := newTestRegistry(t, "", "")
|
||||
reg.pushTags(t, "team/app", "1.2", "1.3")
|
||||
reg.reset()
|
||||
|
||||
_, err := newClient().Digest(context.Background(), reg.host+"/team/app:1.2")
|
||||
require.NoError(t, err)
|
||||
_, err = newClient().Tags(context.Background(), reg.host+"/team/app")
|
||||
require.NoError(t, err)
|
||||
|
||||
reg.mu.Lock()
|
||||
defer reg.mu.Unlock()
|
||||
for _, r := range reg.requests {
|
||||
switch {
|
||||
case strings.Contains(r.path, "/manifests/"):
|
||||
assert.Equal(t, http.MethodHead, r.method, r.path)
|
||||
case r.path == "/v2/", r.path == "/v2/team/app/tags/list":
|
||||
assert.Equal(t, http.MethodGet, r.method, r.path)
|
||||
default:
|
||||
assert.Failf(t, "unexpected request", "%s %s", r.method, r.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTagsListsAllTags(t *testing.T) {
|
||||
dockerConfig(t, "")
|
||||
reg := newTestRegistry(t, "", "")
|
||||
reg.pushTags(t, "team/app", "1.2", "1.3", "latest")
|
||||
|
||||
got, err := newClient().Tags(context.Background(), reg.host+"/team/app")
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.ElementsMatch(t, []string{"1.2", "1.3", "latest"}, got)
|
||||
}
|
||||
|
||||
// ggcr's in-memory registry sends no Link header, so pagination is tested
|
||||
// against a handler that does.
|
||||
func TestTagsFollowsLinkPagination(t *testing.T) {
|
||||
dockerConfig(t, "")
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
case r.URL.Path == "/v2/":
|
||||
case r.URL.Path == "/v2/a/b/tags/list" && r.URL.Query().Get("last") == "":
|
||||
w.Header().Set("Link", `</v2/a/b/tags/list?last=1.3&n=2>; rel="next"`)
|
||||
_, _ = w.Write([]byte(`{"name":"a/b","tags":["1.2","1.3"]}`))
|
||||
case r.URL.Path == "/v2/a/b/tags/list":
|
||||
_, _ = w.Write([]byte(`{"name":"a/b","tags":["1.4"]}`))
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
t.Cleanup(srv.Close)
|
||||
|
||||
got, err := newClient().Tags(context.Background(), strings.TrimPrefix(srv.URL, "http://")+"/a/b")
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []string{"1.2", "1.3", "1.4"}, got)
|
||||
}
|
||||
|
||||
func TestTagsUsesDockerConfigCredentials(t *testing.T) {
|
||||
reg := newTestRegistry(t, "bot", "s3cret")
|
||||
reg.pushIndex(t, "team/app", "1.2", remote.WithAuth(&authn.Basic{Username: "bot", Password: "s3cret"}))
|
||||
auth := base64.StdEncoding.EncodeToString([]byte("bot:s3cret"))
|
||||
dockerConfig(t, `{"auths":{"`+reg.host+`":{"auth":"`+auth+`"}}}`)
|
||||
|
||||
got, err := newClient().Tags(context.Background(), reg.host+"/team/app")
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []string{"1.2"}, got)
|
||||
}
|
||||
|
||||
func TestTagsErrorBodyDoesNotLeak(t *testing.T) {
|
||||
dockerConfig(t, "")
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
_, _ = w.Write([]byte(`{"errors":[{"code":"NAME_UNKNOWN","message":"internal-secret-body"}]}`))
|
||||
}))
|
||||
t.Cleanup(srv.Close)
|
||||
host := strings.TrimPrefix(srv.URL, "http://")
|
||||
|
||||
_, err := newClient().Tags(context.Background(), host+"/a/b")
|
||||
|
||||
require.Error(t, err)
|
||||
assert.NotContains(t, err.Error(), "internal-secret-body")
|
||||
assert.ErrorContains(t, err, "list "+host+"/a/b: registry answered 400 Bad Request")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user