diff --git a/libbeat/setup/kibana/client.go b/libbeat/setup/kibana/client.go index 07baa9efe5a..d25a775bcd7 100644 --- a/libbeat/setup/kibana/client.go +++ b/libbeat/setup/kibana/client.go @@ -10,6 +10,8 @@ import ( "net/url" "strings" + "github.com/pkg/errors" + "github.com/elastic/beats/libbeat/common" "github.com/elastic/beats/libbeat/logp" "github.com/elastic/beats/libbeat/outputs" @@ -38,6 +40,25 @@ func addToURL(_url, _path string, params url.Values) string { return strings.Join([]string{_url, _path, "?", params.Encode()}, "") } +func extractError(result []byte) error { + var kibanaResult struct { + Objects []struct { + Error struct { + Message string + } + } + } + if err := json.Unmarshal(result, &kibanaResult); err != nil { + return errors.Wrap(err, "parsing kibana response") + } + for _, o := range kibanaResult.Objects { + if o.Error.Message != "" { + return errors.New(kibanaResult.Objects[0].Error.Message) + } + } + return nil +} + func NewKibanaClient(cfg *common.Config) (*Client, error) { config := defaultKibanaConfig if err := cfg.Unpack(&config); err != nil { @@ -140,6 +161,7 @@ func (conn *Connection) Request(method, extraPath string, return 0, nil, fmt.Errorf("fail to read response %s", err) } + retError = extractError(result) return resp.StatusCode, result, retError } diff --git a/libbeat/setup/kibana/client_test.go b/libbeat/setup/kibana/client_test.go new file mode 100644 index 00000000000..5a33ee18acc --- /dev/null +++ b/libbeat/setup/kibana/client_test.go @@ -0,0 +1,56 @@ +package kibana + +import ( + "net/http" + "net/http/httptest" + "net/url" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestErrorJson(t *testing.T) { + // also common 200: {"objects":[{"id":"apm-*","type":"index-pattern","error":{"message":"[doc][index-pattern:test-*]: version conflict, document already exists (current version [1])"}}]} + kibanaTs := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(`{"objects":[{"id":"test-*","type":"index-pattern","error":{"message":"action [indices:data/write/bulk[s]] is unauthorized for user [test]"}}]}`)) + })) + defer kibanaTs.Close() + + conn := Connection{ + URL: kibanaTs.URL, + http: http.DefaultClient, + } + code, _, err := conn.Request(http.MethodPost, "", url.Values{}, nil) + assert.Equal(t, http.StatusOK, code) + assert.Error(t, err) +} + +func TestErrorBadJson(t *testing.T) { + kibanaTs := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(`{`)) + })) + defer kibanaTs.Close() + + conn := Connection{ + URL: kibanaTs.URL, + http: http.DefaultClient, + } + code, _, err := conn.Request(http.MethodPost, "", url.Values{}, nil) + assert.Equal(t, http.StatusOK, code) + assert.Error(t, err) +} + +func TestSuccess(t *testing.T) { + kibanaTs := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(`{"objects":[{"id":"test-*","type":"index-pattern","updated_at":"2018-01-24T19:04:13.371Z","version":1}]}`)) + })) + defer kibanaTs.Close() + + conn := Connection{ + URL: kibanaTs.URL, + http: http.DefaultClient, + } + code, _, err := conn.Request(http.MethodPost, "", url.Values{}, nil) + assert.Equal(t, http.StatusOK, code) + assert.NoError(t, err) +}