Skip to content

Commit 1c62aa2

Browse files
committed
retry logic for image and manifest loading in UploadCachedImage
1 parent bc39b20 commit 1c62aa2

File tree

1 file changed

+49
-7
lines changed

1 file changed

+49
-7
lines changed

pkg/minikube/image/image.go

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -212,11 +212,7 @@ func UploadCachedImage(imgName string) error {
212212
return err
213213
}
214214
if err := uploadImage(tag, imagePathInCache(imgName)); err != nil {
215-
// this time try determine image tags from tarball
216-
217-
manifest, err := tarball.LoadManifest(func() (io.ReadCloser, error) {
218-
return os.Open(imagePathInCache(imgName))
219-
})
215+
manifest, err := loadManifestWithRetry(imagePathInCache(imgName))
220216
if err != nil || len(manifest) == 0 || len(manifest[0].RepoTags) == 0 {
221217
return fmt.Errorf("failed to determine the image tag from tarball, err: %v", err)
222218
}
@@ -239,9 +235,9 @@ func uploadImage(tag name.Tag, p string) error {
239235
return fmt.Errorf("neither daemon nor remote")
240236
}
241237

242-
img, err = tarball.ImageFromPath(p, &tag)
238+
img, err = imageFromPathWithRetry(p, tag)
243239
if err != nil {
244-
return errors.Wrap(err, "tarball")
240+
return err
245241
}
246242
ref := name.Reference(tag)
247243

@@ -271,6 +267,52 @@ func uploadRemote(ref name.Reference, img v1.Image, p v1.Platform) error {
271267
return err
272268
}
273269

270+
func imageFromPathWithRetry(path string, tag name.Tag) (v1.Image, error) {
271+
var lastErr error
272+
const maxAttempts = 3
273+
for i := 0; i < maxAttempts; i++ {
274+
if i > 0 {
275+
time.Sleep(200 * time.Millisecond)
276+
}
277+
img, err := tarball.ImageFromPath(path, &tag)
278+
if err == nil {
279+
return img, nil
280+
}
281+
lastErr = errors.Wrap(err, "tarball")
282+
if !isRetryableEOF(err) {
283+
return nil, lastErr
284+
}
285+
klog.Infof("retrying tarball read for %s due to EOF (%d/%d)", path, i+1, maxAttempts)
286+
}
287+
return nil, lastErr
288+
}
289+
290+
func loadManifestWithRetry(path string) (tarball.Manifest, error) {
291+
var lastErr error
292+
const maxAttempts = 3
293+
for i := 0; i < maxAttempts; i++ {
294+
if i > 0 {
295+
time.Sleep(200 * time.Millisecond)
296+
}
297+
manifest, err := tarball.LoadManifest(func() (io.ReadCloser, error) {
298+
return os.Open(path)
299+
})
300+
if err == nil {
301+
return manifest, nil
302+
}
303+
lastErr = err
304+
if !isRetryableEOF(err) {
305+
return nil, lastErr
306+
}
307+
klog.Infof("retrying manifest read for %s due to EOF (%d/%d)", path, i+1, maxAttempts)
308+
}
309+
return nil, lastErr
310+
}
311+
312+
func isRetryableEOF(err error) bool {
313+
return errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF) || strings.Contains(err.Error(), "unexpected EOF")
314+
}
315+
274316
// See https://github.com/kubernetes/minikube/issues/10402
275317
// check if downloaded image Architecture field matches the requested and fix it otherwise
276318
func fixPlatform(ref name.Reference, img v1.Image, p v1.Platform) (v1.Image, error) {

0 commit comments

Comments
 (0)