Skip to content

Commit 7c24cfa

Browse files
kaisechengyaauie
andauthored
Support legacy template api in elasticsearch 8 (#1092)
This commit adds a new flag template_api to control which API to use. The available value is auto, legacy and composable. The default value is auto. Fixed: #1088 Co-authored-by: Ry Biesemeyer <ry.biesemeyer@elastic.co>
1 parent 97ef7ed commit 7c24cfa

File tree

8 files changed

+106
-34
lines changed

8 files changed

+106
-34
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 11.12.0
2+
- Add legacy template API support for Elasticsearch 8 [#1092](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/1092)
3+
14
## 11.11.0
25
- When using an `api_key` along with either `cloud_id` or https `hosts`, you no longer need to also specify `ssl => true` [#1065](https://github.com/logstash-plugins/logstash-output-elasticsearch/issues/1065)
36

docs/index.asciidoc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ This plugin supports the following configuration options plus the
362362
| <<plugins-{type}s-{plugin}-ssl_certificate_verification>> |<<boolean,boolean>>|No
363363
| <<plugins-{type}s-{plugin}-ssl_supported_protocols>> |<<string,string>>|No
364364
| <<plugins-{type}s-{plugin}-template>> |a valid filesystem path|No
365+
| <<plugins-{type}s-{plugin}-template_api>> |<<string,string>>, one of `["auto", "legacy", "composable"]`|No
365366
| <<plugins-{type}s-{plugin}-template_name>> |<<string,string>>|No
366367
| <<plugins-{type}s-{plugin}-template_overwrite>> |<<boolean,boolean>>|No
367368
| <<plugins-{type}s-{plugin}-timeout>> |<<number,number>>|No
@@ -1080,6 +1081,22 @@ the *$JDK_HOME/conf/security/java.security* configuration file. That is, `TLSv1.
10801081
You can set the path to your own template here, if you so desire.
10811082
If not set, the included template will be used.
10821083

1084+
[id="plugins-{type}s-{plugin}-template_api"]
1085+
===== `template_api`
1086+
1087+
* Value can be any of: `auto`, `legacy`, `composable`
1088+
* Default value is `auto`
1089+
1090+
The default setting of `auto` will use
1091+
{ref}/index-templates.html[index template API] to create index template, if the
1092+
Elasticsearch cluster is running Elasticsearch version `8.0.0` or higher,
1093+
and use {ref}/indices-templates-v1.html[legacy template API] otherwise.
1094+
1095+
Setting this flag to `legacy` will use legacy template API to create index template.
1096+
Setting this flag to `composable` will use index template API to create index template.
1097+
1098+
NOTE: The format of template provided to <<plugins-{type}s-{plugin}-template>> needs to match the template API being used.
1099+
10831100
[id="plugins-{type}s-{plugin}-template_name"]
10841101
===== `template_name`
10851102

lib/logstash/outputs/elasticsearch.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,11 @@ class LogStash::Outputs::ElasticSearch < LogStash::Outputs::Base
185185
# the "logstash" template (i.e. removing all customized settings)
186186
config :template_overwrite, :validate => :boolean, :default => false
187187

188+
# Flag for enabling legacy template api for Elasticsearch 8
189+
# Default auto will use index template api for Elasticsearch 8 and use legacy api for 7
190+
# Set to legacy to use legacy template api
191+
config :template_api, :validate => ['auto', 'legacy', 'composable'], :default => 'auto'
192+
188193
# The version to use for indexing. Use sprintf syntax like `%{my_version}` to use a field value here.
189194
# See https://www.elastic.co/blog/elasticsearch-versioning-support.
190195
config :version, :validate => :string

lib/logstash/outputs/elasticsearch/http_client.rb

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,12 @@ def build_url_template
7777
}
7878
end
7979

80-
def template_install(name, template, force=false)
81-
if template_exists?(name) && !force
80+
def template_install(template_endpoint, name, template, force=false)
81+
if template_exists?(template_endpoint, name) && !force
8282
@logger.debug("Found existing Elasticsearch template, skipping template management", name: name)
8383
return
8484
end
85-
template_put(name, template)
85+
template_put(template_endpoint, name, template)
8686
end
8787

8888
def last_es_version
@@ -402,20 +402,16 @@ def exists?(path, use_get=false)
402402
response.code >= 200 && response.code <= 299
403403
end
404404

405-
def template_exists?(name)
405+
def template_exists?(template_endpoint, name)
406406
exists?("/#{template_endpoint}/#{name}")
407407
end
408408

409-
def template_put(name, template)
409+
def template_put(template_endpoint, name, template)
410410
path = "#{template_endpoint}/#{name}"
411411
logger.info("Installing Elasticsearch template", name: name)
412412
@pool.put(path, nil, LogStash::Json.dump(template))
413413
end
414414

415-
def template_endpoint
416-
maximum_seen_major_version < 8 ? '_template' : '_index_template'
417-
end
418-
419415
# ILM methods
420416

421417
# check whether rollover alias already exists

lib/logstash/outputs/elasticsearch/template_manager.rb

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
module LogStash; module Outputs; class ElasticSearch
22
class TemplateManager
3+
LEGACY_TEMPLATE_ENDPOINT = '_template'.freeze
4+
INDEX_TEMPLATE_ENDPOINT = '_index_template'.freeze
5+
36
# To be mixed into the elasticsearch plugin base
47
def self.install_template(plugin)
58
return unless plugin.manage_template
9+
10+
if plugin.maximum_seen_major_version < 8 && plugin.template_api == 'auto'
11+
plugin.logger.warn("`template_api => auto` resolved to `legacy` since we are connected to " + "Elasticsearch #{plugin.maximum_seen_major_version}, " +
12+
"but will resolve to `composable` the first time it connects to Elasticsearch 8+. " +
13+
"We recommend either setting `template_api => legacy` to continue providing legacy-style templates, " +
14+
"or migrating your template to the composable style and setting `template_api => composable`. " +
15+
"The legacy template API is slated for removal in Elasticsearch 9.")
16+
end
17+
618
if plugin.template
719
plugin.logger.info("Using mapping template from", :path => plugin.template)
820
template = read_template_file(plugin.template)
@@ -14,7 +26,7 @@ def self.install_template(plugin)
1426

1527
add_ilm_settings_to_template(plugin, template) if plugin.ilm_in_use?
1628
plugin.logger.debug("Attempting to install template", template: template)
17-
install(plugin.client, template_name(plugin), template, plugin.template_overwrite)
29+
install(plugin.client, template_endpoint(plugin), template_name(plugin), template, plugin.template_overwrite)
1830
end
1931

2032
private
@@ -25,8 +37,8 @@ def self.load_default_template(es_major_version, ecs_compatibility)
2537
fail "Failed to load default template for Elasticsearch v#{es_major_version} with ECS #{ecs_compatibility}; caused by: #{e.inspect}"
2638
end
2739

28-
def self.install(client, template_name, template, template_overwrite)
29-
client.template_install(template_name, template, template_overwrite)
40+
def self.install(client, template_endpoint, template_name, template, template_overwrite)
41+
client.template_install(template_endpoint, template_name, template, template_overwrite)
3042
end
3143

3244
def self.add_ilm_settings_to_template(plugin, template)
@@ -63,5 +75,16 @@ def self.read_template_file(template_path)
6375
template_data = ::IO.read(template_path)
6476
LogStash::Json.load(template_data)
6577
end
78+
79+
def self.template_endpoint(plugin)
80+
if plugin.template_api == 'auto'
81+
plugin.maximum_seen_major_version < 8 ? LEGACY_TEMPLATE_ENDPOINT : INDEX_TEMPLATE_ENDPOINT
82+
elsif plugin.template_api.to_s == 'legacy'
83+
LEGACY_TEMPLATE_ENDPOINT
84+
else
85+
INDEX_TEMPLATE_ENDPOINT
86+
end
87+
end
88+
6689
end
6790
end end end

logstash-output-elasticsearch.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Gem::Specification.new do |s|
22
s.name = 'logstash-output-elasticsearch'
3-
s.version = '11.11.0'
3+
s.version = '11.12.0'
44
s.licenses = ['apache-2.0']
55
s.summary = "Stores logs in Elasticsearch"
66
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"

spec/unit/outputs/elasticsearch/http_client_spec.rb

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -140,27 +140,6 @@
140140
end
141141
end
142142

143-
describe "index template" do
144-
subject { described_class.new(base_options) }
145-
let(:template_name) { "logstash" }
146-
let(:template) { {} }
147-
let(:get_response) {
148-
double("response", :body => {})
149-
}
150-
151-
it "should call composable index template in version 8+" do
152-
expect(subject).to receive(:maximum_seen_major_version).and_return(8)
153-
expect(subject.pool).to receive(:put).with("_index_template/#{template_name}", nil, anything).and_return(get_response)
154-
subject.template_put(template_name, template)
155-
end
156-
157-
it "should call index template in version < 8" do
158-
expect(subject).to receive(:maximum_seen_major_version).and_return(7)
159-
expect(subject.pool).to receive(:put).with("_template/#{template_name}", nil, anything).and_return(get_response)
160-
subject.template_put(template_name, template)
161-
end
162-
end
163-
164143
describe "join_bulk_responses" do
165144
subject { described_class.new(base_options) }
166145

spec/unit/outputs/elasticsearch/template_manager_spec.rb

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,53 @@
6363
end
6464
end
6565
end
66+
67+
describe "template endpoint" do
68+
describe "template_api => 'auto'" do
69+
let(:plugin_settings) { {"manage_template" => true, "template_api" => 'auto'} }
70+
let(:plugin) { LogStash::Outputs::ElasticSearch.new(plugin_settings) }
71+
72+
describe "in version 8+" do
73+
it "should use index template API" do
74+
expect(plugin).to receive(:maximum_seen_major_version).at_least(:once).and_return(8)
75+
endpoint = described_class.template_endpoint(plugin)
76+
expect(endpoint).to be_equal(LogStash::Outputs::ElasticSearch::TemplateManager::INDEX_TEMPLATE_ENDPOINT)
77+
end
78+
end
79+
80+
describe "in version < 8" do
81+
it "should use legacy template API" do
82+
expect(plugin).to receive(:maximum_seen_major_version).at_least(:once).and_return(7)
83+
endpoint = described_class.template_endpoint(plugin)
84+
expect(endpoint).to be_equal(LogStash::Outputs::ElasticSearch::TemplateManager::LEGACY_TEMPLATE_ENDPOINT)
85+
end
86+
end
87+
end
88+
89+
describe "template_api => 'legacy'" do
90+
let(:plugin_settings) { {"manage_template" => true, "template_api" => 'legacy'} }
91+
let(:plugin) { LogStash::Outputs::ElasticSearch.new(plugin_settings) }
92+
93+
describe "in version 8+" do
94+
it "should use legacy template API" do
95+
expect(plugin).to receive(:maximum_seen_major_version).never
96+
endpoint = described_class.template_endpoint(plugin)
97+
expect(endpoint).to be_equal(LogStash::Outputs::ElasticSearch::TemplateManager::LEGACY_TEMPLATE_ENDPOINT)
98+
end
99+
end
100+
end
101+
102+
describe "template_api => 'composable'" do
103+
let(:plugin_settings) { {"manage_template" => true, "template_api" => 'composable'} }
104+
let(:plugin) { LogStash::Outputs::ElasticSearch.new(plugin_settings) }
105+
106+
describe "in version 8+" do
107+
it "should use legacy template API" do
108+
expect(plugin).to receive(:maximum_seen_major_version).never
109+
endpoint = described_class.template_endpoint(plugin)
110+
expect(endpoint).to be_equal(LogStash::Outputs::ElasticSearch::TemplateManager:: INDEX_TEMPLATE_ENDPOINT)
111+
end
112+
end
113+
end
114+
end
66115
end

0 commit comments

Comments
 (0)