From 0aa250bd60e472dadfd8e9e1f90465e041b03983 Mon Sep 17 00:00:00 2001 From: Qiang Huang Date: Sat, 21 Mar 2015 10:16:18 +0800 Subject: [PATCH] fix decode data loss when using int64 in json The problem is when I create container though REST api, set memory limit in hostConfig, the memory limit didn't work. Because when we DecodeEnv, we got hostConfig part of Env like this: {"Binds":["/:/tmp"],"CpuShares":512,"CpusetCpus":"0,1","Devices":[],"Memory":1.6777216e+07,"MemorySwap":0} And we cannot unmarshal number 1.6777216e+07 into Go value of type int64, so we got 0. We can fix this by setting Decoder as UseNumber(). Signed-off-by: Qiang Huang --- engine/env.go | 5 ++++- engine/env_test.go | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/engine/env.go b/engine/env.go index a671f13c6b..c6c673271e 100644 --- a/engine/env.go +++ b/engine/env.go @@ -189,7 +189,10 @@ func (decoder *Decoder) Decode() (*Env, error) { // is returned. func (env *Env) Decode(src io.Reader) error { m := make(map[string]interface{}) - if err := json.NewDecoder(src).Decode(&m); err != nil { + d := json.NewDecoder(src) + // We need this or we'll lose data when we decode int64 in json + d.UseNumber() + if err := d.Decode(&m); err != nil { return err } for k, v := range m { diff --git a/engine/env_test.go b/engine/env_test.go index 2ed99d0fea..dd282fef01 100644 --- a/engine/env_test.go +++ b/engine/env_test.go @@ -78,6 +78,26 @@ func TestSetenv(t *testing.T) { } } +func TestDecodeEnv(t *testing.T) { + job := mkJob(t, "dummy") + type tmp struct { + Id1 int64 + Id2 int64 + } + body := []byte("{\"tags\":{\"Id1\":123, \"Id2\":1234567}}") + if err := job.DecodeEnv(bytes.NewBuffer(body)); err != nil { + t.Fatalf("DecodeEnv failed: %v", err) + } + mytag := tmp{} + if val := job.GetenvJson("tags", &mytag); val != nil { + t.Fatalf("GetenvJson returns incorrect value: %s", val) + } + + if mytag.Id1 != 123 || mytag.Id2 != 1234567 { + t.Fatal("Get wrong values set by job.DecodeEnv") + } +} + func TestSetenvBool(t *testing.T) { job := mkJob(t, "dummy") job.SetenvBool("foo", true)