1// Copyright 2012-2015 Oliver Eilhard. All rights reserved.
2// Use of this source code is governed by a MIT-license.
3// See http://olivere.mit-license.org/license.txt for details.
4
5package elastic
6
7import (
8	"encoding/json"
9	"net/http"
10	"net/url"
11)
12
13// PingService checks if an Elasticsearch server on a given URL is alive.
14// When asked for, it can also return various information about the
15// Elasticsearch server, e.g. the Elasticsearch version number.
16//
17// Ping simply starts a HTTP GET request to the URL of the server.
18// If the server responds with HTTP Status code 200 OK, the server is alive.
19type PingService struct {
20	client       *Client
21	url          string
22	timeout      string
23	httpHeadOnly bool
24	pretty       bool
25}
26
27// PingResult is the result returned from querying the Elasticsearch server.
28type PingResult struct {
29	Status      int    `json:"status"`
30	Name        string `json:"name"`
31	ClusterName string `json:"cluster_name"`
32	Version     struct {
33		Number         string `json:"number"`
34		BuildHash      string `json:"build_hash"`
35		BuildTimestamp string `json:"build_timestamp"`
36		BuildSnapshot  bool   `json:"build_snapshot"`
37		LuceneVersion  string `json:"lucene_version"`
38	} `json:"version"`
39	TagLine string `json:"tagline"`
40}
41
42func NewPingService(client *Client) *PingService {
43	return &PingService{
44		client:       client,
45		url:          DefaultURL,
46		httpHeadOnly: false,
47		pretty:       false,
48	}
49}
50
51func (s *PingService) URL(url string) *PingService {
52	s.url = url
53	return s
54}
55
56func (s *PingService) Timeout(timeout string) *PingService {
57	s.timeout = timeout
58	return s
59}
60
61// HeadOnly makes the service to only return the status code in Do;
62// the PingResult will be nil.
63func (s *PingService) HttpHeadOnly(httpHeadOnly bool) *PingService {
64	s.httpHeadOnly = httpHeadOnly
65	return s
66}
67
68func (s *PingService) Pretty(pretty bool) *PingService {
69	s.pretty = pretty
70	return s
71}
72
73// Do returns the PingResult, the HTTP status code of the Elasticsearch
74// server, and an error.
75func (s *PingService) Do() (*PingResult, int, error) {
76	url_ := s.url + "/"
77
78	params := make(url.Values)
79	if s.timeout != "" {
80		params.Set("timeout", s.timeout)
81	}
82	if s.pretty {
83		params.Set("pretty", "1")
84	}
85	if len(params) > 0 {
86		url_ += "?" + params.Encode()
87	}
88
89	var method string
90	if s.httpHeadOnly {
91		method = "HEAD"
92	} else {
93		method = "GET"
94	}
95
96	// Notice: This service must NOT use PerformRequest!
97	req, err := NewRequest(method, url_)
98	if err != nil {
99		return nil, 0, err
100	}
101
102	res, err := s.client.c.Do((*http.Request)(req))
103	if err != nil {
104		return nil, 0, err
105	}
106	defer res.Body.Close()
107
108	var ret *PingResult
109	if !s.httpHeadOnly {
110		ret = new(PingResult)
111		if err := json.NewDecoder(res.Body).Decode(ret); err != nil {
112			return nil, res.StatusCode, err
113		}
114	}
115
116	return ret, res.StatusCode, nil
117}
118