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
12	"github.com/olivere/elastic/uritemplates"
13)
14
15// IndicesPutTemplateService creates or updates index mappings.
16// See https://www.elastic.co/guide/en/elasticsearch/reference/6.7/indices-templates.html.
17type IndicesPutTemplateService struct {
18	client        *Client
19	pretty        bool
20	name          string
21	cause         string
22	order         interface{}
23	version       *int
24	create        *bool
25	timeout       string
26	masterTimeout string
27	flatSettings  *bool
28	bodyJson      interface{}
29	bodyString    string
30}
31
32// NewIndicesPutTemplateService creates a new IndicesPutTemplateService.
33func NewIndicesPutTemplateService(client *Client) *IndicesPutTemplateService {
34	return &IndicesPutTemplateService{
35		client: client,
36	}
37}
38
39// Name is the name of the index template.
40func (s *IndicesPutTemplateService) Name(name string) *IndicesPutTemplateService {
41	s.name = name
42	return s
43}
44
45// Cause describes the cause for this index template creation. This is currently
46// undocumented, but part of the Java source.
47func (s *IndicesPutTemplateService) Cause(cause string) *IndicesPutTemplateService {
48	s.cause = cause
49	return s
50}
51
52// Timeout is an explicit operation timeout.
53func (s *IndicesPutTemplateService) Timeout(timeout string) *IndicesPutTemplateService {
54	s.timeout = timeout
55	return s
56}
57
58// MasterTimeout specifies the timeout for connection to master.
59func (s *IndicesPutTemplateService) MasterTimeout(masterTimeout string) *IndicesPutTemplateService {
60	s.masterTimeout = masterTimeout
61	return s
62}
63
64// FlatSettings indicates whether to return settings in flat format (default: false).
65func (s *IndicesPutTemplateService) FlatSettings(flatSettings bool) *IndicesPutTemplateService {
66	s.flatSettings = &flatSettings
67	return s
68}
69
70// Order is the order for this template when merging multiple matching ones
71// (higher numbers are merged later, overriding the lower numbers).
72func (s *IndicesPutTemplateService) Order(order interface{}) *IndicesPutTemplateService {
73	s.order = order
74	return s
75}
76
77// Version sets the version number for this template.
78func (s *IndicesPutTemplateService) Version(version int) *IndicesPutTemplateService {
79	s.version = &version
80	return s
81}
82
83// Create indicates whether the index template should only be added if
84// new or can also replace an existing one.
85func (s *IndicesPutTemplateService) Create(create bool) *IndicesPutTemplateService {
86	s.create = &create
87	return s
88}
89
90// Pretty indicates that the JSON response be indented and human readable.
91func (s *IndicesPutTemplateService) Pretty(pretty bool) *IndicesPutTemplateService {
92	s.pretty = pretty
93	return s
94}
95
96// BodyJson is documented as: The template definition.
97func (s *IndicesPutTemplateService) BodyJson(body interface{}) *IndicesPutTemplateService {
98	s.bodyJson = body
99	return s
100}
101
102// BodyString is documented as: The template definition.
103func (s *IndicesPutTemplateService) BodyString(body string) *IndicesPutTemplateService {
104	s.bodyString = body
105	return s
106}
107
108// buildURL builds the URL for the operation.
109func (s *IndicesPutTemplateService) buildURL() (string, url.Values, error) {
110	// Build URL
111	path, err := uritemplates.Expand("/_template/{name}", map[string]string{
112		"name": s.name,
113	})
114	if err != nil {
115		return "", url.Values{}, err
116	}
117
118	// Add query string parameters
119	params := url.Values{}
120	if s.pretty {
121		params.Set("pretty", "true")
122	}
123	if s.order != nil {
124		params.Set("order", fmt.Sprintf("%v", s.order))
125	}
126	if s.version != nil {
127		params.Set("version", fmt.Sprintf("%v", *s.version))
128	}
129	if s.create != nil {
130		params.Set("create", fmt.Sprintf("%v", *s.create))
131	}
132	if s.cause != "" {
133		params.Set("cause", s.cause)
134	}
135	if s.timeout != "" {
136		params.Set("timeout", s.timeout)
137	}
138	if s.masterTimeout != "" {
139		params.Set("master_timeout", s.masterTimeout)
140	}
141	if s.flatSettings != nil {
142		params.Set("flat_settings", fmt.Sprintf("%v", *s.flatSettings))
143	}
144	return path, params, nil
145}
146
147// Validate checks if the operation is valid.
148func (s *IndicesPutTemplateService) Validate() error {
149	var invalid []string
150	if s.name == "" {
151		invalid = append(invalid, "Name")
152	}
153	if s.bodyString == "" && s.bodyJson == nil {
154		invalid = append(invalid, "BodyJson")
155	}
156	if len(invalid) > 0 {
157		return fmt.Errorf("missing required fields: %v", invalid)
158	}
159	return nil
160}
161
162// Do executes the operation.
163func (s *IndicesPutTemplateService) Do(ctx context.Context) (*IndicesPutTemplateResponse, error) {
164	// Check pre-conditions
165	if err := s.Validate(); err != nil {
166		return nil, err
167	}
168
169	// Get URL for request
170	path, params, err := s.buildURL()
171	if err != nil {
172		return nil, err
173	}
174
175	// Setup HTTP request body
176	var body interface{}
177	if s.bodyJson != nil {
178		body = s.bodyJson
179	} else {
180		body = s.bodyString
181	}
182
183	// Get HTTP response
184	res, err := s.client.PerformRequest(ctx, PerformRequestOptions{
185		Method: "PUT",
186		Path:   path,
187		Params: params,
188		Body:   body,
189	})
190	if err != nil {
191		return nil, err
192	}
193
194	// Return operation response
195	ret := new(IndicesPutTemplateResponse)
196	if err := s.client.decoder.Decode(res.Body, ret); err != nil {
197		return nil, err
198	}
199	return ret, nil
200}
201
202// IndicesPutTemplateResponse is the response of IndicesPutTemplateService.Do.
203type IndicesPutTemplateResponse struct {
204	Acknowledged       bool   `json:"acknowledged"`
205	ShardsAcknowledged bool   `json:"shards_acknowledged"`
206	Index              string `json:"index,omitempty"`
207}
208