mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
docker/save: stable timestamp for blobs/digest dir
Writing the OCI manifest file to the blobs/digest dir will update the directory mtime, producing a tar file containing a member with a contemporary mtime. Exported tars for the same image will therefore have different checksums. Although this was previously addressed by overriding the mtime manually to 0, this was done before the OCI manifest file was written. This change simply moves the call to system.Chtimes to set the mtime of the blobs/digest directory to 0 after writing the OCI manifest file. This commit also updates the TestSaveCheckTimes integration test to check the mtime of all members in the exported tar to ensure that all mtime are not newer than img.Created or 0 (depending on whether the containerd-snapshotter is disabled or enabled, respectively). Signed-off-by: Sam Nicholls <sam.nicholls@nanoporetech.com>
This commit is contained in:
@@ -264,14 +264,14 @@ func (s *saveSession) save(ctx context.Context, outStream io.Writer) error {
|
||||
if err := mkdirAllWithChtimes(filepath.Dir(mFile), 0o755, time.Unix(0, 0), time.Unix(0, 0)); err != nil {
|
||||
return errors.Wrap(err, "error creating blob directory")
|
||||
}
|
||||
if err := system.Chtimes(filepath.Dir(mFile), time.Unix(0, 0), time.Unix(0, 0)); err != nil {
|
||||
return errors.Wrap(err, "error setting blob directory timestamps")
|
||||
}
|
||||
if err := os.WriteFile(mFile, data, 0o644); err != nil {
|
||||
return errors.Wrap(err, "error writing oci manifest file")
|
||||
}
|
||||
if err := system.Chtimes(mFile, time.Unix(0, 0), time.Unix(0, 0)); err != nil {
|
||||
return errors.Wrap(err, "error setting blob directory timestamps")
|
||||
return errors.Wrap(err, "error setting oci manifest timestamp")
|
||||
}
|
||||
if err := system.Chtimes(filepath.Dir(mFile), time.Unix(0, 0), time.Unix(0, 0)); err != nil {
|
||||
return errors.Wrap(err, "error setting blob digest directory timestamp")
|
||||
}
|
||||
|
||||
untaggedMfstDesc := ocispec.Descriptor{
|
||||
|
||||
@@ -65,26 +65,25 @@ func TestSaveCheckTimes(t *testing.T) {
|
||||
rdr, err := apiClient.ImageSave(ctx, []string{repoName})
|
||||
assert.NilError(t, err)
|
||||
|
||||
tarfs := tarIndexFS(t, rdr)
|
||||
|
||||
dt, err := fs.ReadFile(tarfs, "manifest.json")
|
||||
assert.NilError(t, err)
|
||||
|
||||
var ls []imageSaveManifestEntry
|
||||
assert.NilError(t, json.Unmarshal(dt, &ls))
|
||||
assert.Assert(t, is.Len(ls, 1))
|
||||
|
||||
info, err := fs.Stat(tarfs, ls[0].Config)
|
||||
assert.NilError(t, err)
|
||||
|
||||
created, err := time.Parse(time.RFC3339, img.Created)
|
||||
assert.NilError(t, err)
|
||||
|
||||
if testEnv.UsingSnapshotter() {
|
||||
// containerd archive export sets the mod time to zero.
|
||||
assert.Check(t, is.Equal(info.ModTime(), time.Unix(0, 0)))
|
||||
} else {
|
||||
assert.Check(t, is.Equal(info.ModTime().Format(time.RFC3339), created.Format(time.RFC3339)))
|
||||
// containerd archive export sets mod times of all members to zero
|
||||
// otherwise no member should be newer than the image created date
|
||||
threshold := time.Unix(0, 0)
|
||||
if !testEnv.UsingSnapshotter() {
|
||||
threshold = created
|
||||
}
|
||||
|
||||
tr := tar.NewReader(rdr)
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
assert.NilError(t, err)
|
||||
modtime := hdr.ModTime
|
||||
assert.Check(t, !modtime.After(threshold), "%s has modtime %s after %s", hdr.Name, modtime, threshold)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user