Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update IsServerless() to use correct Kibana APIs #213

Merged
merged 5 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 35 additions & 9 deletions kibana/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"mime"
"mime/multipart"
"net/http"
Expand Down Expand Up @@ -226,7 +225,7 @@ func (conn *Connection) Request(method, extraPath string,
}
defer resp.Body.Close()

result, err := ioutil.ReadAll(resp.Body)
result, err := io.ReadAll(resp.Body)
if err != nil {
return 0, nil, fmt.Errorf("fail to read response: %w", err)
}
Expand Down Expand Up @@ -346,16 +345,43 @@ func (client *Client) readVersion() error {
func (client *Client) GetVersion() version.V { return client.Version }

// KibanaIsServerless returns true if we're talking to a serverless instance.
// Right now we don't have an API to tell us if we're running against serverless or not, so this actual implementation is something of a hack.
// see https://github.com/elastic/kibana/pull/164850
func (client *Client) KibanaIsServerless() (bool, error) {
ret, _, err := client.Connection.Request("GET", "/api/saved_objects/_find", nil, nil, nil)
if ret > 300 && strings.Contains(err.Error(), "not available with the current configuration") {

type apiStatus struct {
Version struct {
BuildFlavor string `json:"build_flavor"`
} `json:"version"`
}

// we can send a GET to `/api/status` without auth, but it won't actually return version info.
params := http.Header{}
if client.APIKey != "" {
v := "ApiKey " + base64.StdEncoding.EncodeToString([]byte(client.APIKey))
params.Add("Authorization", v)
}

ret, resp, err := client.Connection.Request("GET", "/api/status", nil, params, nil)
if err != nil {
return false, fmt.Errorf("error in HTTP request: %w", err)
}

respString := string(resp)
if ret > http.StatusMultipleChoices {
return false, fmt.Errorf("got invalid response code: %v (%s)", ret, respString)
}

status := apiStatus{}
err = json.Unmarshal(resp, &status)
if err != nil {
return false, fmt.Errorf("error unmarshalling JSON: %w", err)
}

if status.Version.BuildFlavor == "serverless" {
return true, nil
} else if err != nil {
return false, fmt.Errorf("error checking serverless status: %w", err)
} else {
return false, nil
}
return false, nil

}

func (client *Client) ImportMultiPartFormFile(url string, params url.Values, filename string, contents string) error {
Expand Down
22 changes: 22 additions & 0 deletions kibana/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,28 @@ func assertConnection(t *testing.T, URL string, expectedStatusCode int) {
assert.Error(t, err)
}

func TestIsServerless(t *testing.T) {
rawStatusCall := `{"name":"kb","uuid":"d2130570-f7d8-463b-bd67-8503150004d5","version":{"number":"8.15.0","build_hash":"13382875e99e8c97f4574d86eca07cac3be9edfc","build_number":75422,"build_snapshot":false,"build_flavor":"stateful","build_date":"2024-06-15T18:13:50.595Z"}}`

kibanaTS := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(rawStatusCall))
}))
defer kibanaTS.Close()

conn := Connection{
URL: kibanaTS.URL,
HTTP: http.DefaultClient,
}

testClient := Client{
Connection: conn,
}

got, err := testClient.KibanaIsServerless()
require.NoError(t, err)
require.False(t, got)
}

func TestErrorBadJson(t *testing.T) {
kibanaTS := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusGone)
Expand Down
3 changes: 2 additions & 1 deletion transport/httpcommon/diag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,8 @@ func Test_diagError(t *testing.T) {
}
_, err = client.Do(req) //nolint:bodyclose // expected to return an error
require.Error(t, err)
require.Contains(t, diagError(err), "caused by expired mTLS client cert.")
// different OSes seem to report different TLS errors, so just check for the "expired" string.
require.Contains(t, diagError(err), "expired")
})
}

Expand Down
Loading