diff options
author | Rob Cowsill <42620235+rcowsill@users.noreply.github.com> | 2021-01-21 21:55:29 +0000 |
---|---|---|
committer | Rob Cowsill <42620235+rcowsill@users.noreply.github.com> | 2021-01-21 22:04:23 +0000 |
commit | 42dba8c3f9a821c64864c49e60fff9b3ba3e86c5 (patch) | |
tree | bc7561b13a017739479927df814c024520341e5f /image | |
parent | b865beba22aac576b95952fef97d4e775632c362 (diff) | |
download | docker-42dba8c3f9a821c64864c49e60fff9b3ba3e86c5.tar.gz |
Fix spurious error from "docker load"
"docker load" validates parent links by comparing image histories, and the
History struct has a time.Time member "Created". Time.UnmarshalJSON can read
RFC3339 timestamps with offset "+00:00", but t.MarshalJSON writes them with
offset "Z". Equivalent times in these two formats are not equal when compared
with the == operator.
This causes checkValidParent to incorrectly return false when the parent image
history contains times using offset "+00:00". In that case the history copied
to the child image will have been converted into "Z" form when marshaled out.
This patch adds an "Equal" method to History, which compares "Created" times
with t.Equal. This is used instead of reflect.DeepEqual in checkValidParent.
Signed-off-by: Rob Cowsill <42620235+rcowsill@users.noreply.github.com>
Diffstat (limited to 'image')
-rw-r--r-- | image/image.go | 11 | ||||
-rw-r--r-- | image/image_test.go | 23 | ||||
-rw-r--r-- | image/tarexport/load.go | 3 |
3 files changed, 35 insertions, 2 deletions
diff --git a/image/image.go b/image/image.go index 29de613a3e..a9db58fd65 100644 --- a/image/image.go +++ b/image/image.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "io" + "reflect" "runtime" "strings" "time" @@ -218,6 +219,16 @@ func NewHistory(author, comment, createdBy string, isEmptyLayer bool) History { } } +// Equal compares two history structs for equality +func (h History) Equal(i History) bool { + if !h.Created.Equal(i.Created) { + return false + } + i.Created = h.Created + + return reflect.DeepEqual(h, i) +} + // Exporter provides interface for loading and saving images type Exporter interface { Load(io.ReadCloser, io.Writer, bool) error diff --git a/image/image_test.go b/image/image_test.go index b174b80908..21f81c768d 100644 --- a/image/image_test.go +++ b/image/image_test.go @@ -56,6 +56,29 @@ func TestMarshalKeyOrder(t *testing.T) { } } +const sampleHistoryJSON = `{ + "created": "2021-01-13T09:35:56Z", + "created_by": "image_test.go" +}` + +func TestHistoryEqual(t *testing.T) { + h := historyFromJSON(t, sampleHistoryJSON) + hCopy := h + assert.Check(t, h.Equal(hCopy)) + + hUTC := historyFromJSON(t, `{"created": "2021-01-13T14:00:00Z"}`) + hOffset0 := historyFromJSON(t, `{"created": "2021-01-13T14:00:00+00:00"}`) + assert.Check(t, hUTC.Created != hOffset0.Created) + assert.Check(t, hUTC.Equal(hOffset0)) +} + +func historyFromJSON(t *testing.T, historyJSON string) History { + var h History + err := json.Unmarshal([]byte(historyJSON), &h) + assert.Check(t, err) + return h +} + func TestImage(t *testing.T) { cid := "50a16564e727" config := &container.Config{ diff --git a/image/tarexport/load.go b/image/tarexport/load.go index bbbb238b2b..37ac4bf082 100644 --- a/image/tarexport/load.go +++ b/image/tarexport/load.go @@ -8,7 +8,6 @@ import ( "io/ioutil" "os" "path/filepath" - "reflect" "runtime" "github.com/containerd/containerd/platforms" @@ -406,7 +405,7 @@ func checkValidParent(img, parent *image.Image) bool { return false } for i, h := range parent.History { - if !reflect.DeepEqual(h, img.History[i]) { + if !h.Equal(img.History[i]) { return false } } |