From c9207bc0aa57745876a3422d2cbc290be7c53da8 Mon Sep 17 00:00:00 2001 From: Antonio Murdaca Date: Sun, 26 Jul 2015 15:00:53 +0200 Subject: [PATCH] Format times in inspect command with a template as RFC3339Nano In 1.6.2 we were decoding inspect API response into interface{}. time.Time fields were JSON encoded as RFC3339Nano in the response and when decoded into interface{} they were just strings so the inspect template treated them as just strings. From 1.7 we are decoding into types.ContainerJSON and when the template gets executed it now gets a time.Time and it's formatted as 2015-07-22 05:02:38.091530369 +0000 UTC. This patch brings back the old behavior by typing time.Time fields as string so they gets formatted as they were encoded in JSON -- RCF3339Nano Signed-off-by: Antonio Murdaca --- api/types/types.go | 8 +++---- daemon/inspect.go | 7 +++--- graph/service.go | 3 ++- integration-cli/docker_cli_inspect_test.go | 26 ++++++++++++++++++++++ 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/api/types/types.go b/api/types/types.go index 0e7078bc72..b02c88bb66 100644 --- a/api/types/types.go +++ b/api/types/types.go @@ -86,7 +86,7 @@ type ImageInspect struct { Id string Parent string Comment string - Created time.Time + Created string Container string ContainerConfig *runconfig.Config DockerVersion string @@ -215,14 +215,14 @@ type ContainerState struct { Pid int ExitCode int Error string - StartedAt time.Time - FinishedAt time.Time + StartedAt string + FinishedAt string } // GET "/containers/{name:.*}/json" type ContainerJSONBase struct { Id string - Created time.Time + Created string Path string Args []string State *ContainerState diff --git a/daemon/inspect.go b/daemon/inspect.go index 1fb73c43ae..d38471a04a 100644 --- a/daemon/inspect.go +++ b/daemon/inspect.go @@ -2,6 +2,7 @@ package daemon import ( "fmt" + "time" "github.com/docker/docker/api/types" ) @@ -91,13 +92,13 @@ func (daemon *Daemon) getInspectData(container *Container) (*types.ContainerJSON Pid: container.State.Pid, ExitCode: container.State.ExitCode, Error: container.State.Error, - StartedAt: container.State.StartedAt, - FinishedAt: container.State.FinishedAt, + StartedAt: container.State.StartedAt.Format(time.RFC3339Nano), + FinishedAt: container.State.FinishedAt.Format(time.RFC3339Nano), } contJSONBase := &types.ContainerJSONBase{ Id: container.ID, - Created: container.Created, + Created: container.Created.Format(time.RFC3339Nano), Path: container.Path, Args: container.Args, State: containerState, diff --git a/graph/service.go b/graph/service.go index 4a8c3d3b8f..a7b9b49359 100644 --- a/graph/service.go +++ b/graph/service.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "runtime" + "time" "github.com/Sirupsen/logrus" "github.com/docker/docker/api/types" @@ -34,7 +35,7 @@ func (s *TagStore) Lookup(name string) (*types.ImageInspect, error) { Id: image.ID, Parent: image.Parent, Comment: image.Comment, - Created: image.Created, + Created: image.Created.Format(time.RFC3339Nano), Container: image.Container, ContainerConfig: &image.ContainerConfig, DockerVersion: image.DockerVersion, diff --git a/integration-cli/docker_cli_inspect_test.go b/integration-cli/docker_cli_inspect_test.go index f90419eee8..3e42d0c373 100644 --- a/integration-cli/docker_cli_inspect_test.go +++ b/integration-cli/docker_cli_inspect_test.go @@ -5,6 +5,7 @@ import ( "os/exec" "strconv" "strings" + "time" "github.com/docker/docker/api/types" "github.com/go-check/check" @@ -260,3 +261,28 @@ func (s *DockerSuite) TestInspectBindMountPoint(c *check.C) { c.Fatalf("Expected rw to be false") } } + +// #14947 +func (s *DockerSuite) TestInspectTimesAsRFC3339Nano(c *check.C) { + out, _ := dockerCmd(c, "run", "-d", "busybox", "true") + id := strings.TrimSpace(out) + startedAt, err := inspectField(id, "State.StartedAt") + c.Assert(err, check.IsNil) + finishedAt, err := inspectField(id, "State.FinishedAt") + c.Assert(err, check.IsNil) + created, err := inspectField(id, "Created") + c.Assert(err, check.IsNil) + + _, err = time.Parse(time.RFC3339Nano, startedAt) + c.Assert(err, check.IsNil) + _, err = time.Parse(time.RFC3339Nano, finishedAt) + c.Assert(err, check.IsNil) + _, err = time.Parse(time.RFC3339Nano, created) + c.Assert(err, check.IsNil) + + created, err = inspectField("busybox", "Created") + c.Assert(err, check.IsNil) + + _, err = time.Parse(time.RFC3339Nano, created) + c.Assert(err, check.IsNil) +}