github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/cmd/roachtest/status_server.go (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package main 12 13 import ( 14 "context" 15 "fmt" 16 "io/ioutil" 17 "net/http" 18 "time" 19 20 "github.com/cockroachdb/cockroach/pkg/roachpb" 21 "github.com/cockroachdb/cockroach/pkg/server/serverpb" 22 "github.com/cockroachdb/cockroach/pkg/util/httputil" 23 "github.com/cockroachdb/cockroach/pkg/util/retry" 24 ) 25 26 func runStatusServer(ctx context.Context, t *test, c *cluster) { 27 c.Put(ctx, cockroach, "./cockroach") 28 c.Start(ctx, t) 29 30 // Get the ids for each node. 31 idMap := make(map[int]roachpb.NodeID) 32 urlMap := make(map[int]string) 33 for i, addr := range c.ExternalAdminUIAddr(ctx, c.All()) { 34 var details serverpb.DetailsResponse 35 url := `http://` + addr + `/_status/details/local` 36 // Use a retry-loop when populating the maps because we might be trying to 37 // talk to the servers before they are responding to status requests 38 // (resulting in 404's). 39 if err := retry.ForDuration(10*time.Second, func() error { 40 return httputil.GetJSON(http.Client{}, url, &details) 41 }); err != nil { 42 t.Fatal(err) 43 } 44 idMap[i+1] = details.NodeID 45 urlMap[i+1] = `http://` + addr 46 } 47 48 // The status endpoints below may take a while to produce their answer, maybe more 49 // than the 3 second timeout of the default http client. 50 httpClient := httputil.NewClientWithTimeout(15 * time.Second) 51 52 // get performs an HTTP GET to the specified path for a specific node. 53 get := func(base, rel string) []byte { 54 url := base + rel 55 resp, err := httpClient.Get(context.TODO(), url) 56 if err != nil { 57 t.Fatalf("could not GET %s - %s", url, err) 58 } 59 defer resp.Body.Close() 60 body, err := ioutil.ReadAll(resp.Body) 61 if err != nil { 62 t.Fatalf("could not read body for %s - %s", url, err) 63 } 64 if resp.StatusCode != http.StatusOK { 65 t.Fatalf("could not GET %s - statuscode: %d - body: %s", url, resp.StatusCode, body) 66 } 67 t.l.Printf("OK response from %s\n", url) 68 return body 69 } 70 71 // checkNode checks all the endpoints of the status server hosted by node and 72 // requests info for the node with otherNodeID. That node could be the same 73 // other node, the same node or "local". 74 checkNode := func(url string, nodeID, otherNodeID, expectedNodeID roachpb.NodeID) { 75 urlIDs := []string{otherNodeID.String()} 76 if nodeID == otherNodeID { 77 urlIDs = append(urlIDs, "local") 78 } 79 var details serverpb.DetailsResponse 80 for _, urlID := range urlIDs { 81 if err := httputil.GetJSON(http.Client{}, url+`/_status/details/`+urlID, &details); err != nil { 82 t.Fatalf("unable to parse details - %s", err) 83 } 84 if details.NodeID != expectedNodeID { 85 t.Fatalf("%d calling %s: node ids don't match - expected %d, actual %d", 86 nodeID, urlID, expectedNodeID, details.NodeID) 87 } 88 89 get(url, fmt.Sprintf("/_status/gossip/%s", urlID)) 90 get(url, fmt.Sprintf("/_status/nodes/%s", urlID)) 91 get(url, fmt.Sprintf("/_status/logfiles/%s", urlID)) 92 get(url, fmt.Sprintf("/_status/logs/%s", urlID)) 93 get(url, fmt.Sprintf("/_status/stacks/%s", urlID)) 94 } 95 96 get(url, "/_status/vars") 97 } 98 99 // Check local response for the every node. 100 for i := 1; i <= c.spec.NodeCount; i++ { 101 id := idMap[i] 102 checkNode(urlMap[i], id, id, id) 103 get(urlMap[i], "/_status/nodes") 104 } 105 106 // Proxy from the first node to the last node. 107 firstNode := 1 108 lastNode := c.spec.NodeCount 109 firstID := idMap[firstNode] 110 lastID := idMap[lastNode] 111 checkNode(urlMap[firstNode], firstID, lastID, lastID) 112 113 // And from the last node to the first node. 114 checkNode(urlMap[lastNode], lastID, firstID, firstID) 115 116 // And from the last node to the last node. 117 checkNode(urlMap[lastNode], lastID, lastID, lastID) 118 }