diff --git a/client.go b/client.go index 38a93faa3..dc4224624 100644 --- a/client.go +++ b/client.go @@ -1816,7 +1816,31 @@ func (c *Client) IndexDeleteIndexTemplate(name string) *IndicesDeleteIndexTempla return NewIndicesDeleteIndexTemplateService(c).Name(name) } -// -- TODO Component templates -- +// -- Component templates -- + +// IndexPutComponentTemplate creates or updates a component template (available since 7.8). +// +// This service implements the component templates as described +// on https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-component-template.html. +func (c *Client) IndexPutComponentTemplate(name string) *IndicesPutComponentTemplateService { + return NewIndicesPutComponentTemplateService(c).Name(name) +} + +// IndexGetComponentTemplate returns a component template (available since 7.8). +// +// This service implements the component templates as described +// on https://www.elastic.co/guide/en/elasticsearch/reference/7.10/getting-component-templates.html. +func (c *Client) IndexGetComponentTemplate(name string) *IndicesGetComponentTemplateService { + return NewIndicesGetComponentTemplateService(c).Name(name) +} + +// IndexDeleteComponentTemplate deletes a component template (available since 7.8). +// +// This service implements the component templates as described +// on https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-delete-component-template.html. +func (c *Client) IndexDeleteComponentTemplate(name string) *IndicesDeleteComponentTemplateService { + return NewIndicesDeleteComponentTemplateService(c).Name(name) +} // GetMapping gets a mapping. func (c *Client) GetMapping() *IndicesGetMappingService { diff --git a/indices_component_templates_test.go b/indices_component_templates_test.go new file mode 100644 index 000000000..14f4fc82a --- /dev/null +++ b/indices_component_templates_test.go @@ -0,0 +1,67 @@ +// Copyright 2012-present Oliver Eilhard. All rights reserved. +// Use of this source code is governed by a MIT-license. +// See http://olivere.mit-license.org/license.txt for details. + +package elastic + +import ( + "context" + "testing" +) + +func TestComponentTemplatesLifecycle(t *testing.T) { + client := setupTestClientAndCreateIndex(t) + + const templateName = "template_1" + + // Always make sure the component template is deleted + defer func() { + _, _ = client.IndexDeleteComponentTemplate(templateName).Pretty(true).Do(context.Background()) + }() + + // Create an component template + { + resp, err := client.IndexPutComponentTemplate(templateName).Pretty(true).BodyString(`{ + "template": { + "settings": { + "number_of_shards": 2, + "number_of_replicas": 0 + }, + "mappings": { + "_source": { "enabled": true } + } + } + }`).Do(context.Background()) + if err != nil { + t.Fatalf("expected to successfully create component template, got %v", err) + } + if resp == nil { + t.Fatal("expected response on creating component template") + } + if want, have := true, resp.Acknowledged; want != have { + t.Errorf("expected Acknowledged=%v, got %v", want, have) + } + } + + // Get the component template + { + resp, err := client.IndexGetComponentTemplate(templateName).Pretty(true).Do(context.Background()) + if err != nil { + t.Fatalf("expected to successfully get component template, got %v", err) + } + if resp == nil { + t.Fatal("expected response on getting component template") + } + } + + // Delete the component template + { + resp, err := client.IndexDeleteComponentTemplate(templateName).Pretty(true).Do(context.Background()) + if err != nil { + t.Fatalf("expected to successfully delete component template, got %v", err) + } + if resp == nil { + t.Fatal("expected response on deleting component template") + } + } +} diff --git a/indices_delete_component_template.go b/indices_delete_component_template.go new file mode 100644 index 000000000..46b842ab9 --- /dev/null +++ b/indices_delete_component_template.go @@ -0,0 +1,182 @@ +// Copyright 2012-present Oliver Eilhard. All rights reserved. +// Use of this source code is governed by a MIT-license. +// See http://olivere.mit-license.org/license.txt for details. + +package elastic + +import ( + "context" + "fmt" + "net/http" + "net/url" + "strings" + + "github.com/olivere/elastic/v7/uritemplates" +) + +// IndicesDeleteComponentTemplateService deletes component templates. +// +// See https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-delete-component-template.html +// for more details. +type IndicesDeleteComponentTemplateService struct { + client *Client + + pretty *bool // pretty format the returned JSON response + human *bool // return human readable values for statistics + errorTrace *bool // include the stack trace of returned errors + filterPath []string // list of filters used to reduce the response + headers http.Header // custom request-level HTTP headers + + name string + timeout string + masterTimeout string +} + +// NewIndicesDeleteComponentTemplateService creates a new IndicesDeleteComponentTemplateService. +func NewIndicesDeleteComponentTemplateService(client *Client) *IndicesDeleteComponentTemplateService { + return &IndicesDeleteComponentTemplateService{ + client: client, + } +} + +// Pretty tells Elasticsearch whether to return a formatted JSON response. +func (s *IndicesDeleteComponentTemplateService) Pretty(pretty bool) *IndicesDeleteComponentTemplateService { + s.pretty = &pretty + return s +} + +// Human specifies whether human readable values should be returned in +// the JSON response, e.g. "7.5mb". +func (s *IndicesDeleteComponentTemplateService) Human(human bool) *IndicesDeleteComponentTemplateService { + s.human = &human + return s +} + +// ErrorTrace specifies whether to include the stack trace of returned errors. +func (s *IndicesDeleteComponentTemplateService) ErrorTrace(errorTrace bool) *IndicesDeleteComponentTemplateService { + s.errorTrace = &errorTrace + return s +} + +// FilterPath specifies a list of filters used to reduce the response. +func (s *IndicesDeleteComponentTemplateService) FilterPath(filterPath ...string) *IndicesDeleteComponentTemplateService { + s.filterPath = filterPath + return s +} + +// Header adds a header to the request. +func (s *IndicesDeleteComponentTemplateService) Header(name string, value string) *IndicesDeleteComponentTemplateService { + if s.headers == nil { + s.headers = http.Header{} + } + s.headers.Add(name, value) + return s +} + +// Headers specifies the headers of the request. +func (s *IndicesDeleteComponentTemplateService) Headers(headers http.Header) *IndicesDeleteComponentTemplateService { + s.headers = headers + return s +} + +// Name is the name of the template. +func (s *IndicesDeleteComponentTemplateService) Name(name string) *IndicesDeleteComponentTemplateService { + s.name = name + return s +} + +// Timeout is an explicit operation timeout. +func (s *IndicesDeleteComponentTemplateService) Timeout(timeout string) *IndicesDeleteComponentTemplateService { + s.timeout = timeout + return s +} + +// MasterTimeout specifies the timeout for connection to master. +func (s *IndicesDeleteComponentTemplateService) MasterTimeout(masterTimeout string) *IndicesDeleteComponentTemplateService { + s.masterTimeout = masterTimeout + return s +} + +// buildURL builds the URL for the operation. +func (s *IndicesDeleteComponentTemplateService) buildURL() (string, url.Values, error) { + // Build URL + path, err := uritemplates.Expand("/_component_template/{name}", map[string]string{ + "name": s.name, + }) + if err != nil { + return "", url.Values{}, err + } + + // Add query string parameters + params := url.Values{} + if v := s.pretty; v != nil { + params.Set("pretty", fmt.Sprint(*v)) + } + if v := s.human; v != nil { + params.Set("human", fmt.Sprint(*v)) + } + if v := s.errorTrace; v != nil { + params.Set("error_trace", fmt.Sprint(*v)) + } + if len(s.filterPath) > 0 { + params.Set("filter_path", strings.Join(s.filterPath, ",")) + } + if s.timeout != "" { + params.Set("timeout", s.timeout) + } + if s.masterTimeout != "" { + params.Set("master_timeout", s.masterTimeout) + } + return path, params, nil +} + +// Validate checks if the operation is valid. +func (s *IndicesDeleteComponentTemplateService) Validate() error { + var invalid []string + if s.name == "" { + invalid = append(invalid, "Name") + } + if len(invalid) > 0 { + return fmt.Errorf("missing required fields: %v", invalid) + } + return nil +} + +// Do executes the operation. +func (s *IndicesDeleteComponentTemplateService) Do(ctx context.Context) (*IndicesDeleteComponentTemplateResponse, error) { + // Check pre-conditions + if err := s.Validate(); err != nil { + return nil, err + } + + // Get URL for request + path, params, err := s.buildURL() + if err != nil { + return nil, err + } + + // Get HTTP response + res, err := s.client.PerformRequest(ctx, PerformRequestOptions{ + Method: "DELETE", + Path: path, + Params: params, + Headers: s.headers, + }) + if err != nil { + return nil, err + } + + // Return operation response + ret := new(IndicesDeleteComponentTemplateResponse) + if err := s.client.decoder.Decode(res.Body, ret); err != nil { + return nil, err + } + return ret, nil +} + +// IndicesDeleteComponentTemplateResponse is the response of IndicesDeleteComponentTemplateService.Do. +type IndicesDeleteComponentTemplateResponse struct { + Acknowledged bool `json:"acknowledged"` + ShardsAcknowledged bool `json:"shards_acknowledged"` + Index string `json:"index,omitempty"` +} diff --git a/indices_get_component_template.go b/indices_get_component_template.go new file mode 100644 index 000000000..d3d2d71aa --- /dev/null +++ b/indices_get_component_template.go @@ -0,0 +1,207 @@ +// Copyright 2012-present Oliver Eilhard. All rights reserved. +// Use of this source code is governed by a MIT-license. +// See http://olivere.mit-license.org/license.txt for details. + +package elastic + +import ( + "context" + "fmt" + "net/http" + "net/url" + "strings" + + "github.com/olivere/elastic/v7/uritemplates" +) + +// IndicesGetComponentTemplateService returns a component template. +// +// See https://www.elastic.co/guide/en/elasticsearch/reference/7.10/getting-component-templates.html +// for more details. +type IndicesGetComponentTemplateService struct { + client *Client + + pretty *bool // pretty format the returned JSON response + human *bool // return human readable values for statistics + errorTrace *bool // include the stack trace of returned errors + filterPath []string // list of filters used to reduce the response + headers http.Header // custom request-level HTTP headers + + name []string + masterTimeout string + flatSettings *bool + local *bool +} + +// NewIndicesGetComponentTemplateService creates a new IndicesGetComponentTemplateService. +func NewIndicesGetComponentTemplateService(client *Client) *IndicesGetComponentTemplateService { + return &IndicesGetComponentTemplateService{ + client: client, + name: make([]string, 0), + } +} + +// Pretty tells Elasticsearch whether to return a formatted JSON response. +func (s *IndicesGetComponentTemplateService) Pretty(pretty bool) *IndicesGetComponentTemplateService { + s.pretty = &pretty + return s +} + +// Human specifies whether human readable values should be returned in +// the JSON response, e.g. "7.5mb". +func (s *IndicesGetComponentTemplateService) Human(human bool) *IndicesGetComponentTemplateService { + s.human = &human + return s +} + +// ErrorTrace specifies whether to include the stack trace of returned errors. +func (s *IndicesGetComponentTemplateService) ErrorTrace(errorTrace bool) *IndicesGetComponentTemplateService { + s.errorTrace = &errorTrace + return s +} + +// FilterPath specifies a list of filters used to reduce the response. +func (s *IndicesGetComponentTemplateService) FilterPath(filterPath ...string) *IndicesGetComponentTemplateService { + s.filterPath = filterPath + return s +} + +// Header adds a header to the request. +func (s *IndicesGetComponentTemplateService) Header(name string, value string) *IndicesGetComponentTemplateService { + if s.headers == nil { + s.headers = http.Header{} + } + s.headers.Add(name, value) + return s +} + +// Headers specifies the headers of the request. +func (s *IndicesGetComponentTemplateService) Headers(headers http.Header) *IndicesGetComponentTemplateService { + s.headers = headers + return s +} + +// Name is the name of the component template. +func (s *IndicesGetComponentTemplateService) Name(name ...string) *IndicesGetComponentTemplateService { + s.name = append(s.name, name...) + return s +} + +// FlatSettings is returns settings in flat format (default: false). +func (s *IndicesGetComponentTemplateService) FlatSettings(flatSettings bool) *IndicesGetComponentTemplateService { + s.flatSettings = &flatSettings + return s +} + +// Local indicates whether to return local information, i.e. do not retrieve +// the state from master node (default: false). +func (s *IndicesGetComponentTemplateService) Local(local bool) *IndicesGetComponentTemplateService { + s.local = &local + return s +} + +// MasterTimeout specifies the timeout for connection to master. +func (s *IndicesGetComponentTemplateService) MasterTimeout(masterTimeout string) *IndicesGetComponentTemplateService { + s.masterTimeout = masterTimeout + return s +} + +// buildURL builds the URL for the operation. +func (s *IndicesGetComponentTemplateService) buildURL() (string, url.Values, error) { + // Build URL + var err error + var path string + if len(s.name) > 0 { + path, err = uritemplates.Expand("/_component_template/{name}", map[string]string{ + "name": strings.Join(s.name, ","), + }) + } else { + path = "/_component_template" + } + if err != nil { + return "", url.Values{}, err + } + + // Add query string parameters + params := url.Values{} + if v := s.pretty; v != nil { + params.Set("pretty", fmt.Sprint(*v)) + } + if v := s.human; v != nil { + params.Set("human", fmt.Sprint(*v)) + } + if v := s.errorTrace; v != nil { + params.Set("error_trace", fmt.Sprint(*v)) + } + if len(s.filterPath) > 0 { + params.Set("filter_path", strings.Join(s.filterPath, ",")) + } + if s.flatSettings != nil { + params.Set("flat_settings", fmt.Sprintf("%v", *s.flatSettings)) + } + if s.local != nil { + params.Set("local", fmt.Sprintf("%v", *s.local)) + } + if s.masterTimeout != "" { + params.Set("master_timeout", s.masterTimeout) + } + return path, params, nil +} + +// Validate checks if the operation is valid. +func (s *IndicesGetComponentTemplateService) Validate() error { + return nil +} + +// Do executes the operation. +func (s *IndicesGetComponentTemplateService) Do(ctx context.Context) (*IndicesGetComponentTemplateResponse, error) { + // Check pre-conditions + if err := s.Validate(); err != nil { + return nil, err + } + + // Get URL for request + path, params, err := s.buildURL() + if err != nil { + return nil, err + } + + // Get HTTP response + res, err := s.client.PerformRequest(ctx, PerformRequestOptions{ + Method: "GET", + Path: path, + Params: params, + Headers: s.headers, + }) + if err != nil { + return nil, err + } + + // Return operation response + var ret *IndicesGetComponentTemplateResponse + if err := s.client.decoder.Decode(res.Body, &ret); err != nil { + return nil, err + } + return ret, nil +} + +// IndicesGetComponentTemplateResponse is the response of IndicesGetComponentTemplateService.Do. +type IndicesGetComponentTemplateResponse struct { + ComponentTemplates []IndicesGetComponentTemplates `json:"component_templates"` +} + +type IndicesGetComponentTemplates struct { + Name string `json:"name"` + ComponentTemplate *IndicesGetComponentTemplate `json:"component_template"` +} + +type IndicesGetComponentTemplate struct { + Version int `json:"version,omitempty"` + Template *IndicesGetComponentTemplateData `json:"template,omitempty"` +} + +type IndicesGetComponentTemplateData struct { + Settings map[string]interface{} `json:"settings,omitempty"` + Mappings map[string]interface{} `json:"mappings,omitempty"` + Aliases map[string]interface{} `json:"aliases,omitempty"` +} diff --git a/indices_put_component_template.go b/indices_put_component_template.go new file mode 100644 index 000000000..ec6b93d15 --- /dev/null +++ b/indices_put_component_template.go @@ -0,0 +1,221 @@ +// Copyright 2012-present Oliver Eilhard. All rights reserved. +// Use of this source code is governed by a MIT-license. +// See http://olivere.mit-license.org/license.txt for details. + +package elastic + +import ( + "context" + "fmt" + "net/http" + "net/url" + "strings" + + "github.com/olivere/elastic/v7/uritemplates" +) + +// IndicesPutComponentTemplateService creates or updates component templates. +// +// See https://www.elastic.co/guide/en/elasticsearch/reference/7.10/indices-component-template.html +// for more details on this API. +type IndicesPutComponentTemplateService struct { + client *Client + + pretty *bool // pretty format the returned JSON response + human *bool // return human readable values for statistics + errorTrace *bool // include the stack trace of returned errors + filterPath []string // list of filters used to reduce the response + headers http.Header // custom request-level HTTP headers + + name string + create *bool + cause string + masterTimeout string + + bodyJson interface{} + bodyString string +} + +// NewIndicesPutComponentTemplateService creates a new IndicesPutComponentTemplateService. +func NewIndicesPutComponentTemplateService(client *Client) *IndicesPutComponentTemplateService { + return &IndicesPutComponentTemplateService{ + client: client, + } +} + +// Pretty tells Elasticsearch whether to return a formatted JSON response. +func (s *IndicesPutComponentTemplateService) Pretty(pretty bool) *IndicesPutComponentTemplateService { + s.pretty = &pretty + return s +} + +// Human specifies whether human readable values should be returned in +// the JSON response, e.g. "7.5mb". +func (s *IndicesPutComponentTemplateService) Human(human bool) *IndicesPutComponentTemplateService { + s.human = &human + return s +} + +// ErrorTrace specifies whether to include the stack trace of returned errors. +func (s *IndicesPutComponentTemplateService) ErrorTrace(errorTrace bool) *IndicesPutComponentTemplateService { + s.errorTrace = &errorTrace + return s +} + +// FilterPath specifies a list of filters used to reduce the response. +func (s *IndicesPutComponentTemplateService) FilterPath(filterPath ...string) *IndicesPutComponentTemplateService { + s.filterPath = filterPath + return s +} + +// Header adds a header to the request. +func (s *IndicesPutComponentTemplateService) Header(name string, value string) *IndicesPutComponentTemplateService { + if s.headers == nil { + s.headers = http.Header{} + } + s.headers.Add(name, value) + return s +} + +// Headers specifies the headers of the request. +func (s *IndicesPutComponentTemplateService) Headers(headers http.Header) *IndicesPutComponentTemplateService { + s.headers = headers + return s +} + +// Name is the name of the component template. +func (s *IndicesPutComponentTemplateService) Name(name string) *IndicesPutComponentTemplateService { + s.name = name + return s +} + +// Create indicates whether the component template should only be added if +// new or can also replace an existing one. +func (s *IndicesPutComponentTemplateService) Create(create bool) *IndicesPutComponentTemplateService { + s.create = &create + return s +} + +// Cause is the user-defined reason for creating/updating the the component template. +func (s *IndicesPutComponentTemplateService) Cause(cause string) *IndicesPutComponentTemplateService { + s.cause = cause + return s +} + +// MasterTimeout specifies the timeout for connection to master. +func (s *IndicesPutComponentTemplateService) MasterTimeout(masterTimeout string) *IndicesPutComponentTemplateService { + s.masterTimeout = masterTimeout + return s +} + +// BodyJson is the component template definition as a JSON serializable +// type, e.g. map[string]interface{}. +func (s *IndicesPutComponentTemplateService) BodyJson(body interface{}) *IndicesPutComponentTemplateService { + s.bodyJson = body + return s +} + +// BodyString is the component template definition as a raw string. +func (s *IndicesPutComponentTemplateService) BodyString(body string) *IndicesPutComponentTemplateService { + s.bodyString = body + return s +} + +// buildURL builds the URL for the operation. +func (s *IndicesPutComponentTemplateService) buildURL() (string, url.Values, error) { + // Build URL + path, err := uritemplates.Expand("/_component_template/{name}", map[string]string{ + "name": s.name, + }) + if err != nil { + return "", url.Values{}, err + } + + // Add query string parameters + params := url.Values{} + if v := s.pretty; v != nil { + params.Set("pretty", fmt.Sprint(*v)) + } + if v := s.human; v != nil { + params.Set("human", fmt.Sprint(*v)) + } + if v := s.errorTrace; v != nil { + params.Set("error_trace", fmt.Sprint(*v)) + } + if len(s.filterPath) > 0 { + params.Set("filter_path", strings.Join(s.filterPath, ",")) + } + if s.create != nil { + params.Set("create", fmt.Sprint(*s.create)) + } + if s.cause != "" { + params.Set("cause", s.cause) + } + if s.masterTimeout != "" { + params.Set("master_timeout", s.masterTimeout) + } + return path, params, nil +} + +// Validate checks if the operation is valid. +func (s *IndicesPutComponentTemplateService) Validate() error { + var invalid []string + if s.name == "" { + invalid = append(invalid, "Name") + } + if s.bodyString == "" && s.bodyJson == nil { + invalid = append(invalid, "BodyJson") + } + if len(invalid) > 0 { + return fmt.Errorf("missing required fields: %v", invalid) + } + return nil +} + +// Do executes the operation. +func (s *IndicesPutComponentTemplateService) Do(ctx context.Context) (*IndicesPutComponentTemplateResponse, error) { + // Check pre-conditions + if err := s.Validate(); err != nil { + return nil, err + } + + // Get URL for request + path, params, err := s.buildURL() + if err != nil { + return nil, err + } + + // Setup HTTP request body + var body interface{} + if s.bodyJson != nil { + body = s.bodyJson + } else { + body = s.bodyString + } + + // Get HTTP response + res, err := s.client.PerformRequest(ctx, PerformRequestOptions{ + Method: "PUT", + Path: path, + Params: params, + Body: body, + Headers: s.headers, + }) + if err != nil { + return nil, err + } + + // Return operation response + ret := new(IndicesPutComponentTemplateResponse) + if err := s.client.decoder.Decode(res.Body, ret); err != nil { + return nil, err + } + return ret, nil +} + +// IndicesPutComponentTemplateResponse is the response of IndicesPutComponentTemplateService.Do. +type IndicesPutComponentTemplateResponse struct { + Acknowledged bool `json:"acknowledged"` + ShardsAcknowledged bool `json:"shards_acknowledged"` + Index string `json:"index,omitempty"` +}