Skip to content

Commit

Permalink
Merge pull request #97 from github/hugodorea/add-cluster-allocation-e…
Browse files Browse the repository at this point in the history
…xplain

adds ClusterAllocationExplain method
  • Loading branch information
hugodorea authored Aug 11, 2022
2 parents 924bd8a + 7bd3420 commit 102f5bf
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 1 deletion.
39 changes: 39 additions & 0 deletions es.go
Original file line number Diff line number Diff line change
Expand Up @@ -1567,3 +1567,42 @@ func (c *Client) GetNodesHotThreads(nodesIDs []string) (string, error) {

return string(body), nil
}

// ClusterAllocationExplainRequest represents request data that can be sent to
// `_cluster/allocation/explain` calls
type ClusterAllocationExplainRequest struct {
// Specifies the node ID or the name of the node to only explain a shard that
// is currently located on the specified node.
CurrentNode string `json:"current_node,omitempty"`

// Specifies the name of the index that you would like an explanation for.
Index string `json:"index,omitempty"`

// If true, returns explanation for the primary shard for the given shard ID.
Primary bool `json:"primary,omitempty"`

// Specifies the ID of the shard that you would like an explanation for.
Shard string `json:"shard,omitempty"`
}

// ClusterAllocationExplain provides an explanation for a shard’s current allocation.
// For more info, please check https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-allocation-explain.html
func (c *Client) ClusterAllocationExplain(req *ClusterAllocationExplainRequest, prettyOutput bool) (string, error) {
var urlBuilder strings.Builder
urlBuilder.WriteString("_cluster/allocation/explain")
if prettyOutput {
urlBuilder.WriteString("?pretty")
}

agent := c.buildGetRequest(urlBuilder.String())
if req != nil {
agent.Set("Content-Type", "application/json").Send(req)
}

body, err := handleErrWithBytes(agent)
if err != nil {
return "", err
}

return string(body), nil
}
84 changes: 83 additions & 1 deletion es_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
type ServerSetup struct {
Method, Path, Body, Response string
HTTPStatus int
extraChecksFn func(t *testing.T, r *http.Request)
}

func buildTestServer(t *testing.T, setups []*ServerSetup, tls bool) *httptest.Server {
Expand All @@ -29,10 +30,14 @@ func buildTestServer(t *testing.T, setups []*ServerSetup, tls bool) *httptest.Se

matched := false
for _, setup := range setups {
if setup.extraChecksFn != nil {
setup.extraChecksFn(t, r)
}
// Extra piece of debug incase there's a typo in your test's response, like a rogue space somewhere
if r.Method == setup.Method && r.URL.EscapedPath() == setup.Path && requestBody != setup.Body {
t.Errorf("request body not matching: %s != %s", requestBody, setup.Body)
t.Fatalf("request body not matching: %s != %s", requestBody, setup.Body)
}

if r.Method == setup.Method && r.URL.EscapedPath() == setup.Path && requestBody == setup.Body {
matched = true
if setup.HTTPStatus == 0 {
Expand Down Expand Up @@ -2096,3 +2101,80 @@ func TestGetNodesHotThreads(t *testing.T) {
t.Errorf("Unexpected response. got %v want %v", hotThreads, testSetup.Response)
}
}

func TestClusterAllocationExplain(t *testing.T) {
tests := []struct {
name string
request *ClusterAllocationExplainRequest
prettyOutput bool
expectedBody string
}{
{
name: "with nil request",
request: nil,
expectedBody: "",
},
{
name: "with current_node set",
request: &ClusterAllocationExplainRequest{
CurrentNode: "test-node",
},
expectedBody: `{"current_node":"test-node"}`,
},
{
name: "with index set",
request: &ClusterAllocationExplainRequest{
Index: "test-index",
},
expectedBody: `{"index":"test-index"}`,
},
{
name: "with primary set",
request: &ClusterAllocationExplainRequest{
Primary: true,
},
expectedBody: `{"primary":true}`,
},
{
name: "with shard set",
request: &ClusterAllocationExplainRequest{
Shard: "test-shard",
},
expectedBody: `{"shard":"test-shard"}`,
},
{
name: "with pretty output",
request: nil,
prettyOutput: true,
},
}

for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
testSetup := &ServerSetup{
Method: "GET",
Path: "/_cluster/allocation/explain",
Body: tc.expectedBody,
}

if tc.prettyOutput {
testSetup.extraChecksFn = func(t *testing.T, r *http.Request) {
expectedURL := "/_cluster/allocation/explain?pretty="
if r.URL.String() != expectedURL {
t.Errorf("Unexpected url query. Want %s, got %s", expectedURL, r.URL.String())
}
}
}

host, port, ts := setupTestServers(t, []*ServerSetup{testSetup})
defer ts.Close()
client := NewClient(host, port)

_, err := client.ClusterAllocationExplain(tc.request, tc.prettyOutput)
if err != nil {
t.Fatalf("Unexpected error. expected nil, got %s", err)
}
})
}
}

0 comments on commit 102f5bf

Please sign in to comment.