Skip to content

Commit f658f33

Browse files
committed
downloader: re-download digest-less cached images if last-modified differs
Signed-off-by: Norio Nomura <[email protected]>
1 parent ac1fc4f commit f658f33

File tree

2 files changed

+55
-8
lines changed

2 files changed

+55
-8
lines changed

pkg/downloader/downloader.go

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ func Download(ctx context.Context, local, remote string, opts ...Opt) (*Result,
229229
}
230230
if _, err := os.Stat(shadData); err == nil {
231231
logrus.Debugf("file %q is cached as %q", localPath, shadData)
232+
useCache := true
232233
if _, err := os.Stat(shadDigest); err == nil {
233234
logrus.Debugf("Comparing digest %q with the cached digest file %q, not computing the actual digest of %q",
234235
o.expectedDigest, shadDigest, shadData)
@@ -239,18 +240,27 @@ func Download(ctx context.Context, local, remote string, opts ...Opt) (*Result,
239240
return nil, err
240241
}
241242
} else {
242-
if err := copyLocal(ctx, localPath, shadData, ext, o.decompress, o.description, o.expectedDigest); err != nil {
243+
if match, err := matchLastModified(ctx, shadTime, remote); err != nil {
243244
return nil, err
245+
} else if match {
246+
if err := copyLocal(ctx, localPath, shadData, ext, o.decompress, o.description, o.expectedDigest); err != nil {
247+
return nil, err
248+
}
249+
} else {
250+
logrus.Info("Re-downloading digest-less image: last-modified mismatch detected.")
251+
useCache = false
244252
}
245253
}
246-
res := &Result{
247-
Status: StatusUsedCache,
248-
CachePath: shadData,
249-
LastModified: readTime(shadTime),
250-
ContentType: readFile(shadType),
251-
ValidatedDigest: o.expectedDigest != "",
254+
if useCache {
255+
res := &Result{
256+
Status: StatusUsedCache,
257+
CachePath: shadData,
258+
LastModified: readTime(shadTime),
259+
ContentType: readFile(shadType),
260+
ValidatedDigest: o.expectedDigest != "",
261+
}
262+
return res, nil
252263
}
253-
return res, nil
254264
}
255265
if err := os.RemoveAll(shad); err != nil {
256266
return nil, err
@@ -516,6 +526,27 @@ func validateLocalFileDigest(localPath string, expectedDigest digest.Digest) err
516526
return nil
517527
}
518528

529+
func matchLastModified(ctx context.Context, lastModified, url string) (bool, error) {
530+
if lastModified == "" {
531+
return false, nil
532+
}
533+
resp, err := httpclientutil.Head(ctx, http.DefaultClient, url)
534+
if err != nil {
535+
return false, err
536+
}
537+
defer resp.Body.Close()
538+
lm := resp.Header.Get("Last-Modified")
539+
if lm == "" {
540+
return false, nil
541+
}
542+
lmTime, err := time.Parse(http.TimeFormat, lm)
543+
if err != nil {
544+
return false, nil
545+
}
546+
lastModifiedTime := readTime(lastModified)
547+
return lmTime.Equal(lastModifiedTime), nil
548+
}
549+
519550
func downloadHTTP(ctx context.Context, localPath, lastModified, contentType, url, description string, expectedDigest digest.Digest) error {
520551
if localPath == "" {
521552
return fmt.Errorf("downloadHTTP: got empty localPath")

pkg/httpclientutil/httpclientutil.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,22 @@ func Get(ctx context.Context, c *http.Client, url string) (*http.Response, error
3232
return resp, nil
3333
}
3434

35+
func Head(ctx context.Context, c *http.Client, url string) (*http.Response, error) {
36+
req, err := http.NewRequestWithContext(ctx, "HEAD", url, http.NoBody)
37+
if err != nil {
38+
return nil, err
39+
}
40+
resp, err := c.Do(req)
41+
if err != nil {
42+
return nil, err
43+
}
44+
if err := Successful(resp); err != nil {
45+
resp.Body.Close()
46+
return nil, err
47+
}
48+
return resp, nil
49+
}
50+
3551
func Post(ctx context.Context, c *http.Client, url string, body io.Reader) (*http.Response, error) {
3652
req, err := http.NewRequestWithContext(ctx, "POST", url, body)
3753
if err != nil {

0 commit comments

Comments
 (0)