func TestUnseal_arg(t *testing.T) { core := vault.TestCore(t) key, _ := vault.TestCoreInit(t, core) ln, addr := http.TestServer(t, core) defer ln.Close() ui := new(cli.MockUi) c := &UnsealCommand{ Meta: Meta{ Ui: ui, }, } args := []string{"-address", addr, hex.EncodeToString(key)} if code := c.Run(args); code != 0 { t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) } sealed, err := core.Sealed() if err != nil { t.Fatalf("err: %s", err) } if sealed { t.Fatal("should not be sealed") } }
func TestStatus(t *testing.T) { ui := new(cli.MockUi) c := &StatusCommand{ Meta: Meta{ Ui: ui, }, } core := vault.TestCore(t) key, _ := vault.TestCoreInit(t, core) ln, addr := http.TestServer(t, core) defer ln.Close() args := []string{"-address", addr} if code := c.Run(args); code != 1 { t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) } if _, err := core.Unseal(key); err != nil { t.Fatalf("err: %s", err) } if code := c.Run(args); code != 0 { t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) } }
func TestSysUnseal_Reset(t *testing.T) { core := vault.TestCore(t) ln, addr := TestServer(t, core) defer ln.Close() thresh := 3 resp := testHttpPut(t, "", addr+"/v1/sys/init", map[string]interface{}{ "secret_shares": 5, "secret_threshold": thresh, }) var actual map[string]interface{} testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) keysRaw, ok := actual["keys"] if !ok { t.Fatalf("no keys: %#v", actual) } for i, key := range keysRaw.([]interface{}) { if i > thresh-2 { break } resp := testHttpPut(t, "", addr+"/v1/sys/unseal", map[string]interface{}{ "key": key.(string), }) var actual map[string]interface{} expected := map[string]interface{}{ "sealed": true, "t": float64(3), "n": float64(5), "progress": float64(i + 1), } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) if !reflect.DeepEqual(actual, expected) { t.Fatalf("\nexpected:\n%#v\nactual:\n%#v\n", expected, actual) } } resp = testHttpPut(t, "", addr+"/v1/sys/unseal", map[string]interface{}{ "reset": true, }) actual = map[string]interface{}{} expected := map[string]interface{}{ "sealed": true, "t": float64(3), "n": float64(5), "progress": float64(0), } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) if !reflect.DeepEqual(actual, expected) { t.Fatalf("\nexpected:\n%#v\nactual:\n%#v\n", expected, actual) } }
func TestSysUnseal_badKey(t *testing.T) { core := vault.TestCore(t) vault.TestCoreInit(t, core) ln, addr := TestServer(t, core) defer ln.Close() resp := testHttpPut(t, "", addr+"/v1/sys/unseal", map[string]interface{}{ "key": "0123", }) testResponseStatus(t, resp, 400) }
func TestSysSealStatus_uninit(t *testing.T) { core := vault.TestCore(t) ln, addr := TestServer(t, core) defer ln.Close() resp, err := http.Get(addr + "/v1/sys/seal-status") if err != nil { t.Fatalf("err: %s", err) } testResponseStatus(t, resp, 400) }
func TestInit_custom(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: meta.Meta{ Ui: ui, }, } core := vault.TestCore(t) ln, addr := http.TestServer(t, core) defer ln.Close() init, err := core.Initialized() if err != nil { t.Fatalf("err: %s", err) } if init { t.Fatal("should not be initialized") } args := []string{ "-address", addr, "-key-shares", "7", "-key-threshold", "3", } if code := c.Run(args); code != 0 { t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) } init, err = core.Initialized() if err != nil { t.Fatalf("err: %s", err) } if !init { t.Fatal("should be initialized") } sealConf, err := core.SealAccess().BarrierConfig() if err != nil { t.Fatalf("err: %s", err) } expected := &vault.SealConfig{ Type: "shamir", SecretShares: 7, SecretThreshold: 3, } if !reflect.DeepEqual(expected, sealConf) { t.Fatalf("expected:\n%#v\ngot:\n%#v\n", expected, sealConf) } }
func TestInit(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ Ui: ui, }, } core := vault.TestCore(t) ln, addr := http.TestServer(t, core) defer ln.Close() init, err := core.Initialized() if err != nil { t.Fatalf("err: %s", err) } if init { t.Fatal("should not be initialized") } args := []string{"-address", addr} if code := c.Run(args); code != 0 { t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) } init, err = core.Initialized() if err != nil { t.Fatalf("err: %s", err) } if !init { t.Fatal("should be initialized") } sealConf, err := core.SealConfig() if err != nil { t.Fatalf("err: %s", err) } expected := &vault.SealConfig{ SecretShares: 5, SecretThreshold: 3, } if !reflect.DeepEqual(expected, sealConf) { t.Fatalf("bad: %#v", sealConf) } }
func TestSysInit_get(t *testing.T) { core := vault.TestCore(t) ln, addr := TestServer(t, core) defer ln.Close() { // Pre-init resp, err := http.Get(addr + "/v1/sys/init") if err != nil { t.Fatalf("err: %s", err) } var actual map[string]interface{} expected := map[string]interface{}{ "initialized": false, } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: %#v", actual) } } vault.TestCoreInit(t, core) { // Post-init resp, err := http.Get(addr + "/v1/sys/init") if err != nil { t.Fatalf("err: %s", err) } var actual map[string]interface{} expected := map[string]interface{}{ "initialized": true, } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: %#v", actual) } } }
func TestSysInit_put(t *testing.T) { core := vault.TestCore(t) ln, addr := TestServer(t, core) defer ln.Close() resp := testHttpPut(t, "", addr+"/v1/sys/init", map[string]interface{}{ "secret_shares": 5, "secret_threshold": 3, }) var actual map[string]interface{} testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) keysRaw, ok := actual["keys"] if !ok { t.Fatalf("no keys: %#v", actual) } if _, ok := actual["root_token"]; !ok { t.Fatal("no root token") } for _, key := range keysRaw.([]interface{}) { keySlice, err := hex.DecodeString(key.(string)) if err != nil { t.Fatalf("bad: %s", err) } if _, err := core.Unseal(keySlice); err != nil { t.Fatalf("bad: %s", err) } } seal, err := core.Sealed() if err != nil { t.Fatalf("err: %s", err) } if seal { t.Fatal("should not be sealed") } }
func TestInit_Check(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: meta.Meta{ Ui: ui, }, } core := vault.TestCore(t) ln, addr := http.TestServer(t, core) defer ln.Close() // Should return 2, not initialized args := []string{"-address", addr, "-check"} if code := c.Run(args); code != 2 { t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) } // Now initialize it args = []string{"-address", addr} if code := c.Run(args); code != 0 { t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) } // Should return 0, initialized args = []string{"-address", addr, "-check"} if code := c.Run(args); code != 0 { t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) } init, err := core.Initialized() if err != nil { t.Fatalf("err: %s", err) } if !init { t.Fatal("should be initialized") } }
func TestSysSealStatus(t *testing.T) { core := vault.TestCore(t) vault.TestCoreInit(t, core) ln, addr := TestServer(t, core) defer ln.Close() resp, err := http.Get(addr + "/v1/sys/seal-status") if err != nil { t.Fatalf("err: %s", err) } var actual map[string]interface{} expected := map[string]interface{}{ "sealed": true, "t": json.Number("1"), "n": json.Number("1"), "progress": json.Number("0"), } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) if actual["version"] == nil { t.Fatalf("expected version information") } expected["version"] = actual["version"] if actual["cluster_name"] == nil { delete(expected, "cluster_name") } else { expected["cluster_name"] = actual["cluster_name"] } if actual["cluster_id"] == nil { delete(expected, "cluster_id") } else { expected["cluster_id"] = actual["cluster_id"] } if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: expected: %#v\nactual: %#v", expected, actual) } }
func TestSysUnseal(t *testing.T) { core := vault.TestCore(t) key, _ := vault.TestCoreInit(t, core) ln, addr := TestServer(t, core) defer ln.Close() resp := testHttpPut(t, "", addr+"/v1/sys/unseal", map[string]interface{}{ "key": hex.EncodeToString(key), }) var actual map[string]interface{} expected := map[string]interface{}{ "sealed": false, "t": float64(1), "n": float64(1), "progress": float64(0), } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: %#v", actual) } }
func TestSysUnseal(t *testing.T) { core := vault.TestCore(t) key, _ := vault.TestCoreInit(t, core) ln, addr := TestServer(t, core) defer ln.Close() resp := testHttpPut(t, "", addr+"/v1/sys/unseal", map[string]interface{}{ "key": hex.EncodeToString(key), }) var actual map[string]interface{} expected := map[string]interface{}{ "sealed": false, "t": json.Number("1"), "n": json.Number("1"), "progress": json.Number("0"), } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) if actual["version"] == nil { t.Fatalf("expected version information") } expected["version"] = actual["version"] if actual["cluster_name"] == nil { delete(expected, "cluster_name") } else { expected["cluster_name"] = actual["cluster_name"] } if actual["cluster_id"] == nil { delete(expected, "cluster_id") } else { expected["cluster_id"] = actual["cluster_id"] } if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: expected: %#v\nactual: %#v", expected, actual) } }
func TestSysSealStatus(t *testing.T) { core := vault.TestCore(t) vault.TestCoreInit(t, core) ln, addr := TestServer(t, core) defer ln.Close() resp, err := http.Get(addr + "/v1/sys/seal-status") if err != nil { t.Fatalf("err: %s", err) } var actual map[string]interface{} expected := map[string]interface{}{ "sealed": true, "t": float64(1), "n": float64(1), "progress": float64(0), } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: %#v", actual) } }
func TestInit_custom(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: meta.Meta{ Ui: ui, }, } core := vault.TestCore(t) ln, addr := http.TestServer(t, core) defer ln.Close() init, err := core.Initialized() if err != nil { t.Fatalf("err: %s", err) } if init { t.Fatal("should not be initialized") } args := []string{ "-address", addr, "-key-shares", "7", "-key-threshold", "3", } if code := c.Run(args); code != 0 { t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) } init, err = core.Initialized() if err != nil { t.Fatalf("err: %s", err) } if !init { t.Fatal("should be initialized") } sealConf, err := core.SealAccess().BarrierConfig() if err != nil { t.Fatalf("err: %s", err) } expected := &vault.SealConfig{ Type: "shamir", SecretShares: 7, SecretThreshold: 3, } if !reflect.DeepEqual(expected, sealConf) { t.Fatalf("expected:\n%#v\ngot:\n%#v\n", expected, sealConf) } re, err := regexp.Compile("\\s+Initial Root Token:\\s+(.*)") if err != nil { t.Fatalf("Error compiling regex: %s", err) } matches := re.FindAllStringSubmatch(ui.OutputWriter.String(), -1) if len(matches) != 1 { t.Fatalf("Unexpected number of tokens found, got %d", len(matches)) } rootToken := matches[0][1] client, err := c.Client() if err != nil { t.Fatalf("Error fetching client: %v", err) } client.SetToken(rootToken) re, err = regexp.Compile("\\s*Unseal Key \\d+: (.*)") if err != nil { t.Fatalf("Error compiling regex: %s", err) } matches = re.FindAllStringSubmatch(ui.OutputWriter.String(), -1) if len(matches) != 7 { t.Fatalf("Unexpected number of keys returned, got %d, matches was \n\n%#v\n\n, input was \n\n%s\n\n", len(matches), matches, ui.OutputWriter.String()) } var unsealed bool for i := 0; i < 3; i++ { decodedKey, err := base64.StdEncoding.DecodeString(strings.TrimSpace(matches[i][1])) if err != nil { t.Fatalf("err decoding key %v: %v", matches[i][1], err) } unsealed, err = core.Unseal(decodedKey) if err != nil { t.Fatalf("err during unseal: %v; key was %v", err, matches[i][1]) } } if !unsealed { t.Fatal("expected to be unsealed") } tokenInfo, err := client.Auth().Token().LookupSelf() if err != nil { t.Fatalf("Error looking up root token info: %v", err) } if tokenInfo.Data["policies"].([]interface{})[0].(string) != "root" { t.Fatalf("expected root policy") } }
func TestInit_PGP(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: meta.Meta{ Ui: ui, }, } core := vault.TestCore(t) ln, addr := http.TestServer(t, core) defer ln.Close() init, err := core.Initialized() if err != nil { t.Fatalf("err: %s", err) } if init { t.Fatal("should not be initialized") } tempDir, pubFiles, err := getPubKeyFiles(t) if err != nil { t.Fatal(err) } defer os.RemoveAll(tempDir) args := []string{ "-address", addr, "-key-shares", "2", "-pgp-keys", pubFiles[0] + ",@" + pubFiles[1] + "," + pubFiles[2], "-key-threshold", "2", "-root-token-pgp-key", pubFiles[0], } // This should fail, as key-shares does not match pgp-keys size if code := c.Run(args); code == 0 { t.Fatalf("bad (command should have failed): %d\n\n%s", code, ui.ErrorWriter.String()) } args = []string{ "-address", addr, "-key-shares", "4", "-pgp-keys", pubFiles[0] + ",@" + pubFiles[1] + "," + pubFiles[2] + "," + pubFiles[3], "-key-threshold", "2", "-root-token-pgp-key", pubFiles[0], } ui.OutputWriter.Reset() if code := c.Run(args); code != 0 { t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) } init, err = core.Initialized() if err != nil { t.Fatalf("err: %s", err) } if !init { t.Fatal("should be initialized") } sealConf, err := core.SealAccess().BarrierConfig() if err != nil { t.Fatalf("err: %s", err) } pgpKeys := []string{} for _, pubFile := range pubFiles { pub, err := pgpkeys.ReadPGPFile(pubFile) if err != nil { t.Fatalf("bad: %v", err) } pgpKeys = append(pgpKeys, pub) } expected := &vault.SealConfig{ Type: "shamir", SecretShares: 4, SecretThreshold: 2, PGPKeys: pgpKeys, } if !reflect.DeepEqual(expected, sealConf) { t.Fatalf("expected:\n%#v\ngot:\n%#v\n", expected, sealConf) } re, err := regexp.Compile("\\s+Initial Root Token:\\s+(.*)") if err != nil { t.Fatalf("Error compiling regex: %s", err) } matches := re.FindAllStringSubmatch(ui.OutputWriter.String(), -1) if len(matches) != 1 { t.Fatalf("Unexpected number of tokens found, got %d", len(matches)) } encRootToken := matches[0][1] privKeyBytes, err := base64.StdEncoding.DecodeString(pgpkeys.TestPrivKey1) if err != nil { t.Fatalf("error decoding private key: %v", err) } ptBuf := bytes.NewBuffer(nil) entity, err := openpgp.ReadEntity(packet.NewReader(bytes.NewBuffer(privKeyBytes))) if err != nil { t.Fatalf("Error parsing private key: %s", err) } var rootBytes []byte rootBytes, err = base64.StdEncoding.DecodeString(encRootToken) if err != nil { t.Fatalf("Error decoding root token: %s", err) } entityList := &openpgp.EntityList{entity} md, err := openpgp.ReadMessage(bytes.NewBuffer(rootBytes), entityList, nil, nil) if err != nil { t.Fatalf("Error decrypting root token: %s", err) } ptBuf.ReadFrom(md.UnverifiedBody) rootToken := ptBuf.String() parseDecryptAndTestUnsealKeys(t, ui.OutputWriter.String(), rootToken, false, nil, nil, core) client, err := c.Client() if err != nil { t.Fatalf("Error fetching client: %v", err) } client.SetToken(rootToken) tokenInfo, err := client.Auth().Token().LookupSelf() if err != nil { t.Fatalf("Error looking up root token info: %v", err) } if tokenInfo.Data["policies"].([]interface{})[0].(string) != "root" { t.Fatalf("expected root policy") } }
func TestInit_PGP(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ Ui: ui, }, } core := vault.TestCore(t) ln, addr := http.TestServer(t, core) defer ln.Close() init, err := core.Initialized() if err != nil { t.Fatalf("err: %s", err) } if init { t.Fatal("should not be initialized") } tempDir, pubFiles, err := getPubKeyFiles(t) if err != nil { t.Fatal(err) } defer os.RemoveAll(tempDir) args := []string{ "-address", addr, "-key-shares", "2", "-pgp-keys", pubFiles[0] + ",@" + pubFiles[1] + "," + pubFiles[2], "-key-threshold", "2", } // This should fail, as key-shares does not match pgp-keys size if code := c.Run(args); code == 0 { t.Fatalf("bad (command should have failed): %d\n\n%s", code, ui.ErrorWriter.String()) } args = []string{ "-address", addr, "-key-shares", "3", "-pgp-keys", pubFiles[0] + ",@" + pubFiles[1] + "," + pubFiles[2], "-key-threshold", "2", } ui.OutputWriter.Reset() if code := c.Run(args); code != 0 { t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) } init, err = core.Initialized() if err != nil { t.Fatalf("err: %s", err) } if !init { t.Fatal("should be initialized") } sealConf, err := core.SealConfig() if err != nil { t.Fatalf("err: %s", err) } pgpKeys := []string{} for _, pubFile := range pubFiles { pub, err := pgpkeys.ReadPGPFile(pubFile) if err != nil { t.Fatalf("bad: %v", err) } pgpKeys = append(pgpKeys, pub) } expected := &vault.SealConfig{ SecretShares: 3, SecretThreshold: 2, PGPKeys: pgpKeys, } if !reflect.DeepEqual(expected, sealConf) { t.Fatalf("bad:\nexpected: %#v\ngot: %#v", expected, sealConf) } re, err := regexp.Compile("\\s+Initial Root Token:\\s+(.*)") if err != nil { t.Fatalf("Error compiling regex: %s", err) } matches := re.FindAllStringSubmatch(ui.OutputWriter.String(), -1) if len(matches) != 1 { t.Fatalf("Unexpected number of tokens found, got %d", len(matches)) } rootToken := matches[0][1] parseDecryptAndTestUnsealKeys(t, ui.OutputWriter.String(), rootToken, false, nil, core) }
func TestSysHealth_get(t *testing.T) { core := vault.TestCore(t) ln, addr := TestServer(t, core) defer ln.Close() resp, err := http.Get(addr + "/v1/sys/health") if err != nil { t.Fatalf("err: %s", err) } var actual map[string]interface{} expected := map[string]interface{}{ "initialized": false, "sealed": true, "standby": true, } testResponseStatus(t, resp, 501) testResponseBody(t, resp, &actual) expected["server_time_utc"] = actual["server_time_utc"] expected["version"] = actual["version"] if actual["cluster_name"] == nil { delete(expected, "cluster_name") } else { expected["cluster_name"] = actual["cluster_name"] } if actual["cluster_id"] == nil { delete(expected, "cluster_id") } else { expected["cluster_id"] = actual["cluster_id"] } if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: expected:%#v\nactual:%#v", expected, actual) } key, _ := vault.TestCoreInit(t, core) resp, err = http.Get(addr + "/v1/sys/health") if err != nil { t.Fatalf("err: %s", err) } actual = map[string]interface{}{} expected = map[string]interface{}{ "initialized": true, "sealed": true, "standby": true, } testResponseStatus(t, resp, 503) testResponseBody(t, resp, &actual) expected["server_time_utc"] = actual["server_time_utc"] expected["version"] = actual["version"] if actual["cluster_name"] == nil { delete(expected, "cluster_name") } else { expected["cluster_name"] = actual["cluster_name"] } if actual["cluster_id"] == nil { delete(expected, "cluster_id") } else { expected["cluster_id"] = actual["cluster_id"] } if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: expected:%#v\nactual:%#v", expected, actual) } if _, err := vault.TestCoreUnseal(core, vault.TestKeyCopy(key)); err != nil { t.Fatalf("unseal err: %s", err) } resp, err = http.Get(addr + "/v1/sys/health") if err != nil { t.Fatalf("err: %s", err) } actual = map[string]interface{}{} expected = map[string]interface{}{ "initialized": true, "sealed": false, "standby": false, } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) expected["server_time_utc"] = actual["server_time_utc"] expected["version"] = actual["version"] if actual["cluster_name"] == nil { delete(expected, "cluster_name") } else { expected["cluster_name"] = actual["cluster_name"] } if actual["cluster_id"] == nil { delete(expected, "cluster_id") } else { expected["cluster_id"] = actual["cluster_id"] } if !reflect.DeepEqual(actual, expected) { t.Fatalf("bad: expected:%#v\nactual:%#v", expected, actual) } }
func TestSysUnseal_Reset(t *testing.T) { core := vault.TestCore(t) ln, addr := TestServer(t, core) defer ln.Close() thresh := 3 resp := testHttpPut(t, "", addr+"/v1/sys/init", map[string]interface{}{ "secret_shares": 5, "secret_threshold": thresh, }) var actual map[string]interface{} testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) keysRaw, ok := actual["keys"] if !ok { t.Fatalf("no keys: %#v", actual) } for i, key := range keysRaw.([]interface{}) { if i > thresh-2 { break } resp := testHttpPut(t, "", addr+"/v1/sys/unseal", map[string]interface{}{ "key": key.(string), }) var actual map[string]interface{} expected := map[string]interface{}{ "sealed": true, "t": json.Number("3"), "n": json.Number("5"), "progress": json.Number(strconv.Itoa(i + 1)), } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) if actual["version"] == nil { t.Fatalf("expected version information") } expected["version"] = actual["version"] if actual["cluster_name"] == nil { delete(expected, "cluster_name") } else { expected["cluster_name"] = actual["cluster_name"] } if actual["cluster_id"] == nil { delete(expected, "cluster_id") } else { expected["cluster_id"] = actual["cluster_id"] } if !reflect.DeepEqual(actual, expected) { t.Fatalf("\nexpected:\n%#v\nactual:\n%#v\n", expected, actual) } } resp = testHttpPut(t, "", addr+"/v1/sys/unseal", map[string]interface{}{ "reset": true, }) actual = map[string]interface{}{} expected := map[string]interface{}{ "sealed": true, "t": json.Number("3"), "n": json.Number("5"), "progress": json.Number("0"), } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) if actual["version"] == nil { t.Fatalf("expected version information") } expected["version"] = actual["version"] if actual["cluster_name"] == nil { delete(expected, "cluster_name") } else { expected["cluster_name"] = actual["cluster_name"] } if actual["cluster_id"] == nil { delete(expected, "cluster_id") } else { expected["cluster_id"] = actual["cluster_id"] } if !reflect.DeepEqual(actual, expected) { t.Fatalf("\nexpected:\n%#v\nactual:\n%#v\n", expected, actual) } }