diff --git a/api/client/commands.go b/api/client/commands.go index a682befa70..784f10024e 100644 --- a/api/client/commands.go +++ b/api/client/commands.go @@ -579,6 +579,14 @@ func (cli *DockerCli) CmdInfo(args ...string) error { if remoteInfo.Exists("NGoroutines") { fmt.Fprintf(cli.out, "Goroutines: %d\n", remoteInfo.GetInt("NGoroutines")) } + if remoteInfo.Exists("SystemTime") { + t, err := remoteInfo.GetTime("SystemTime") + if err != nil { + log.Errorf("Error reading system time: %v", err) + } else { + fmt.Fprintf(cli.out, "System Time: %s\n", t.Format(time.UnixDate)) + } + } if remoteInfo.Exists("NEventsListener") { fmt.Fprintf(cli.out, "EventsListeners: %d\n", remoteInfo.GetInt("NEventsListener")) } diff --git a/daemon/info.go b/daemon/info.go index 67ac048acf..965c370328 100644 --- a/daemon/info.go +++ b/daemon/info.go @@ -3,6 +3,7 @@ package daemon import ( "os" "runtime" + "time" log "github.com/Sirupsen/logrus" "github.com/docker/docker/autogen/dockerversion" @@ -76,6 +77,7 @@ func (daemon *Daemon) CmdInfo(job *engine.Job) engine.Status { v.SetBool("Debug", os.Getenv("DEBUG") != "") v.SetInt("NFd", utils.GetTotalUsedFds()) v.SetInt("NGoroutines", runtime.NumGoroutine()) + v.Set("SystemTime", time.Now().Format(time.RFC3339Nano)) v.Set("ExecutionDriver", daemon.ExecutionDriver().Name()) v.SetInt("NEventsListener", env.GetInt("count")) v.Set("KernelVersion", kernelVersion) diff --git a/docs/sources/reference/api/docker_remote_api.md b/docs/sources/reference/api/docker_remote_api.md index 7cfdb468bd..051b90ce97 100644 --- a/docs/sources/reference/api/docker_remote_api.md +++ b/docs/sources/reference/api/docker_remote_api.md @@ -57,10 +57,10 @@ This endpoint now returns `Os`, `Arch` and `KernelVersion`. **New!** You can set ulimit settings to be used within the container. -`Get /info` +`GET /info` **New!** -Add return value `HttpProxy`,`HttpsProxy` and `NoProxy` to this entrypoint. +This endpoint now returns `SystemTime`, `HttpProxy`,`HttpsProxy` and `NoProxy`. ## v1.17 diff --git a/docs/sources/reference/api/docker_remote_api_v1.18.md b/docs/sources/reference/api/docker_remote_api_v1.18.md index 76e0e400d6..46351ed85c 100644 --- a/docs/sources/reference/api/docker_remote_api_v1.18.md +++ b/docs/sources/reference/api/docker_remote_api_v1.18.md @@ -1452,6 +1452,7 @@ Display system-wide information "Debug":false, "NFd": 11, "NGoroutines":21, + "SystemTime": "2015-03-10T11:11:23.730591467-07:00" "NEventsListener":0, "InitPath":"/usr/bin/docker", "InitSha1":"", diff --git a/docs/sources/reference/commandline/cli.md b/docs/sources/reference/commandline/cli.md index 4987764bfb..0e4f805f83 100644 --- a/docs/sources/reference/commandline/cli.md +++ b/docs/sources/reference/commandline/cli.md @@ -1248,6 +1248,7 @@ For example: Debug mode (client): true Fds: 10 Goroutines: 9 + System Time: Tue Mar 10 18:38:57 UTC 2015 EventsListeners: 0 Init Path: /usr/bin/docker Docker Root Dir: /var/lib/docker diff --git a/engine/env.go b/engine/env.go index f370e95ed0..a671f13c6b 100644 --- a/engine/env.go +++ b/engine/env.go @@ -7,6 +7,7 @@ import ( "io" "strconv" "strings" + "time" "github.com/docker/docker/utils" ) @@ -69,6 +70,15 @@ func (env *Env) SetBool(key string, value bool) { } } +func (env *Env) GetTime(key string) (time.Time, error) { + t, err := time.Parse(time.RFC3339Nano, env.Get(key)) + return t, err +} + +func (env *Env) SetTime(key string, t time.Time) { + env.Set(key, t.Format(time.RFC3339Nano)) +} + func (env *Env) GetInt(key string) int { return int(env.GetInt64(key)) } diff --git a/engine/env_test.go b/engine/env_test.go index b0caca9cbd..2ed99d0fea 100644 --- a/engine/env_test.go +++ b/engine/env_test.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "testing" + "time" "github.com/docker/docker/pkg/testutils" ) @@ -94,6 +95,27 @@ func TestSetenvBool(t *testing.T) { } } +func TestSetenvTime(t *testing.T) { + job := mkJob(t, "dummy") + + now := time.Now() + job.SetenvTime("foo", now) + if val, err := job.GetenvTime("foo"); err != nil { + t.Fatalf("GetenvTime failed to parse: %v", err) + } else { + nowStr := now.Format(time.RFC3339) + valStr := val.Format(time.RFC3339) + if nowStr != valStr { + t.Fatalf("GetenvTime returns incorrect value: %s, Expected: %s", valStr, nowStr) + } + } + + job.Setenv("bar", "Obviously I'm not a date") + if val, err := job.GetenvTime("bar"); err == nil { + t.Fatalf("GetenvTime was supposed to fail, instead returned: %s", val) + } +} + func TestSetenvInt(t *testing.T) { job := mkJob(t, "dummy") diff --git a/engine/job.go b/engine/job.go index 6c11b13446..4b2befb425 100644 --- a/engine/job.go +++ b/engine/job.go @@ -145,6 +145,14 @@ func (job *Job) SetenvBool(key string, value bool) { job.env.SetBool(key, value) } +func (job *Job) GetenvTime(key string) (value time.Time, err error) { + return job.env.GetTime(key) +} + +func (job *Job) SetenvTime(key string, value time.Time) { + job.env.SetTime(key, value) +} + func (job *Job) GetenvSubEnv(key string) *Env { return job.env.GetSubEnv(key) }