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>
| ... | ... |
@@ -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() |