Browse code

Fix error paring null JSON - Issue7941

Closes #7941

Treat a null in JSON, when reading the config of a container, as if the
property was never included. W/o this fix the null would be saved in the
property as a string with a value of "null".

Signed-off-by: Doug Davis <dug@us.ibm.com>

Doug Davis authored on 2014/09/29 11:45:03
Showing 2 changed files
... ...
@@ -187,6 +187,12 @@ func (env *Env) Decode(src io.Reader) error {
187 187
 }
188 188
 
189 189
 func (env *Env) SetAuto(k string, v interface{}) {
190
+	// Issue 7941 - if the value in the incoming JSON is null then treat it
191
+	// as if they never specified the property at all.
192
+	if v == nil {
193
+		return
194
+	}
195
+
190 196
 	// FIXME: we fix-convert float values to int, because
191 197
 	// encoding/json decodes integers to float64, but cannot encode them back.
192 198
 	// (See http://golang.org/src/pkg/encoding/json/decode.go#L46)
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"bufio"
5 5
 	"bytes"
6 6
 	"encoding/json"
7
+	"fmt"
7 8
 	"io"
8 9
 	"io/ioutil"
9 10
 	"net"
... ...
@@ -425,6 +426,67 @@ func TestPostJsonVerify(t *testing.T) {
425 425
 	}
426 426
 }
427 427
 
428
+// Issue 7941 - test to make sure a "null" in JSON is just ignored.
429
+// W/o this fix a null in JSON would be parsed into a string var as "null"
430
+func TestPostCreateNull(t *testing.T) {
431
+	eng := NewTestEngine(t)
432
+	daemon := mkDaemonFromEngine(eng, t)
433
+	defer daemon.Nuke()
434
+
435
+	configStr := fmt.Sprintf(`{
436
+		"Hostname":"",
437
+		"Domainname":"",
438
+		"Memory":0,
439
+		"MemorySwap":0,
440
+		"CpuShares":0,
441
+		"Cpuset":null,
442
+		"AttachStdin":true,
443
+		"AttachStdout":true,
444
+		"AttachStderr":true,
445
+		"PortSpecs":null,
446
+		"ExposedPorts":{},
447
+		"Tty":true,
448
+		"OpenStdin":true,
449
+		"StdinOnce":true,
450
+		"Env":[],
451
+		"Cmd":"ls",
452
+		"Image":"%s",
453
+		"Volumes":{},
454
+		"WorkingDir":"",
455
+		"Entrypoint":null,
456
+		"NetworkDisabled":false,
457
+		"OnBuild":null}`, unitTestImageID)
458
+
459
+	req, err := http.NewRequest("POST", "/containers/create", strings.NewReader(configStr))
460
+	if err != nil {
461
+		t.Fatal(err)
462
+	}
463
+
464
+	req.Header.Set("Content-Type", "application/json")
465
+
466
+	r := httptest.NewRecorder()
467
+	if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
468
+		t.Fatal(err)
469
+	}
470
+	assertHttpNotError(r, t)
471
+	if r.Code != http.StatusCreated {
472
+		t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code)
473
+	}
474
+
475
+	var apiRun engine.Env
476
+	if err := apiRun.Decode(r.Body); err != nil {
477
+		t.Fatal(err)
478
+	}
479
+	containerID := apiRun.Get("Id")
480
+
481
+	containerAssertExists(eng, containerID, t)
482
+
483
+	c := daemon.Get(containerID)
484
+	if c.Config.Cpuset != "" {
485
+		t.Fatalf("Cpuset should have been empty - instead its:" + c.Config.Cpuset)
486
+	}
487
+}
488
+
428 489
 func TestPostContainersKill(t *testing.T) {
429 490
 	eng := NewTestEngine(t)
430 491
 	defer mkDaemonFromEngine(eng, t).Nuke()