From f7cecafd02f8c6aa60e491f18c1816616796b49c Mon Sep 17 00:00:00 2001 From: hugodorea Date: Wed, 10 Aug 2022 15:37:08 -0700 Subject: [PATCH 1/7] adds ClusterAllocationExplain method --- es.go | 34 ++++++++++++++++++++++++++++++ es_test.go | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/es.go b/es.go index 724526f..a57ddbd 100644 --- a/es.go +++ b/es.go @@ -1567,3 +1567,37 @@ 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. +func (c *Client) ClusterAllocationExplain(req *ClusterAllocationExplainRequest) (string, error) { + agent := c.buildGetRequest("_cluster/allocation/explain?pretty"). + Set("Content-Type", "application/json") + + if req != nil { + agent.Send(req) + } + + body, err := handleErrWithBytes(agent) + if err != nil { + return "", err + } + + return string(body), nil +} diff --git a/es_test.go b/es_test.go index c616b1b..fc5cb2f 100644 --- a/es_test.go +++ b/es_test.go @@ -2096,3 +2096,65 @@ 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 + 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"}`, + }, + } + + 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, + } + + host, port, ts := setupTestServers(t, []*ServerSetup{testSetup}) + defer ts.Close() + client := NewClient(host, port) + + _, err := client.ClusterAllocationExplain(tc.request) + if err != nil { + t.Fatalf("Unexpected error expected nil, got %s", err) + } + }) + } +} From 97c09212511581de18ec166b0ea0bc10d1a9d97b Mon Sep 17 00:00:00 2001 From: hugodorea Date: Wed, 10 Aug 2022 15:40:28 -0700 Subject: [PATCH 2/7] small punctuation fix --- es_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/es_test.go b/es_test.go index fc5cb2f..4dd4dfe 100644 --- a/es_test.go +++ b/es_test.go @@ -2153,7 +2153,7 @@ func TestClusterAllocationExplain(t *testing.T) { _, err := client.ClusterAllocationExplain(tc.request) if err != nil { - t.Fatalf("Unexpected error expected nil, got %s", err) + t.Fatalf("Unexpected error. expected nil, got %s", err) } }) } From 71e8a4617895cfdea533e8245ca6cb13498b9c63 Mon Sep 17 00:00:00 2001 From: hugodorea Date: Wed, 10 Aug 2022 15:42:26 -0700 Subject: [PATCH 3/7] adds elastic.co documentation link to comment --- es.go | 1 + 1 file changed, 1 insertion(+) diff --git a/es.go b/es.go index a57ddbd..6abbf00 100644 --- a/es.go +++ b/es.go @@ -1586,6 +1586,7 @@ type ClusterAllocationExplainRequest struct { } // 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) (string, error) { agent := c.buildGetRequest("_cluster/allocation/explain?pretty"). Set("Content-Type", "application/json") From 8b6852347c7331b1015737bfe5a916d0d44ca2dc Mon Sep 17 00:00:00 2001 From: hugodorea Date: Thu, 11 Aug 2022 11:05:54 -0700 Subject: [PATCH 4/7] adds prettyOutput argument to ClusterAllocationExplain method --- es.go | 13 +++++++++---- es_test.go | 26 +++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/es.go b/es.go index 6abbf00..c99a6ed 100644 --- a/es.go +++ b/es.go @@ -1587,12 +1587,17 @@ type ClusterAllocationExplainRequest struct { // 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) (string, error) { - agent := c.buildGetRequest("_cluster/allocation/explain?pretty"). - Set("Content-Type", "application/json") +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.Send(req) + agent.Set("Content-Type", "application/json"). + Send(req) } body, err := handleErrWithBytes(agent) diff --git a/es_test.go b/es_test.go index 4dd4dfe..97cec90 100644 --- a/es_test.go +++ b/es_test.go @@ -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 { @@ -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) + if r.Method == setup.Method && r.URL.String() == setup.Path && 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 { @@ -2101,6 +2106,7 @@ func TestClusterAllocationExplain(t *testing.T) { tests := []struct { name string request *ClusterAllocationExplainRequest + prettyOutput bool expectedBody string }{ { @@ -2136,6 +2142,11 @@ func TestClusterAllocationExplain(t *testing.T) { }, expectedBody: `{"shard":"test-shard"}`, }, + { + name: "with pretty output", + request: nil, + prettyOutput: true, + }, } for _, tt := range tests { @@ -2147,11 +2158,20 @@ func TestClusterAllocationExplain(t *testing.T) { 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) + _, err := client.ClusterAllocationExplain(tc.request, tc.prettyOutput) if err != nil { t.Fatalf("Unexpected error. expected nil, got %s", err) } From 58a9be9634c83e618a540c1dc9c0d45dc4f32ac3 Mon Sep 17 00:00:00 2001 From: hugodorea Date: Thu, 11 Aug 2022 11:31:22 -0700 Subject: [PATCH 5/7] adds global path for golangci-lint in test script --- es.go | 3 +-- script/test | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/es.go b/es.go index c99a6ed..bfcbb61 100644 --- a/es.go +++ b/es.go @@ -1596,8 +1596,7 @@ func (c *Client) ClusterAllocationExplain(req *ClusterAllocationExplainRequest, agent := c.buildGetRequest(urlBuilder.String()) if req != nil { - agent.Set("Content-Type", "application/json"). - Send(req) + agent.Set("Content-Type", "application/json").Send(req) } body, err := handleErrWithBytes(agent) diff --git a/script/test b/script/test index 8fb4f03..fa22d74 100755 --- a/script/test +++ b/script/test @@ -11,4 +11,4 @@ else go test -v github.com/github/vulcanizer/... fi -golangci-lint -v run +$(go env GOPATH)/bin/golangci-lint -v run From 694de6e9aa83f865237489d6af4fb1f1741ea2e5 Mon Sep 17 00:00:00 2001 From: hugodorea Date: Thu, 11 Aug 2022 11:34:06 -0700 Subject: [PATCH 6/7] removes global path to golangci-lint --- script/test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/test b/script/test index fa22d74..8fb4f03 100755 --- a/script/test +++ b/script/test @@ -11,4 +11,4 @@ else go test -v github.com/github/vulcanizer/... fi -$(go env GOPATH)/bin/golangci-lint -v run +golangci-lint -v run From 7bd342038514d58df7a923e76fe370a770627f2d Mon Sep 17 00:00:00 2001 From: hugodorea Date: Thu, 11 Aug 2022 11:35:26 -0700 Subject: [PATCH 7/7] reverts from URL.String to URL.EscapedPath --- es_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/es_test.go b/es_test.go index 97cec90..5026c32 100644 --- a/es_test.go +++ b/es_test.go @@ -34,7 +34,7 @@ func buildTestServer(t *testing.T, setups []*ServerSetup, tls bool) *httptest.Se 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.String() == setup.Path && requestBody != setup.Body { + if r.Method == setup.Method && r.URL.EscapedPath() == setup.Path && requestBody != setup.Body { t.Fatalf("request body not matching: %s != %s", requestBody, setup.Body) }