diff --git a/client/v2/client.go b/client/v2/client.go index f3de4bb1d57..259c4932ef8 100644 --- a/client/v2/client.go +++ b/client/v2/client.go @@ -73,6 +73,9 @@ type BatchPointsConfig struct { // Client is a client interface for writing & querying the database type Client interface { + // Ping checks that status of cluster + Ping(timeout time.Duration) (time.Duration, string, error) + // Write takes a BatchPoints object and writes all Points to InfluxDB. Write(bp BatchPoints) error @@ -119,6 +122,50 @@ func NewHTTPClient(conf HTTPConfig) (Client, error) { }, nil } +// Ping will check to see if the server is up with an optional timeout on waiting for leader. +// Ping returns how long the request took, the version of the server it connected to, and an error if one occurred. +func (c *client) Ping(timeout time.Duration) (time.Duration, string, error) { + now := time.Now() + u := c.url + u.Path = "ping" + + req, err := http.NewRequest("GET", u.String(), nil) + if err != nil { + return 0, "", err + } + + req.Header.Set("User-Agent", c.useragent) + + if c.username != "" { + req.SetBasicAuth(c.username, c.password) + } + + if timeout > 0 { + params := req.URL.Query() + params.Set("wait_for_leader", fmt.Sprintf("%.0fs", timeout.Seconds())) + req.URL.RawQuery = params.Encode() + } + + resp, err := c.httpClient.Do(req) + if err != nil { + return 0, "", err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return 0, "", err + } + + if resp.StatusCode != http.StatusNoContent { + var err = fmt.Errorf(string(body)) + return 0, "", err + } + + version := resp.Header.Get("X-Influxdb-Version") + return time.Since(now), version, nil +} + // Close releases the client's resources. func (c *client) Close() error { return nil @@ -149,6 +196,12 @@ func NewUDPClient(conf UDPConfig) (Client, error) { }, nil } +// Ping will check to see if the server is up with an optional timeout on waiting for leader. +// Ping returns how long the request took, the version of the server it connected to, and an error if one occurred. +func (uc *udpclient) Ping(timeout time.Duration) (time.Duration, string, error) { + return 0, "", nil +} + // Close releases the udpclient's resources. func (uc *udpclient) Close() error { return uc.conn.Close() diff --git a/client/v2/client_test.go b/client/v2/client_test.go index 5f1e908a190..9272292b662 100644 --- a/client/v2/client_test.go +++ b/client/v2/client_test.go @@ -24,6 +24,20 @@ func TestUDPClient_Query(t *testing.T) { } } +func TestUDPClient_Ping(t *testing.T) { + config := UDPConfig{Addr: "localhost:8089"} + c, err := NewUDPClient(config) + if err != nil { + t.Errorf("unexpected error. expected %v, actual %v", nil, err) + } + defer c.Close() + + rtt, version, err := c.Ping(0) + if rtt != 0 || version != "" || err != nil { + t.Errorf("unexpected error. expected (%v, '%v', %v), actual (%v, '%v', %v)", 0, "", nil, rtt, version, err) + } +} + func TestUDPClient_Write(t *testing.T) { config := UDPConfig{Addr: "localhost:8089"} c, err := NewUDPClient(config) @@ -106,6 +120,24 @@ func TestClient_BasicAuth(t *testing.T) { } } +func TestClient_Ping(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var data Response + w.WriteHeader(http.StatusNoContent) + _ = json.NewEncoder(w).Encode(data) + })) + defer ts.Close() + + config := HTTPConfig{Addr: ts.URL} + c, _ := NewHTTPClient(config) + defer c.Close() + + _, _, err := c.Ping(0) + if err != nil { + t.Errorf("unexpected error. expected %v, actual %v", nil, err) + } +} + func TestClient_Write(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var data Response diff --git a/client/v2/example_test.go b/client/v2/example_test.go index ae899d8eebf..93d7ad3bac2 100644 --- a/client/v2/example_test.go +++ b/client/v2/example_test.go @@ -55,6 +55,23 @@ func ExampleClient_uDP() { c.Write(bp) } +// Ping the cluster using the HTTP client +func ExampleClient_Ping() { + // Make client + c, err := client.NewHTTPClient(client.HTTPConfig{ + Addr: "http://localhost:8086", + }) + if err != nil { + fmt.Println("Error creating InfluxDB Client: ", err.Error()) + } + defer c.Close() + + _, _, err = c.Ping(0) + if err != nil { + fmt.Println("Error pinging InfluxDB Cluster: ", err.Error()) + } +} + // Write a point using the HTTP client func ExampleClient_write() { // Make client