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 "fmt" 10 "net/url" 11 "strings" 12 13 "gopkg.in/olivere/elastic.v2/uritemplates" 14) 15 16// ClusterHealthService allows to get the status of the cluster. 17// It is documented at http://www.elasticsearch.org/guide/en/elasticsearch/reference/1.4/cluster-health.html. 18type ClusterHealthService struct { 19 client *Client 20 pretty bool 21 indices []string 22 waitForStatus string 23 level string 24 local *bool 25 masterTimeout string 26 timeout string 27 waitForActiveShards *int 28 waitForNodes string 29 waitForRelocatingShards *int 30} 31 32// NewClusterHealthService creates a new ClusterHealthService. 33func NewClusterHealthService(client *Client) *ClusterHealthService { 34 return &ClusterHealthService{client: client, indices: make([]string, 0)} 35} 36 37// Index limits the information returned to a specific index. 38func (s *ClusterHealthService) Index(index string) *ClusterHealthService { 39 s.indices = make([]string, 0) 40 s.indices = append(s.indices, index) 41 return s 42} 43 44// Indices limits the information returned to specific indices. 45func (s *ClusterHealthService) Indices(indices ...string) *ClusterHealthService { 46 s.indices = make([]string, 0) 47 s.indices = append(s.indices, indices...) 48 return s 49} 50 51// MasterTimeout specifies an explicit operation timeout for connection to master node. 52func (s *ClusterHealthService) MasterTimeout(masterTimeout string) *ClusterHealthService { 53 s.masterTimeout = masterTimeout 54 return s 55} 56 57// Timeout specifies an explicit operation timeout. 58func (s *ClusterHealthService) Timeout(timeout string) *ClusterHealthService { 59 s.timeout = timeout 60 return s 61} 62 63// WaitForActiveShards can be used to wait until the specified number of shards are active. 64func (s *ClusterHealthService) WaitForActiveShards(waitForActiveShards int) *ClusterHealthService { 65 s.waitForActiveShards = &waitForActiveShards 66 return s 67} 68 69// WaitForNodes can be used to wait until the specified number of nodes are available. 70func (s *ClusterHealthService) WaitForNodes(waitForNodes string) *ClusterHealthService { 71 s.waitForNodes = waitForNodes 72 return s 73} 74 75// WaitForRelocatingShards can be used to wait until the specified number of relocating shards is finished. 76func (s *ClusterHealthService) WaitForRelocatingShards(waitForRelocatingShards int) *ClusterHealthService { 77 s.waitForRelocatingShards = &waitForRelocatingShards 78 return s 79} 80 81// WaitForStatus can be used to wait until the cluster is in a specific state. 82// Valid values are: green, yellow, or red. 83func (s *ClusterHealthService) WaitForStatus(waitForStatus string) *ClusterHealthService { 84 s.waitForStatus = waitForStatus 85 return s 86} 87 88// Level specifies the level of detail for returned information. 89func (s *ClusterHealthService) Level(level string) *ClusterHealthService { 90 s.level = level 91 return s 92} 93 94// Local indicates whether to return local information. If it is true, 95// we do not retrieve the state from master node (default: false). 96func (s *ClusterHealthService) Local(local bool) *ClusterHealthService { 97 s.local = &local 98 return s 99} 100 101// buildURL builds the URL for the operation. 102func (s *ClusterHealthService) buildURL() (string, url.Values, error) { 103 // Build URL 104 path, err := uritemplates.Expand("/_cluster/health/{index}", map[string]string{ 105 "index": strings.Join(s.indices, ","), 106 }) 107 if err != nil { 108 return "", url.Values{}, err 109 } 110 111 // Add query string parameters 112 params := url.Values{} 113 if s.waitForRelocatingShards != nil { 114 params.Set("wait_for_relocating_shards", fmt.Sprintf("%d", *s.waitForRelocatingShards)) 115 } 116 if s.waitForStatus != "" { 117 params.Set("wait_for_status", s.waitForStatus) 118 } 119 if s.level != "" { 120 params.Set("level", s.level) 121 } 122 if s.local != nil { 123 params.Set("local", fmt.Sprintf("%v", *s.local)) 124 } 125 if s.masterTimeout != "" { 126 params.Set("master_timeout", s.masterTimeout) 127 } 128 if s.timeout != "" { 129 params.Set("timeout", s.timeout) 130 } 131 if s.waitForActiveShards != nil { 132 params.Set("wait_for_active_shards", fmt.Sprintf("%d", *s.waitForActiveShards)) 133 } 134 if s.waitForNodes != "" { 135 params.Set("wait_for_nodes", s.waitForNodes) 136 } 137 138 return path, params, nil 139} 140 141// Validate checks if the operation is valid. 142func (s *ClusterHealthService) Validate() error { 143 return nil 144} 145 146// Do executes the operation. 147func (s *ClusterHealthService) Do() (*ClusterHealthResponse, error) { 148 // Check pre-conditions 149 if err := s.Validate(); err != nil { 150 return nil, err 151 } 152 153 // Get URL for request 154 path, params, err := s.buildURL() 155 if err != nil { 156 return nil, err 157 } 158 159 // Get HTTP response 160 res, err := s.client.PerformRequest("GET", path, params, nil) 161 if err != nil { 162 return nil, err 163 } 164 165 // Return operation response 166 resp := new(ClusterHealthResponse) 167 if err := json.Unmarshal(res.Body, resp); err != nil { 168 return nil, err 169 } 170 return resp, nil 171} 172 173// ClusterHealthResponse is the response of ClusterHealthService.Do. 174type ClusterHealthResponse struct { 175 ClusterName string `json:"cluster_name"` 176 Status string `json:"status"` 177 TimedOut bool `json:"timed_out"` 178 NumberOfNodes int `json:"number_of_nodes"` 179 NumberOfDataNodes int `json:"number_of_data_nodes"` 180 ActivePrimaryShards int `json:"active_primary_shards"` 181 ActiveShards int `json:"active_shards"` 182 RelocatingShards int `json:"relocating_shards"` 183 InitializingShards int `json:"initializing_shards"` 184 UnassignedShards int `json:"unassigned_shards"` 185 NumberOfPendingTasks int `json:"number_of_pending_tasks"` 186} 187