logstash-output-elasticsearch 9.2.4-java → 9.3.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/docs/index.asciidoc +104 -2
- data/lib/logstash/outputs/elasticsearch.rb +4 -0
- data/lib/logstash/outputs/elasticsearch/common.rb +8 -5
- data/lib/logstash/outputs/elasticsearch/common_configs.rb +23 -1
- data/lib/logstash/outputs/elasticsearch/default-ilm-policy.json +14 -0
- data/lib/logstash/outputs/elasticsearch/http_client.rb +47 -2
- data/lib/logstash/outputs/elasticsearch/http_client/manticore_adapter.rb +3 -3
- data/lib/logstash/outputs/elasticsearch/ilm.rb +84 -0
- data/lib/logstash/outputs/elasticsearch/template_manager.rb +21 -1
- data/logstash-output-elasticsearch.gemspec +1 -1
- data/spec/es_spec_helper.rb +70 -0
- data/spec/fixtures/template-with-policy-es6x.json +48 -0
- data/spec/fixtures/template-with-policy-es7x.json +46 -0
- data/spec/integration/outputs/create_spec.rb +1 -1
- data/spec/integration/outputs/ilm_spec.rb +542 -0
- data/spec/integration/outputs/ingest_pipeline_spec.rb +2 -2
- data/spec/integration/outputs/no_es_on_startup_spec.rb +2 -2
- data/spec/integration/outputs/retry_spec.rb +3 -3
- data/spec/integration/outputs/templates_5x_spec.rb +7 -7
- data/spec/integration/outputs/templates_spec.rb +7 -7
- data/spec/support/elasticsearch/api/actions/delete_ilm_policy.rb +19 -0
- data/spec/support/elasticsearch/api/actions/get_alias.rb +18 -0
- data/spec/support/elasticsearch/api/actions/get_ilm_policy.rb +18 -0
- data/spec/support/elasticsearch/api/actions/put_alias.rb +24 -0
- data/spec/support/elasticsearch/api/actions/put_ilm_policy.rb +25 -0
- metadata +20 -2
@@ -5,8 +5,9 @@ module LogStash; module Outputs; class ElasticSearch
|
|
5
5
|
return unless plugin.manage_template
|
6
6
|
plugin.logger.info("Using mapping template from", :path => plugin.template)
|
7
7
|
template = get_template(plugin.template, plugin.maximum_seen_major_version)
|
8
|
+
add_ilm_settings_to_template(plugin, template) if plugin.ilm_enabled?
|
8
9
|
plugin.logger.info("Attempting to install template", :manage_template => template)
|
9
|
-
install(plugin.client, plugin
|
10
|
+
install(plugin.client, template_name(plugin), template, plugin.template_overwrite)
|
10
11
|
rescue => e
|
11
12
|
plugin.logger.error("Failed to install template.", :message => e.message, :class => e.class.name, :backtrace => e.backtrace)
|
12
13
|
end
|
@@ -21,6 +22,25 @@ module LogStash; module Outputs; class ElasticSearch
|
|
21
22
|
client.template_install(template_name, template, template_overwrite)
|
22
23
|
end
|
23
24
|
|
25
|
+
def self.add_ilm_settings_to_template(plugin, template)
|
26
|
+
plugin.logger.info("Overwriting index patterns, as ILM is enabled.")
|
27
|
+
# Overwrite any index patterns, and use the rollover alias. Use 'index_patterns' rather than 'template' for pattern
|
28
|
+
# definition - remove any existing definition of 'template'
|
29
|
+
template.delete('template') if template.include?('template')
|
30
|
+
template['index_patterns'] = "#{plugin.ilm_rollover_alias}-*"
|
31
|
+
if template['settings'] && (template['settings']['index.lifecycle.name'] || template['settings']['index.lifecycle.rollover_alias'])
|
32
|
+
plugin.logger.info("Overwriting index lifecycle name and rollover alias as ILM is enabled.")
|
33
|
+
end
|
34
|
+
template['settings'].update({ 'index.lifecycle.name' => plugin.ilm_policy, 'index.lifecycle.rollover_alias' => plugin.ilm_rollover_alias})
|
35
|
+
end
|
36
|
+
|
37
|
+
# Template name - if template_name set, use it
|
38
|
+
# if not and ILM is enabled, use the rollover alias
|
39
|
+
# else use the default value of template_name
|
40
|
+
def self.template_name(plugin)
|
41
|
+
plugin.ilm_enabled? && !plugin.original_params.key?('template_name') ? plugin.ilm_rollover_alias : plugin.template_name
|
42
|
+
end
|
43
|
+
|
24
44
|
def self.default_template_path(es_major_version)
|
25
45
|
template_version = es_major_version == 1 ? 2 : es_major_version
|
26
46
|
default_template_name = "elasticsearch-template-es#{template_version}x.json"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-output-elasticsearch'
|
3
|
-
s.version = '9.
|
3
|
+
s.version = '9.3.0'
|
4
4
|
s.licenses = ['apache-2.0']
|
5
5
|
s.summary = "Stores logs in Elasticsearch"
|
6
6
|
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"
|
data/spec/es_spec_helper.rb
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
require "logstash/devutils/rspec/spec_helper"
|
2
2
|
require 'manticore'
|
3
3
|
require 'elasticsearch'
|
4
|
+
require_relative "support/elasticsearch/api/actions/delete_ilm_policy"
|
5
|
+
require_relative "support/elasticsearch/api/actions/get_alias"
|
6
|
+
require_relative "support/elasticsearch/api/actions/put_alias"
|
7
|
+
require_relative "support/elasticsearch/api/actions/get_ilm_policy"
|
8
|
+
require_relative "support/elasticsearch/api/actions/put_ilm_policy"
|
9
|
+
|
10
|
+
require 'json'
|
4
11
|
|
5
12
|
module ESHelper
|
6
13
|
def get_host_port
|
@@ -19,6 +26,10 @@ module ESHelper
|
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
29
|
+
def todays_date
|
30
|
+
Time.now.strftime("%Y.%m.%d")
|
31
|
+
end
|
32
|
+
|
22
33
|
def mapping_name
|
23
34
|
if ESHelper.es_version_satisfies?(">=7")
|
24
35
|
"_doc"
|
@@ -40,6 +51,17 @@ module ESHelper
|
|
40
51
|
RSpec.configuration.filter[:es_version] || ENV['ES_VERSION']
|
41
52
|
end
|
42
53
|
|
54
|
+
RSpec::Matchers.define :have_hits do |expected|
|
55
|
+
match do |actual|
|
56
|
+
if ESHelper.es_version_satisfies?(">=7")
|
57
|
+
expected == actual['hits']['total']['value']
|
58
|
+
else
|
59
|
+
expected == actual['hits']['total']
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
43
65
|
def self.es_version_satisfies?(*requirement)
|
44
66
|
es_version = RSpec.configuration.filter[:es_version] || ENV['ES_VERSION']
|
45
67
|
if es_version.nil?
|
@@ -49,6 +71,54 @@ module ESHelper
|
|
49
71
|
es_release_version = Gem::Version.new(es_version).release
|
50
72
|
Gem::Requirement.new(requirement).satisfied_by?(es_release_version)
|
51
73
|
end
|
74
|
+
|
75
|
+
def clean(client)
|
76
|
+
client.indices.delete_template(:name => "*")
|
77
|
+
# This can fail if there are no indexes, ignore failure.
|
78
|
+
client.indices.delete(:index => "*") rescue nil
|
79
|
+
clean_ilm(client) if supports_ilm?(client)
|
80
|
+
end
|
81
|
+
|
82
|
+
def set_cluster_settings(client, cluster_settings)
|
83
|
+
client.cluster.put_settings(body: cluster_settings)
|
84
|
+
get_cluster_settings(client)
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_cluster_settings(client)
|
88
|
+
client.cluster.get_settings
|
89
|
+
end
|
90
|
+
|
91
|
+
def get_policy(client, policy_name)
|
92
|
+
client.get_ilm_policy(name: policy_name)
|
93
|
+
end
|
94
|
+
|
95
|
+
def put_policy(client, policy_name, policy)
|
96
|
+
client.put_ilm_policy({:name => policy_name, :body=> policy})
|
97
|
+
end
|
98
|
+
|
99
|
+
def put_alias(client, the_alias, index)
|
100
|
+
body = {
|
101
|
+
"aliases" => {
|
102
|
+
index => {
|
103
|
+
"is_write_index"=> true
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}
|
107
|
+
client.put_alias({name: the_alias, body: body})
|
108
|
+
end
|
109
|
+
|
110
|
+
def clean_ilm(client)
|
111
|
+
client.get_ilm_policy.each_key {|key| client.delete_ilm_policy(name: key)}
|
112
|
+
end
|
113
|
+
|
114
|
+
def supports_ilm?(client)
|
115
|
+
begin
|
116
|
+
client.get_ilm_policy
|
117
|
+
true
|
118
|
+
rescue
|
119
|
+
false
|
120
|
+
end
|
121
|
+
end
|
52
122
|
end
|
53
123
|
|
54
124
|
RSpec.configure do |config|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
{
|
2
|
+
"template" : "overwrite-*",
|
3
|
+
"version" : 60001,
|
4
|
+
"settings" : {
|
5
|
+
"index.refresh_interval" : "1s",
|
6
|
+
"number_of_shards": 1,
|
7
|
+
"index.lifecycle.name": "overwrite-policy",
|
8
|
+
"index.lifecycle.rollover_alias": "overwrite"
|
9
|
+
},
|
10
|
+
"mappings" : {
|
11
|
+
"_default_" : {
|
12
|
+
"dynamic_templates" : [ {
|
13
|
+
"message_field" : {
|
14
|
+
"path_match" : "message",
|
15
|
+
"match_mapping_type" : "string",
|
16
|
+
"mapping" : {
|
17
|
+
"type" : "text",
|
18
|
+
"norms" : false
|
19
|
+
}
|
20
|
+
}
|
21
|
+
}, {
|
22
|
+
"string_fields" : {
|
23
|
+
"match" : "*",
|
24
|
+
"match_mapping_type" : "string",
|
25
|
+
"mapping" : {
|
26
|
+
"type" : "text", "norms" : false,
|
27
|
+
"fields" : {
|
28
|
+
"keyword" : { "type": "keyword", "ignore_above": 256 }
|
29
|
+
}
|
30
|
+
}
|
31
|
+
}
|
32
|
+
} ],
|
33
|
+
"properties" : {
|
34
|
+
"@timestamp": { "type": "date"},
|
35
|
+
"@version": { "type": "keyword"},
|
36
|
+
"geoip" : {
|
37
|
+
"dynamic": true,
|
38
|
+
"properties" : {
|
39
|
+
"ip": { "type": "ip" },
|
40
|
+
"location" : { "type" : "geo_point" },
|
41
|
+
"latitude" : { "type" : "half_float" },
|
42
|
+
"longitude" : { "type" : "half_float" }
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
{
|
2
|
+
"index_patterns" : "overwrite-*",
|
3
|
+
"version" : 60001,
|
4
|
+
"settings" : {
|
5
|
+
"index.refresh_interval" : "1s",
|
6
|
+
"number_of_shards": 1
|
7
|
+
},
|
8
|
+
"mappings" : {
|
9
|
+
"_doc" : {
|
10
|
+
"dynamic_templates" : [ {
|
11
|
+
"message_field" : {
|
12
|
+
"path_match" : "message",
|
13
|
+
"match_mapping_type" : "string",
|
14
|
+
"mapping" : {
|
15
|
+
"type" : "text",
|
16
|
+
"norms" : false
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}, {
|
20
|
+
"string_fields" : {
|
21
|
+
"match" : "*",
|
22
|
+
"match_mapping_type" : "string",
|
23
|
+
"mapping" : {
|
24
|
+
"type" : "text", "norms" : false,
|
25
|
+
"fields" : {
|
26
|
+
"keyword" : { "type": "keyword", "ignore_above": 256 }
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
} ],
|
31
|
+
"properties" : {
|
32
|
+
"@timestamp": { "type": "date"},
|
33
|
+
"@version": { "type": "keyword"},
|
34
|
+
"geoip" : {
|
35
|
+
"dynamic": true,
|
36
|
+
"properties" : {
|
37
|
+
"ip": { "type": "ip" },
|
38
|
+
"location" : { "type" : "geo_point" },
|
39
|
+
"latitude" : { "type" : "half_float" },
|
40
|
+
"longitude" : { "type" : "half_float" }
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
}
|
@@ -0,0 +1,542 @@
|
|
1
|
+
require_relative "../../../spec/es_spec_helper"
|
2
|
+
|
3
|
+
shared_examples_for 'an Elasticsearch instance that does not support index lifecycle management' do
|
4
|
+
require "logstash/outputs/elasticsearch"
|
5
|
+
|
6
|
+
let (:ilm_enabled) { false }
|
7
|
+
let (:settings) {
|
8
|
+
{
|
9
|
+
"ilm_enabled" => ilm_enabled,
|
10
|
+
"hosts" => "#{get_host_port()}"
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
before :each do
|
15
|
+
require "elasticsearch"
|
16
|
+
|
17
|
+
# Clean ES of data before we start.
|
18
|
+
@es = get_client
|
19
|
+
clean(@es)
|
20
|
+
end
|
21
|
+
|
22
|
+
after :each do
|
23
|
+
clean(@es)
|
24
|
+
end
|
25
|
+
|
26
|
+
subject { LogStash::Outputs::ElasticSearch.new(settings) }
|
27
|
+
|
28
|
+
context 'when ilm is enabled in Logstash' do
|
29
|
+
let (:ilm_enabled) { true }
|
30
|
+
|
31
|
+
it 'should raise a configuration error' do
|
32
|
+
expect do
|
33
|
+
begin
|
34
|
+
subject.register
|
35
|
+
sleep(1)
|
36
|
+
ensure
|
37
|
+
subject.stop_template_installer
|
38
|
+
end
|
39
|
+
end.to raise_error(LogStash::ConfigurationError)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when ilm is disabled in Logstash' do
|
44
|
+
it 'should index documents normally' do
|
45
|
+
subject.register
|
46
|
+
|
47
|
+
subject.multi_receive([
|
48
|
+
LogStash::Event.new("message" => "sample message here"),
|
49
|
+
LogStash::Event.new("somemessage" => { "message" => "sample nested message here" }),
|
50
|
+
LogStash::Event.new("somevalue" => 100),
|
51
|
+
])
|
52
|
+
|
53
|
+
sleep(6)
|
54
|
+
|
55
|
+
subject.multi_receive([
|
56
|
+
LogStash::Event.new("country" => "us"),
|
57
|
+
LogStash::Event.new("country" => "at"),
|
58
|
+
LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0 ] })
|
59
|
+
])
|
60
|
+
|
61
|
+
@es.indices.refresh
|
62
|
+
|
63
|
+
# Wait or fail until everything's indexed.
|
64
|
+
Stud::try(20.times) do
|
65
|
+
r = @es.search
|
66
|
+
expect(r).to have_hits(6)
|
67
|
+
end
|
68
|
+
indexes_written = @es.search['hits']['hits'].each_with_object(Hash.new(0)) do |x, res|
|
69
|
+
index_written = x['_index']
|
70
|
+
res[index_written] += 1
|
71
|
+
end
|
72
|
+
expect(indexes_written.count).to eq(1)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
shared_examples_for 'an ILM enabled Logstash' do
|
79
|
+
|
80
|
+
context 'with a policy with a maximum number of documents' do
|
81
|
+
let (:policy) { small_max_doc_policy }
|
82
|
+
let (:ilm_policy_name) { "custom-policy"}
|
83
|
+
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
84
|
+
|
85
|
+
it 'should rollover when the policy max docs is reached' do
|
86
|
+
put_policy(@es,ilm_policy_name, policy)
|
87
|
+
subject.register
|
88
|
+
|
89
|
+
subject.multi_receive([
|
90
|
+
LogStash::Event.new("message" => "sample message here"),
|
91
|
+
LogStash::Event.new("somemessage" => { "message" => "sample nested message here" }),
|
92
|
+
LogStash::Event.new("somevalue" => 100),
|
93
|
+
])
|
94
|
+
|
95
|
+
sleep(6)
|
96
|
+
|
97
|
+
subject.multi_receive([
|
98
|
+
LogStash::Event.new("country" => "us"),
|
99
|
+
LogStash::Event.new("country" => "at"),
|
100
|
+
LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0 ] })
|
101
|
+
])
|
102
|
+
|
103
|
+
sleep(6)
|
104
|
+
|
105
|
+
subject.multi_receive([
|
106
|
+
LogStash::Event.new("country" => "uk"),
|
107
|
+
LogStash::Event.new("country" => "fr"),
|
108
|
+
LogStash::Event.new("geoip" => { "location" => [ 0.1, 1.0 ] })
|
109
|
+
])
|
110
|
+
|
111
|
+
@es.indices.refresh
|
112
|
+
|
113
|
+
# Wait or fail until everything's indexed.
|
114
|
+
Stud::try(20.times) do
|
115
|
+
r = @es.search
|
116
|
+
expect(r).to have_hits(9)
|
117
|
+
end
|
118
|
+
indexes_written = @es.search['hits']['hits'].each_with_object(Hash.new(0)) do |x, res|
|
119
|
+
index_written = x['_index']
|
120
|
+
res[index_written] += 1
|
121
|
+
end
|
122
|
+
expect(indexes_written.count).to eq(3)
|
123
|
+
expect(indexes_written["#{expected_index}-#{todays_date}-000001"]).to eq(3)
|
124
|
+
expect(indexes_written["#{expected_index}-#{todays_date}-000002"]).to eq(3)
|
125
|
+
expect(indexes_written["#{expected_index}-#{todays_date}-000003"]).to eq(3)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'with a policy where the maximum number of documents is not reached' do
|
130
|
+
let (:policy) { large_max_doc_policy }
|
131
|
+
let (:ilm_policy_name) { "custom-policy"}
|
132
|
+
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
133
|
+
|
134
|
+
it 'should ingest into a single index when max docs is not reached' do
|
135
|
+
put_policy(@es,ilm_policy_name, policy)
|
136
|
+
subject.register
|
137
|
+
|
138
|
+
subject.multi_receive([
|
139
|
+
LogStash::Event.new("message" => "sample message here"),
|
140
|
+
LogStash::Event.new("somemessage" => { "message" => "sample nested message here" }),
|
141
|
+
LogStash::Event.new("somevalue" => 100),
|
142
|
+
])
|
143
|
+
|
144
|
+
sleep(6)
|
145
|
+
|
146
|
+
subject.multi_receive([
|
147
|
+
LogStash::Event.new("country" => "us"),
|
148
|
+
LogStash::Event.new("country" => "at"),
|
149
|
+
LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0 ] })
|
150
|
+
])
|
151
|
+
|
152
|
+
@es.indices.refresh
|
153
|
+
|
154
|
+
# Wait or fail until everything's indexed.
|
155
|
+
Stud::try(20.times) do
|
156
|
+
r = @es.search
|
157
|
+
expect(r).to have_hits(6)
|
158
|
+
end
|
159
|
+
indexes_written = @es.search['hits']['hits'].each_with_object(Hash.new(0)) do |x, res|
|
160
|
+
index_written = x['_index']
|
161
|
+
res[index_written] += 1
|
162
|
+
end
|
163
|
+
expect(indexes_written.count).to eq(1)
|
164
|
+
expect(indexes_written["#{expected_index}-#{todays_date}-000001"]).to eq(6)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
if ESHelper.es_version_satisfies?("<= 6.5")
|
171
|
+
describe 'Pre-ILM versions of Elasticsearch', :integration => true do
|
172
|
+
it_behaves_like 'an Elasticsearch instance that does not support index lifecycle management'
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
if ESHelper.es_version_satisfies?(">= 6.6")
|
177
|
+
describe 'OSS Elasticsearch', :distribution => 'oss', :integration => true do
|
178
|
+
it_behaves_like 'an Elasticsearch instance that does not support index lifecycle management'
|
179
|
+
end
|
180
|
+
|
181
|
+
describe 'Elasticsearch has index lifecycle management enabled', :distribution => 'xpack', :integration => true do
|
182
|
+
DEFAULT_INTERVAL = '600s'
|
183
|
+
|
184
|
+
require "logstash/outputs/elasticsearch"
|
185
|
+
let (:ilm_enabled) { true }
|
186
|
+
|
187
|
+
let (:settings) {
|
188
|
+
{
|
189
|
+
"ilm_enabled" => ilm_enabled,
|
190
|
+
"hosts" => "#{get_host_port()}"
|
191
|
+
}
|
192
|
+
}
|
193
|
+
let (:policy) { small_max_doc_policy }
|
194
|
+
|
195
|
+
|
196
|
+
let (:small_max_doc_policy) {
|
197
|
+
{"policy" => {
|
198
|
+
"phases"=> {
|
199
|
+
"hot" => {
|
200
|
+
"actions" => {
|
201
|
+
"rollover" => {
|
202
|
+
"max_docs" => "3"
|
203
|
+
}
|
204
|
+
}
|
205
|
+
}
|
206
|
+
}
|
207
|
+
}}
|
208
|
+
}
|
209
|
+
|
210
|
+
let (:large_max_doc_policy) {
|
211
|
+
{"policy" => {
|
212
|
+
"phases"=> {
|
213
|
+
"hot" => {
|
214
|
+
"actions" => {
|
215
|
+
"rollover" => {
|
216
|
+
"max_docs" => "1000000"
|
217
|
+
}
|
218
|
+
}
|
219
|
+
}
|
220
|
+
}
|
221
|
+
}}
|
222
|
+
}
|
223
|
+
|
224
|
+
|
225
|
+
|
226
|
+
subject { LogStash::Outputs::ElasticSearch.new(settings) }
|
227
|
+
|
228
|
+
before :each do
|
229
|
+
# Delete all templates first.
|
230
|
+
require "elasticsearch"
|
231
|
+
|
232
|
+
# Clean ES of data before we start.
|
233
|
+
@es = get_client
|
234
|
+
clean(@es)
|
235
|
+
# Set the poll interval for lifecycle management to be short so changes get picked up in time.
|
236
|
+
set_cluster_settings(@es, {
|
237
|
+
"persistent" => {
|
238
|
+
"indices.lifecycle.poll_interval" => "1s"
|
239
|
+
}
|
240
|
+
})
|
241
|
+
end
|
242
|
+
|
243
|
+
after :each do
|
244
|
+
# Set poll interval back to default
|
245
|
+
set_cluster_settings(@es, {
|
246
|
+
"persistent" => {
|
247
|
+
"indices.lifecycle.poll_interval" => DEFAULT_INTERVAL
|
248
|
+
}
|
249
|
+
})
|
250
|
+
clean(@es)
|
251
|
+
end
|
252
|
+
|
253
|
+
|
254
|
+
context 'with ilm enabled' do
|
255
|
+
let (:ilm_enabled) { true }
|
256
|
+
|
257
|
+
|
258
|
+
context 'when using the default policy' do
|
259
|
+
context 'with a custom pattern' do
|
260
|
+
let (:settings) { super.merge("ilm_pattern" => "000001")}
|
261
|
+
it 'should create a rollover alias' do
|
262
|
+
expect(@es.indices.exists_alias(index: "logstash")).to be_falsey
|
263
|
+
subject.register
|
264
|
+
sleep(1)
|
265
|
+
expect(@es.indices.exists_alias(index: "logstash")).to be_truthy
|
266
|
+
expect(@es.get_alias(name: "logstash")).to include("logstash-000001")
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
|
271
|
+
it 'should install it if it is not present' do
|
272
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
273
|
+
subject.register
|
274
|
+
sleep(1)
|
275
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.not_to raise_error
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'should create the default rollover alias' do
|
279
|
+
expect(@es.indices.exists_alias(index: "logstash")).to be_falsey
|
280
|
+
subject.register
|
281
|
+
sleep(1)
|
282
|
+
expect(@es.indices.exists_alias(index: "logstash")).to be_truthy
|
283
|
+
expect(@es.get_alias(name: "logstash")).to include("logstash-#{todays_date}-000001")
|
284
|
+
end
|
285
|
+
|
286
|
+
|
287
|
+
it 'should ingest into a single index' do
|
288
|
+
subject.register
|
289
|
+
|
290
|
+
subject.multi_receive([
|
291
|
+
LogStash::Event.new("message" => "sample message here"),
|
292
|
+
LogStash::Event.new("somemessage" => { "message" => "sample nested message here" }),
|
293
|
+
LogStash::Event.new("somevalue" => 100),
|
294
|
+
])
|
295
|
+
|
296
|
+
sleep(6)
|
297
|
+
|
298
|
+
subject.multi_receive([
|
299
|
+
LogStash::Event.new("country" => "us"),
|
300
|
+
LogStash::Event.new("country" => "at"),
|
301
|
+
LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0 ] })
|
302
|
+
])
|
303
|
+
|
304
|
+
@es.indices.refresh
|
305
|
+
|
306
|
+
# Wait or fail until everything's indexed.
|
307
|
+
Stud::try(20.times) do
|
308
|
+
r = @es.search
|
309
|
+
expect(r).to have_hits(6)
|
310
|
+
end
|
311
|
+
indexes_written = @es.search['hits']['hits'].each_with_object(Hash.new(0)) do |x, res|
|
312
|
+
index_written = x['_index']
|
313
|
+
res[index_written] += 1
|
314
|
+
end
|
315
|
+
|
316
|
+
expect(indexes_written.count).to eq(1)
|
317
|
+
expect(indexes_written["logstash-#{todays_date}-000001"]).to eq(6)
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
context 'when not using the default policy' do
|
322
|
+
let (:ilm_policy_name) {"new_one"}
|
323
|
+
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
324
|
+
let (:policy) {{
|
325
|
+
"policy" => {
|
326
|
+
"phases"=> {
|
327
|
+
"hot" => {
|
328
|
+
"actions" => {
|
329
|
+
"rollover" => {
|
330
|
+
"max_docs" => "3"
|
331
|
+
}
|
332
|
+
}
|
333
|
+
}
|
334
|
+
}
|
335
|
+
}}}
|
336
|
+
|
337
|
+
before do
|
338
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
339
|
+
put_policy(@es,ilm_policy_name, policy)
|
340
|
+
end
|
341
|
+
|
342
|
+
it 'should not install the default policy if it is not used' do
|
343
|
+
subject.register
|
344
|
+
sleep(1)
|
345
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
context 'when using a time based policy' do
|
350
|
+
let (:ilm_policy_name) {"new_one"}
|
351
|
+
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
352
|
+
let (:policy) {{
|
353
|
+
"policy" => {
|
354
|
+
"phases"=> {
|
355
|
+
"hot" => {
|
356
|
+
"actions" => {
|
357
|
+
"rollover" => {
|
358
|
+
"max_age" => "1d"
|
359
|
+
}
|
360
|
+
}
|
361
|
+
}
|
362
|
+
}
|
363
|
+
}}}
|
364
|
+
|
365
|
+
before do
|
366
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
367
|
+
put_policy(@es,ilm_policy_name, policy)
|
368
|
+
end
|
369
|
+
|
370
|
+
it 'should not install the default policy if it is not used' do
|
371
|
+
subject.register
|
372
|
+
sleep(1)
|
373
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
374
|
+
end
|
375
|
+
end
|
376
|
+
context 'with the default template' do
|
377
|
+
let(:expected_index) { "logstash" }
|
378
|
+
|
379
|
+
it 'should create the rollover alias' do
|
380
|
+
expect(@es.indices.exists_alias(index: expected_index)).to be_falsey
|
381
|
+
subject.register
|
382
|
+
sleep(1)
|
383
|
+
expect(@es.indices.exists_alias(index: expected_index)).to be_truthy
|
384
|
+
expect(@es.get_alias(name: expected_index)).to include("#{expected_index}-#{todays_date}-000001")
|
385
|
+
end
|
386
|
+
|
387
|
+
it 'should write the ILM settings into the template' do
|
388
|
+
subject.register
|
389
|
+
sleep(1)
|
390
|
+
expect(@es.indices.get_template(name: "logstash")["logstash"]["index_patterns"]).to eq(["logstash-*"])
|
391
|
+
expect(@es.indices.get_template(name: "logstash")["logstash"]["settings"]['index']['lifecycle']['name']).to eq("logstash-policy")
|
392
|
+
expect(@es.indices.get_template(name: "logstash")["logstash"]["settings"]['index']['lifecycle']['rollover_alias']).to eq("logstash")
|
393
|
+
end
|
394
|
+
|
395
|
+
it_behaves_like 'an ILM enabled Logstash'
|
396
|
+
end
|
397
|
+
|
398
|
+
context 'with a custom template' do
|
399
|
+
let (:ilm_rollover_alias) { "the_cat_in_the_hat" }
|
400
|
+
let (:index) { ilm_rollover_alias }
|
401
|
+
let(:expected_index) { index }
|
402
|
+
let (:settings) { super.merge("ilm_policy" => ilm_policy_name,
|
403
|
+
"template" => template,
|
404
|
+
"ilm_rollover_alias" => ilm_rollover_alias)}
|
405
|
+
|
406
|
+
|
407
|
+
if ESHelper.es_version_satisfies?(">= 7.0")
|
408
|
+
let (:template) { "spec/fixtures/template-with-policy-es7x.json" }
|
409
|
+
else
|
410
|
+
let (:template) { "spec/fixtures/template-with-policy-es6x.json" }
|
411
|
+
end
|
412
|
+
let (:ilm_enabled) { true }
|
413
|
+
let (:ilm_policy_name) { "custom-policy" }
|
414
|
+
|
415
|
+
|
416
|
+
before :each do
|
417
|
+
put_policy(@es,ilm_policy_name, policy)
|
418
|
+
end
|
419
|
+
|
420
|
+
it_behaves_like 'an ILM enabled Logstash'
|
421
|
+
|
422
|
+
it 'should create the rollover alias' do
|
423
|
+
expect(@es.indices.exists_alias(index: ilm_rollover_alias)).to be_falsey
|
424
|
+
subject.register
|
425
|
+
sleep(1)
|
426
|
+
expect(@es.indices.exists_alias(index: ilm_rollover_alias)).to be_truthy
|
427
|
+
expect(@es.get_alias(name: ilm_rollover_alias)).to include("#{ilm_rollover_alias}-#{todays_date}-000001")
|
428
|
+
end
|
429
|
+
|
430
|
+
context 'when the custom rollover alias already exists' do
|
431
|
+
it 'should ignore the already exists error' do
|
432
|
+
expect(@es.indices.exists_alias(index: ilm_rollover_alias)).to be_falsey
|
433
|
+
put_alias(@es, "#{ilm_rollover_alias}-#{todays_date}-000001", ilm_rollover_alias)
|
434
|
+
expect(@es.indices.exists_alias(index: ilm_rollover_alias)).to be_truthy
|
435
|
+
subject.register
|
436
|
+
sleep(1)
|
437
|
+
expect(@es.get_alias(name: ilm_rollover_alias)).to include("#{ilm_rollover_alias}-#{todays_date}-000001")
|
438
|
+
end
|
439
|
+
|
440
|
+
end
|
441
|
+
|
442
|
+
it 'should write the ILM settings into the template' do
|
443
|
+
subject.register
|
444
|
+
sleep(1)
|
445
|
+
expect(@es.indices.get_template(name: ilm_rollover_alias)[ilm_rollover_alias]["index_patterns"]).to eq(["#{ilm_rollover_alias}-*"])
|
446
|
+
expect(@es.indices.get_template(name: ilm_rollover_alias)[ilm_rollover_alias]["settings"]['index']['lifecycle']['name']).to eq(ilm_policy_name)
|
447
|
+
expect(@es.indices.get_template(name: ilm_rollover_alias)[ilm_rollover_alias]["settings"]['index']['lifecycle']['rollover_alias']).to eq(ilm_rollover_alias)
|
448
|
+
end
|
449
|
+
|
450
|
+
context 'with a different template_name' do
|
451
|
+
let (:template_name) { "custom_template_name" }
|
452
|
+
let (:settings) { super.merge('template_name' => template_name)}
|
453
|
+
|
454
|
+
it_behaves_like 'an ILM enabled Logstash'
|
455
|
+
|
456
|
+
it 'should write the ILM settings into the template' do
|
457
|
+
subject.register
|
458
|
+
sleep(1)
|
459
|
+
expect(@es.indices.get_template(name: template_name)[template_name]["index_patterns"]).to eq(["#{ilm_rollover_alias}-*"])
|
460
|
+
expect(@es.indices.get_template(name: template_name)[template_name]["settings"]['index']['lifecycle']['name']).to eq(ilm_policy_name)
|
461
|
+
expect(@es.indices.get_template(name: template_name)[template_name]["settings"]['index']['lifecycle']['rollover_alias']).to eq(ilm_rollover_alias)
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
context 'with ilm disabled' do
|
469
|
+
let (:ilm_enabled) { false }
|
470
|
+
|
471
|
+
it 'should not create a rollover alias' do
|
472
|
+
expect(@es.get_alias).to be_empty
|
473
|
+
subject.register
|
474
|
+
sleep(1)
|
475
|
+
expect(@es.get_alias).to be_empty
|
476
|
+
end
|
477
|
+
|
478
|
+
it 'should not install the default policy' do
|
479
|
+
subject.register
|
480
|
+
sleep(1)
|
481
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
482
|
+
end
|
483
|
+
|
484
|
+
it 'should not write the ILM settings into the template' do
|
485
|
+
subject.register
|
486
|
+
sleep(1)
|
487
|
+
expect(@es.indices.get_template(name: "logstash")["logstash"]["index_patterns"]).to eq(["logstash-*"])
|
488
|
+
expect(@es.indices.get_template(name: "logstash")["logstash"]["settings"]['index']['lifecycle']).to be_nil
|
489
|
+
end
|
490
|
+
|
491
|
+
context 'with an existing policy that will roll over' do
|
492
|
+
let (:policy) { small_max_doc_policy }
|
493
|
+
let (:ilm_policy_name) { "3_docs"}
|
494
|
+
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
495
|
+
|
496
|
+
it 'should not roll over indices' do
|
497
|
+
subject.register
|
498
|
+
subject.multi_receive([
|
499
|
+
LogStash::Event.new("message" => "sample message here"),
|
500
|
+
LogStash::Event.new("somemessage" => { "message" => "sample nested message here" }),
|
501
|
+
LogStash::Event.new("somevalue" => 100),
|
502
|
+
])
|
503
|
+
|
504
|
+
sleep(6)
|
505
|
+
|
506
|
+
subject.multi_receive([
|
507
|
+
LogStash::Event.new("country" => "us"),
|
508
|
+
LogStash::Event.new("country" => "at"),
|
509
|
+
LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0 ] })
|
510
|
+
])
|
511
|
+
|
512
|
+
@es.indices.refresh
|
513
|
+
|
514
|
+
# Wait or fail until everything's indexed.
|
515
|
+
Stud::try(20.times) do
|
516
|
+
r = @es.search
|
517
|
+
expect(r).to have_hits(6)
|
518
|
+
end
|
519
|
+
indexes_written = @es.search['hits']['hits'].each_with_object(Hash.new(0)) do |x, res|
|
520
|
+
index_written = x['_index']
|
521
|
+
res[index_written] += 1
|
522
|
+
end
|
523
|
+
expect(indexes_written.count).to eq(1)
|
524
|
+
expect(indexes_written.values.first).to eq(6)
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
context 'with a custom template name' do
|
529
|
+
let (:template_name) { "custom_template_name" }
|
530
|
+
let (:settings) { super.merge('template_name' => template_name)}
|
531
|
+
|
532
|
+
it 'should not write the ILM settings into the template' do
|
533
|
+
subject.register
|
534
|
+
sleep(1)
|
535
|
+
expect(@es.indices.get_template(name: template_name)[template_name]["index_patterns"]).to eq(["logstash-*"])
|
536
|
+
expect(@es.indices.get_template(name: template_name)[template_name]["settings"]['index']['lifecycle']).to be_nil
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
end
|
541
|
+
end
|
542
|
+
end
|