Skip to content

Commit 66dd454

Browse files
authored
remote: retry failed Puller and Pusher initialization (#2406)
1 parent 3f47f91 commit 66dd454

3 files changed

Lines changed: 97 additions & 2 deletions

File tree

‎pkg/v1/remote/puller.go‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,11 @@ func (p *Puller) fetcher(ctx context.Context, target resource) (*fetcher, error)
7676
o: p.o,
7777
})
7878
rr := v.(*reader)
79-
return rr.f, rr.init(ctx)
79+
if err := rr.init(ctx); err != nil {
80+
p.readers.CompareAndDelete(target, rr)
81+
return nil, err
82+
}
83+
return rr.f, nil
8084
}
8185

8286
// Head is like remote.Head, but avoids re-authenticating when possible.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright 2026 Google LLC All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package remote
16+
17+
import (
18+
"context"
19+
"errors"
20+
"fmt"
21+
"net/http/httptest"
22+
"net/url"
23+
"testing"
24+
25+
"github.com/google/go-containerregistry/pkg/name"
26+
"github.com/google/go-containerregistry/pkg/registry"
27+
"github.com/google/go-containerregistry/pkg/v1/empty"
28+
)
29+
30+
func TestPullerRetriesFailedInitialization(t *testing.T) {
31+
s := httptest.NewServer(registry.New())
32+
defer s.Close()
33+
34+
ref := registryReference(t, s.URL)
35+
if err := Write(ref, empty.Image); err != nil {
36+
t.Fatalf("Write() = %v", err)
37+
}
38+
39+
puller, err := NewPuller()
40+
if err != nil {
41+
t.Fatalf("NewPuller() = %v", err)
42+
}
43+
44+
ctx, cancel := context.WithCancel(context.Background())
45+
cancel()
46+
if _, err := puller.Head(ctx, ref); !errors.Is(err, context.Canceled) {
47+
t.Fatalf("Head() = %v, want context.Canceled", err)
48+
}
49+
50+
if _, err := puller.Head(context.Background(), ref); err != nil {
51+
t.Fatalf("Head() after canceled initialization = %v", err)
52+
}
53+
}
54+
55+
func TestPusherRetriesFailedInitialization(t *testing.T) {
56+
s := httptest.NewServer(registry.New())
57+
defer s.Close()
58+
59+
ref := registryReference(t, s.URL)
60+
pusher, err := NewPusher()
61+
if err != nil {
62+
t.Fatalf("NewPusher() = %v", err)
63+
}
64+
65+
ctx, cancel := context.WithCancel(context.Background())
66+
cancel()
67+
if err := pusher.Push(ctx, ref, empty.Image); !errors.Is(err, context.Canceled) {
68+
t.Fatalf("Push() = %v, want context.Canceled", err)
69+
}
70+
71+
if err := pusher.Push(context.Background(), ref, empty.Image); err != nil {
72+
t.Fatalf("Push() after canceled initialization = %v", err)
73+
}
74+
}
75+
76+
func registryReference(t *testing.T, registryURL string) name.Reference {
77+
t.Helper()
78+
u, err := url.Parse(registryURL)
79+
if err != nil {
80+
t.Fatalf("url.Parse(%q) = %v", registryURL, err)
81+
}
82+
ref, err := name.NewTag(fmt.Sprintf("%s/retry/init:latest", u.Host))
83+
if err != nil {
84+
t.Fatalf("name.NewTag() = %v", err)
85+
}
86+
return ref
87+
}

‎pkg/v1/remote/pusher.go‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,11 @@ func (p *Pusher) writer(ctx context.Context, repo name.Repository, o *options) (
122122
o: o,
123123
})
124124
rw := v.(*repoWriter)
125-
return rw, rw.init(ctx)
125+
if err := rw.init(ctx); err != nil {
126+
p.writers.CompareAndDelete(repo, rw)
127+
return nil, err
128+
}
129+
return rw, nil
126130
}
127131

128132
func (p *Pusher) Put(ctx context.Context, ref name.Reference, t Taggable) error {

0 commit comments

Comments
 (0)