1// Copyright 2012-present 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 "context" 9 "fmt" 10 "net/url" 11 "strings" 12 13 "gopkg.in/olivere/elastic.v5/uritemplates" 14) 15 16// TasksListService retrieves the list of currently executing tasks 17// on one ore more nodes in the cluster. It is part of the Task Management API 18// documented at http://www.elastic.co/guide/en/elasticsearch/reference/5.2/tasks-list.html. 19// 20// It is supported as of Elasticsearch 2.3.0. 21type TasksListService struct { 22 client *Client 23 pretty bool 24 taskId []int64 25 actions []string 26 detailed *bool 27 nodeId []string 28 parentNode string 29 parentTask *int64 30 waitForCompletion *bool 31} 32 33// NewTasksListService creates a new TasksListService. 34func NewTasksListService(client *Client) *TasksListService { 35 return &TasksListService{ 36 client: client, 37 taskId: make([]int64, 0), 38 actions: make([]string, 0), 39 nodeId: make([]string, 0), 40 } 41} 42 43// TaskId indicates to returns the task(s) with specified id(s). 44func (s *TasksListService) TaskId(taskId ...int64) *TasksListService { 45 s.taskId = append(s.taskId, taskId...) 46 return s 47} 48 49// Actions is a list of actions that should be returned. Leave empty to return all. 50func (s *TasksListService) Actions(actions ...string) *TasksListService { 51 s.actions = append(s.actions, actions...) 52 return s 53} 54 55// Detailed indicates whether to return detailed task information (default: false). 56func (s *TasksListService) Detailed(detailed bool) *TasksListService { 57 s.detailed = &detailed 58 return s 59} 60 61// NodeId is a list of node IDs or names to limit the returned information; 62// use `_local` to return information from the node you're connecting to, 63// leave empty to get information from all nodes. 64func (s *TasksListService) NodeId(nodeId ...string) *TasksListService { 65 s.nodeId = append(s.nodeId, nodeId...) 66 return s 67} 68 69// ParentNode returns tasks with specified parent node. 70func (s *TasksListService) ParentNode(parentNode string) *TasksListService { 71 s.parentNode = parentNode 72 return s 73} 74 75// ParentTask returns tasks with specified parent task id. Set to -1 to return all. 76func (s *TasksListService) ParentTask(parentTask int64) *TasksListService { 77 s.parentTask = &parentTask 78 return s 79} 80 81// WaitForCompletion indicates whether to wait for the matching tasks 82// to complete (default: false). 83func (s *TasksListService) WaitForCompletion(waitForCompletion bool) *TasksListService { 84 s.waitForCompletion = &waitForCompletion 85 return s 86} 87 88// Pretty indicates that the JSON response be indented and human readable. 89func (s *TasksListService) Pretty(pretty bool) *TasksListService { 90 s.pretty = pretty 91 return s 92} 93 94// buildURL builds the URL for the operation. 95func (s *TasksListService) buildURL() (string, url.Values, error) { 96 // Build URL 97 var err error 98 var path string 99 if len(s.taskId) > 0 { 100 var tasks []string 101 for _, taskId := range s.taskId { 102 tasks = append(tasks, fmt.Sprintf("%d", taskId)) 103 } 104 path, err = uritemplates.Expand("/_tasks/{task_id}", map[string]string{ 105 "task_id": strings.Join(tasks, ","), 106 }) 107 } else { 108 path = "/_tasks" 109 } 110 if err != nil { 111 return "", url.Values{}, err 112 } 113 114 // Add query string parameters 115 params := url.Values{} 116 if s.pretty { 117 params.Set("pretty", "1") 118 } 119 if len(s.actions) > 0 { 120 params.Set("actions", strings.Join(s.actions, ",")) 121 } 122 if s.detailed != nil { 123 params.Set("detailed", fmt.Sprintf("%v", *s.detailed)) 124 } 125 if len(s.nodeId) > 0 { 126 params.Set("node_id", strings.Join(s.nodeId, ",")) 127 } 128 if s.parentNode != "" { 129 params.Set("parent_node", s.parentNode) 130 } 131 if s.parentTask != nil { 132 params.Set("parent_task", fmt.Sprintf("%v", *s.parentTask)) 133 } 134 if s.waitForCompletion != nil { 135 params.Set("wait_for_completion", fmt.Sprintf("%v", *s.waitForCompletion)) 136 } 137 return path, params, nil 138} 139 140// Validate checks if the operation is valid. 141func (s *TasksListService) Validate() error { 142 return nil 143} 144 145// Do executes the operation. 146func (s *TasksListService) Do(ctx context.Context) (*TasksListResponse, error) { 147 // Check pre-conditions 148 if err := s.Validate(); err != nil { 149 return nil, err 150 } 151 152 // Get URL for request 153 path, params, err := s.buildURL() 154 if err != nil { 155 return nil, err 156 } 157 158 // Get HTTP response 159 res, err := s.client.PerformRequest(ctx, "GET", path, params, nil) 160 if err != nil { 161 return nil, err 162 } 163 164 // Return operation response 165 ret := new(TasksListResponse) 166 if err := s.client.decoder.Decode(res.Body, ret); err != nil { 167 return nil, err 168 } 169 return ret, nil 170} 171 172// TasksListResponse is the response of TasksListService.Do. 173type TasksListResponse struct { 174 TaskFailures []*TaskOperationFailure `json:"task_failures"` 175 NodeFailures []*FailedNodeException `json:"node_failures"` 176 // Nodes returns the tasks per node. The key is the node id. 177 Nodes map[string]*DiscoveryNode `json:"nodes"` 178} 179 180type TaskOperationFailure struct { 181 TaskId int64 `json:"task_id"` 182 NodeId string `json:"node_id"` 183 Status string `json:"status"` 184 Reason *ErrorDetails `json:"reason"` 185} 186 187type FailedNodeException struct { 188 *ErrorDetails 189 NodeId string `json:"node_id"` 190} 191 192type DiscoveryNode struct { 193 Name string `json:"name"` 194 TransportAddress string `json:"transport_address"` 195 Host string `json:"host"` 196 IP string `json:"ip"` 197 Attributes map[string]interface{} `json:"attributes"` 198 // Tasks returns the tasks by its id (as a string). 199 Tasks map[string]*TaskInfo `json:"tasks"` 200} 201 202type TaskInfo struct { 203 Node string `json:"node"` 204 Id int64 `json:"id"` // the task id 205 Type string `json:"type"` 206 Action string `json:"action"` 207 Status interface{} `json:"status"` // has separate implementations of Task.Status in Java for reindexing, replication, and "RawTaskStatus" 208 Description interface{} `json:"description"` // same as Status 209 StartTime string `json:"start_time"` 210 StartTimeInMillis int64 `json:"start_time_in_millis"` 211 RunningTime string `json:"running_time"` 212 RunningTimeInNanos int64 `json:"running_time_in_nanos"` 213 Cancellable bool `json:"cancellable"` 214 ParentTaskId string `json:"parent_task_id"` // like "YxJnVYjwSBm_AUbzddTajQ:12356" 215} 216 217// StartTaskResult is used in cases where a task gets started asynchronously and 218// the operation simply returnes a TaskID to watch for via the Task Management API. 219type StartTaskResult struct { 220 TaskId string `json:"task"` 221} 222