logstash-output-elasticsearch-test 10.3.0-x86_64-linux
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 +7 -0
- data/CHANGELOG.md +397 -0
- data/CONTRIBUTORS +33 -0
- data/Gemfile +15 -0
- data/LICENSE +13 -0
- data/NOTICE.TXT +5 -0
- data/README.md +106 -0
- data/docs/index.asciidoc +899 -0
- data/lib/logstash/outputs/elasticsearch/common.rb +441 -0
- data/lib/logstash/outputs/elasticsearch/common_configs.rb +167 -0
- data/lib/logstash/outputs/elasticsearch/default-ilm-policy.json +14 -0
- data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es2x.json +95 -0
- data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es5x.json +46 -0
- data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es6x.json +45 -0
- data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es7x.json +44 -0
- data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es8x.json +44 -0
- data/lib/logstash/outputs/elasticsearch/http_client/manticore_adapter.rb +131 -0
- data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +495 -0
- data/lib/logstash/outputs/elasticsearch/http_client.rb +432 -0
- data/lib/logstash/outputs/elasticsearch/http_client_builder.rb +159 -0
- data/lib/logstash/outputs/elasticsearch/ilm.rb +113 -0
- data/lib/logstash/outputs/elasticsearch/template_manager.rb +61 -0
- data/lib/logstash/outputs/elasticsearch.rb +263 -0
- data/logstash-output-elasticsearch.gemspec +33 -0
- data/spec/es_spec_helper.rb +189 -0
- data/spec/fixtures/_nodes/2x_1x.json +27 -0
- data/spec/fixtures/_nodes/5x_6x.json +81 -0
- data/spec/fixtures/_nodes/7x.json +92 -0
- data/spec/fixtures/htpasswd +2 -0
- data/spec/fixtures/nginx_reverse_proxy.conf +22 -0
- data/spec/fixtures/scripts/groovy/scripted_update.groovy +2 -0
- data/spec/fixtures/scripts/groovy/scripted_update_nested.groovy +2 -0
- data/spec/fixtures/scripts/groovy/scripted_upsert.groovy +2 -0
- data/spec/fixtures/scripts/painless/scripted_update.painless +2 -0
- data/spec/fixtures/scripts/painless/scripted_update_nested.painless +1 -0
- data/spec/fixtures/scripts/painless/scripted_upsert.painless +1 -0
- data/spec/fixtures/template-with-policy-es6x.json +48 -0
- data/spec/fixtures/template-with-policy-es7x.json +45 -0
- data/spec/fixtures/test_certs/ca/ca.crt +32 -0
- data/spec/fixtures/test_certs/ca/ca.key +51 -0
- data/spec/fixtures/test_certs/test.crt +36 -0
- data/spec/fixtures/test_certs/test.key +51 -0
- data/spec/integration/outputs/compressed_indexing_spec.rb +69 -0
- data/spec/integration/outputs/create_spec.rb +67 -0
- data/spec/integration/outputs/delete_spec.rb +65 -0
- data/spec/integration/outputs/groovy_update_spec.rb +150 -0
- data/spec/integration/outputs/ilm_spec.rb +531 -0
- data/spec/integration/outputs/index_spec.rb +178 -0
- data/spec/integration/outputs/index_version_spec.rb +102 -0
- data/spec/integration/outputs/ingest_pipeline_spec.rb +74 -0
- data/spec/integration/outputs/metrics_spec.rb +70 -0
- data/spec/integration/outputs/no_es_on_startup_spec.rb +58 -0
- data/spec/integration/outputs/painless_update_spec.rb +189 -0
- data/spec/integration/outputs/parent_spec.rb +102 -0
- data/spec/integration/outputs/retry_spec.rb +169 -0
- data/spec/integration/outputs/routing_spec.rb +61 -0
- data/spec/integration/outputs/sniffer_spec.rb +133 -0
- data/spec/integration/outputs/templates_5x_spec.rb +98 -0
- data/spec/integration/outputs/templates_spec.rb +98 -0
- data/spec/integration/outputs/update_spec.rb +116 -0
- 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
- data/spec/unit/http_client_builder_spec.rb +185 -0
- data/spec/unit/outputs/elasticsearch/http_client/manticore_adapter_spec.rb +149 -0
- data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +274 -0
- data/spec/unit/outputs/elasticsearch/http_client_spec.rb +250 -0
- data/spec/unit/outputs/elasticsearch/template_manager_spec.rb +25 -0
- data/spec/unit/outputs/elasticsearch_proxy_spec.rb +72 -0
- data/spec/unit/outputs/elasticsearch_spec.rb +675 -0
- data/spec/unit/outputs/elasticsearch_ssl_spec.rb +82 -0
- data/spec/unit/outputs/error_whitelist_spec.rb +54 -0
- metadata +300 -0
@@ -0,0 +1,150 @@
|
|
1
|
+
require_relative "../../../spec/es_spec_helper"
|
2
|
+
|
3
|
+
if ESHelper.es_version_satisfies?('>= 2', '< 6')
|
4
|
+
describe "Update actions using groovy scripts", :integration => true, :update_tests => 'groovy' do
|
5
|
+
require "logstash/outputs/elasticsearch"
|
6
|
+
|
7
|
+
def get_es_output( options={} )
|
8
|
+
settings = {
|
9
|
+
"manage_template" => true,
|
10
|
+
"index" => "logstash-update",
|
11
|
+
"template_overwrite" => true,
|
12
|
+
"hosts" => get_host_port(),
|
13
|
+
"action" => "update",
|
14
|
+
"script_lang" => "groovy"
|
15
|
+
}
|
16
|
+
LogStash::Outputs::ElasticSearch.new(settings.merge!(options))
|
17
|
+
end
|
18
|
+
|
19
|
+
before :each do
|
20
|
+
@es = get_client
|
21
|
+
# Delete all templates first.
|
22
|
+
# Clean ES of data before we start.
|
23
|
+
@es.indices.delete_template(:name => "*")
|
24
|
+
# This can fail if there are no indexes, ignore failure.
|
25
|
+
@es.indices.delete(:index => "*") rescue nil
|
26
|
+
@es.index(
|
27
|
+
:index => 'logstash-update',
|
28
|
+
:type => doc_type,
|
29
|
+
:id => "123",
|
30
|
+
:body => { :message => 'Test', :counter => 1 }
|
31
|
+
)
|
32
|
+
@es.indices.refresh
|
33
|
+
end
|
34
|
+
|
35
|
+
context "scripted updates" do
|
36
|
+
it "should increment a counter with event/doc 'count' variable" do
|
37
|
+
subject = get_es_output({ 'document_id' => "123", 'script' => 'scripted_update', 'script_type' => 'file' })
|
38
|
+
subject.register
|
39
|
+
subject.multi_receive([LogStash::Event.new("count" => 2)])
|
40
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "123", :refresh => true)
|
41
|
+
expect(r["_source"]["counter"]).to eq(3)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should increment a counter with event/doc '[data][count]' nested variable" do
|
45
|
+
subject = get_es_output({ 'document_id' => "123", 'script' => 'scripted_update_nested', 'script_type' => 'file' })
|
46
|
+
subject.register
|
47
|
+
subject.multi_receive([LogStash::Event.new("data" => { "count" => 3 })])
|
48
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "123", :refresh => true)
|
49
|
+
expect(r["_source"]["counter"]).to eq(4)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should increment a counter with event/doc 'count' variable with inline script" do
|
53
|
+
subject = get_es_output({
|
54
|
+
'document_id' => "123",
|
55
|
+
'script' => 'ctx._source.counter += event["counter"]',
|
56
|
+
'script_lang' => 'groovy',
|
57
|
+
'script_type' => 'inline'
|
58
|
+
})
|
59
|
+
subject.register
|
60
|
+
subject.multi_receive([LogStash::Event.new("counter" => 3 )])
|
61
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "123", :refresh => true)
|
62
|
+
expect(r["_source"]["counter"]).to eq(4)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should increment a counter with event/doc 'count' variable with event/doc as upsert and inline script" do
|
66
|
+
subject = get_es_output({
|
67
|
+
'document_id' => "123",
|
68
|
+
'doc_as_upsert' => true,
|
69
|
+
'script' => 'if( ctx._source.containsKey("counter") ){ ctx._source.counter += event["counter"]; } else { ctx._source.counter = event["counter"]; }',
|
70
|
+
'script_lang' => 'groovy',
|
71
|
+
'script_type' => 'inline'
|
72
|
+
})
|
73
|
+
subject.register
|
74
|
+
subject.multi_receive([LogStash::Event.new("counter" => 3 )])
|
75
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "123", :refresh => true)
|
76
|
+
expect(r["_source"]["counter"]).to eq(4)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should, with new doc, set a counter with event/doc 'count' variable with event/doc as upsert and inline script" do
|
80
|
+
subject = get_es_output({
|
81
|
+
'document_id' => "456",
|
82
|
+
'doc_as_upsert' => true,
|
83
|
+
'script' => 'if( ctx._source.containsKey("counter") ){ ctx._source.counter += event["count"]; } else { ctx._source.counter = event["count"]; }',
|
84
|
+
'script_lang' => 'groovy',
|
85
|
+
'script_type' => 'inline'
|
86
|
+
})
|
87
|
+
subject.register
|
88
|
+
subject.multi_receive([LogStash::Event.new("counter" => 3 )])
|
89
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "456", :refresh => true)
|
90
|
+
expect(r["_source"]["counter"]).to eq(3)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should increment a counter with event/doc 'count' variable with indexed script" do
|
94
|
+
@es.put_script lang: 'groovy', id: 'indexed_update', body: { script: 'ctx._source.counter += event["count"]' }
|
95
|
+
subject = get_es_output({
|
96
|
+
'document_id' => "123",
|
97
|
+
'script' => 'indexed_update',
|
98
|
+
'script_lang' => 'groovy',
|
99
|
+
'script_type' => 'indexed'
|
100
|
+
})
|
101
|
+
subject.register
|
102
|
+
subject.multi_receive([LogStash::Event.new("count" => 4 )])
|
103
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "123", :refresh => true)
|
104
|
+
expect(r["_source"]["counter"]).to eq(5)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "when update with upsert" do
|
109
|
+
it "should create new documents with provided upsert" do
|
110
|
+
subject = get_es_output({ 'document_id' => "456", 'upsert' => '{"message": "upsert message"}' })
|
111
|
+
subject.register
|
112
|
+
subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
|
113
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "456", :refresh => true)
|
114
|
+
expect(r["_source"]["message"]).to eq('upsert message')
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should create new documents with event/doc as upsert" do
|
118
|
+
subject = get_es_output({ 'document_id' => "456", 'doc_as_upsert' => true })
|
119
|
+
subject.register
|
120
|
+
subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
|
121
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "456", :refresh => true)
|
122
|
+
expect(r["_source"]["message"]).to eq('sample message here')
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should fail on documents with event/doc as upsert at external version" do
|
126
|
+
subject = get_es_output({ 'document_id' => "456", 'doc_as_upsert' => true, 'version' => 999, "version_type" => "external" })
|
127
|
+
expect { subject.register }.to raise_error(LogStash::ConfigurationError)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "updates with scripted upsert" do
|
132
|
+
it "should create new documents with upsert content" do
|
133
|
+
subject = get_es_output({ 'document_id' => "456", 'script' => 'scripted_update', 'upsert' => '{"message": "upsert message"}', 'script_type' => 'file' })
|
134
|
+
subject.register
|
135
|
+
subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
|
136
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "456", :refresh => true)
|
137
|
+
expect(r["_source"]["message"]).to eq('upsert message')
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should create new documents with event/doc as script params" do
|
141
|
+
subject = get_es_output({ 'document_id' => "456", 'script' => 'scripted_upsert', 'scripted_upsert' => true, 'script_type' => 'file' })
|
142
|
+
subject.register
|
143
|
+
subject.multi_receive([LogStash::Event.new("counter" => 1)])
|
144
|
+
@es.indices.refresh
|
145
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "456", :refresh => true)
|
146
|
+
expect(r["_source"]["counter"]).to eq(1)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,531 @@
|
|
1
|
+
require_relative "../../../spec/es_spec_helper"
|
2
|
+
|
3
|
+
shared_examples_for 'an ILM enabled Logstash' do
|
4
|
+
|
5
|
+
context 'with a policy with a maximum number of documents' do
|
6
|
+
let (:policy) { small_max_doc_policy }
|
7
|
+
let (:ilm_policy_name) { "custom-policy"}
|
8
|
+
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
9
|
+
|
10
|
+
it 'should rollover when the policy max docs is reached' do
|
11
|
+
put_policy(@es,ilm_policy_name, policy)
|
12
|
+
subject.register
|
13
|
+
|
14
|
+
subject.multi_receive([
|
15
|
+
LogStash::Event.new("message" => "sample message here"),
|
16
|
+
LogStash::Event.new("somemessage" => { "message" => "sample nested message here" }),
|
17
|
+
LogStash::Event.new("somevalue" => 100),
|
18
|
+
])
|
19
|
+
|
20
|
+
sleep(6)
|
21
|
+
|
22
|
+
subject.multi_receive([
|
23
|
+
LogStash::Event.new("country" => "us"),
|
24
|
+
LogStash::Event.new("country" => "at"),
|
25
|
+
LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0 ] })
|
26
|
+
])
|
27
|
+
|
28
|
+
sleep(6)
|
29
|
+
|
30
|
+
subject.multi_receive([
|
31
|
+
LogStash::Event.new("country" => "uk"),
|
32
|
+
LogStash::Event.new("country" => "fr"),
|
33
|
+
LogStash::Event.new("geoip" => { "location" => [ 0.1, 1.0 ] })
|
34
|
+
])
|
35
|
+
|
36
|
+
@es.indices.refresh
|
37
|
+
|
38
|
+
# Wait or fail until everything's indexed.
|
39
|
+
Stud::try(20.times) do
|
40
|
+
r = @es.search
|
41
|
+
expect(r).to have_hits(9)
|
42
|
+
end
|
43
|
+
indexes_written = @es.search['hits']['hits'].each_with_object(Hash.new(0)) do |x, res|
|
44
|
+
index_written = x['_index']
|
45
|
+
res[index_written] += 1
|
46
|
+
end
|
47
|
+
expect(indexes_written.count).to eq(3)
|
48
|
+
expect(indexes_written["#{expected_index}-#{todays_date}-000001"]).to eq(3)
|
49
|
+
expect(indexes_written["#{expected_index}-#{todays_date}-000002"]).to eq(3)
|
50
|
+
expect(indexes_written["#{expected_index}-#{todays_date}-000003"]).to eq(3)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'with a policy where the maximum number of documents is not reached' do
|
55
|
+
let (:policy) { large_max_doc_policy }
|
56
|
+
let (:ilm_policy_name) { "custom-policy"}
|
57
|
+
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
58
|
+
|
59
|
+
it 'should ingest into a single index when max docs is not reached' do
|
60
|
+
put_policy(@es,ilm_policy_name, policy)
|
61
|
+
subject.register
|
62
|
+
|
63
|
+
subject.multi_receive([
|
64
|
+
LogStash::Event.new("message" => "sample message here"),
|
65
|
+
LogStash::Event.new("somemessage" => { "message" => "sample nested message here" }),
|
66
|
+
LogStash::Event.new("somevalue" => 100),
|
67
|
+
])
|
68
|
+
|
69
|
+
sleep(6)
|
70
|
+
|
71
|
+
subject.multi_receive([
|
72
|
+
LogStash::Event.new("country" => "us"),
|
73
|
+
LogStash::Event.new("country" => "at"),
|
74
|
+
LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0 ] })
|
75
|
+
])
|
76
|
+
|
77
|
+
@es.indices.refresh
|
78
|
+
|
79
|
+
# Wait or fail until everything's indexed.
|
80
|
+
Stud::try(20.times) do
|
81
|
+
r = @es.search
|
82
|
+
expect(r).to have_hits(6)
|
83
|
+
end
|
84
|
+
indexes_written = @es.search['hits']['hits'].each_with_object(Hash.new(0)) do |x, res|
|
85
|
+
index_written = x['_index']
|
86
|
+
res[index_written] += 1
|
87
|
+
end
|
88
|
+
expect(indexes_written.count).to eq(1)
|
89
|
+
expect(indexes_written["#{expected_index}-#{todays_date}-000001"]).to eq(6)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
shared_examples_for 'an ILM disabled Logstash' do
|
95
|
+
it 'should not create a rollover alias' do
|
96
|
+
expect(@es.get_alias).to be_empty
|
97
|
+
subject.register
|
98
|
+
sleep(1)
|
99
|
+
expect(@es.get_alias).to be_empty
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should not install the default policy' do
|
103
|
+
subject.register
|
104
|
+
sleep(1)
|
105
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should not write the ILM settings into the template' do
|
109
|
+
subject.register
|
110
|
+
sleep(1)
|
111
|
+
expect(@es.indices.get_template(name: "logstash")["logstash"]).to have_index_pattern("logstash-*")
|
112
|
+
if ESHelper.es_version_satisfies?(">= 2")
|
113
|
+
expect(@es.indices.get_template(name: "logstash")["logstash"]["settings"]['index']['lifecycle']).to be_nil
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'with an existing policy that will roll over' do
|
118
|
+
let (:policy) { small_max_doc_policy }
|
119
|
+
let (:ilm_policy_name) { "3_docs"}
|
120
|
+
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
121
|
+
|
122
|
+
it 'should not roll over indices' do
|
123
|
+
subject.register
|
124
|
+
subject.multi_receive([
|
125
|
+
LogStash::Event.new("message" => "sample message here"),
|
126
|
+
LogStash::Event.new("somemessage" => { "message" => "sample nested message here" }),
|
127
|
+
LogStash::Event.new("somevalue" => 100),
|
128
|
+
])
|
129
|
+
|
130
|
+
sleep(6)
|
131
|
+
|
132
|
+
subject.multi_receive([
|
133
|
+
LogStash::Event.new("country" => "us"),
|
134
|
+
LogStash::Event.new("country" => "at"),
|
135
|
+
LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0 ] })
|
136
|
+
])
|
137
|
+
|
138
|
+
@es.indices.refresh
|
139
|
+
|
140
|
+
# Wait or fail until everything's indexed.
|
141
|
+
Stud::try(20.times) do
|
142
|
+
r = @es.search
|
143
|
+
expect(r).to have_hits(6)
|
144
|
+
end
|
145
|
+
indexes_written = @es.search['hits']['hits'].each_with_object(Hash.new(0)) do |x, res|
|
146
|
+
index_written = x['_index']
|
147
|
+
res[index_written] += 1
|
148
|
+
end
|
149
|
+
expect(indexes_written.count).to eq(1)
|
150
|
+
expect(indexes_written.values.first).to eq(6)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'with a custom template name' do
|
155
|
+
let (:template_name) { "custom_template_name" }
|
156
|
+
let (:settings) { super.merge('template_name' => template_name)}
|
157
|
+
|
158
|
+
it 'should not write the ILM settings into the template' do
|
159
|
+
subject.register
|
160
|
+
sleep(1)
|
161
|
+
|
162
|
+
expect(@es.indices.get_template(name: template_name)[template_name]).to have_index_pattern("logstash-*")
|
163
|
+
if ESHelper.es_version_satisfies?(">= 2")
|
164
|
+
expect(@es.indices.get_template(name: template_name)[template_name]["settings"]['index']['lifecycle']).to be_nil
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
shared_examples_for 'an Elasticsearch instance that does not support index lifecycle management' do
|
171
|
+
require "logstash/outputs/elasticsearch"
|
172
|
+
|
173
|
+
let (:ilm_enabled) { false }
|
174
|
+
let (:settings) {
|
175
|
+
{
|
176
|
+
"hosts" => "#{get_host_port()}"
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
before :each do
|
181
|
+
require "elasticsearch"
|
182
|
+
|
183
|
+
# Clean ES of data before we start.
|
184
|
+
@es = get_client
|
185
|
+
clean(@es)
|
186
|
+
end
|
187
|
+
|
188
|
+
after :each do
|
189
|
+
clean(@es)
|
190
|
+
end
|
191
|
+
|
192
|
+
subject { LogStash::Outputs::ElasticSearch.new(settings) }
|
193
|
+
|
194
|
+
context 'when ilm is enabled in Logstash' do
|
195
|
+
let (:settings) { super.merge!({ 'ilm_enabled' => true }) }
|
196
|
+
|
197
|
+
it 'should raise a configuration error' do
|
198
|
+
expect do
|
199
|
+
begin
|
200
|
+
subject.register
|
201
|
+
sleep(1)
|
202
|
+
ensure
|
203
|
+
subject.stop_template_installer
|
204
|
+
end
|
205
|
+
end.to raise_error(LogStash::ConfigurationError)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
context 'when ilm is disabled in Logstash' do
|
210
|
+
let (:settings) { super.merge!({ 'ilm_enabled' => false }) }
|
211
|
+
|
212
|
+
it_behaves_like 'an ILM disabled Logstash'
|
213
|
+
end
|
214
|
+
|
215
|
+
context 'when ilm is set to auto in Logstash' do
|
216
|
+
let (:settings) { super.merge!({ 'ilm_enabled' => 'auto' }) }
|
217
|
+
|
218
|
+
it_behaves_like 'an ILM disabled Logstash'
|
219
|
+
end
|
220
|
+
|
221
|
+
context 'when ilm is not set in Logstash' do
|
222
|
+
it_behaves_like 'an ILM disabled Logstash'
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
if ESHelper.es_version_satisfies?("<= 6.5")
|
228
|
+
describe 'Pre-ILM versions of Elasticsearch', :integration => true do
|
229
|
+
it_behaves_like 'an Elasticsearch instance that does not support index lifecycle management'
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
if ESHelper.es_version_satisfies?(">= 6.6")
|
234
|
+
describe 'OSS Elasticsearch', :distribution => 'oss', :integration => true do
|
235
|
+
it_behaves_like 'an Elasticsearch instance that does not support index lifecycle management'
|
236
|
+
end
|
237
|
+
|
238
|
+
describe 'Elasticsearch has index lifecycle management enabled', :distribution => 'xpack', :integration => true do
|
239
|
+
|
240
|
+
DEFAULT_INTERVAL = '600s'
|
241
|
+
|
242
|
+
let (:ilm_enabled) { true }
|
243
|
+
|
244
|
+
let (:settings) {
|
245
|
+
{
|
246
|
+
"ilm_enabled" => ilm_enabled,
|
247
|
+
"hosts" => "#{get_host_port()}"
|
248
|
+
}
|
249
|
+
}
|
250
|
+
let (:small_max_doc_policy) { max_docs_policy(3) }
|
251
|
+
let (:large_max_doc_policy) { max_docs_policy(1000000) }
|
252
|
+
let (:expected_index) { LogStash::Outputs::ElasticSearch::DEFAULT_ROLLOVER_ALIAS }
|
253
|
+
|
254
|
+
subject { LogStash::Outputs::ElasticSearch.new(settings) }
|
255
|
+
|
256
|
+
before :each do
|
257
|
+
# Delete all templates first.
|
258
|
+
require "elasticsearch"
|
259
|
+
|
260
|
+
# Clean ES of data before we start.
|
261
|
+
@es = get_client
|
262
|
+
clean(@es)
|
263
|
+
# Set the poll interval for lifecycle management to be short so changes get picked up in time.
|
264
|
+
set_cluster_settings(@es, {
|
265
|
+
"persistent" => {
|
266
|
+
"indices.lifecycle.poll_interval" => "1s"
|
267
|
+
}
|
268
|
+
})
|
269
|
+
end
|
270
|
+
|
271
|
+
after :each do
|
272
|
+
# Set poll interval back to default
|
273
|
+
set_cluster_settings(@es, {
|
274
|
+
"persistent" => {
|
275
|
+
"indices.lifecycle.poll_interval" => DEFAULT_INTERVAL
|
276
|
+
}
|
277
|
+
})
|
278
|
+
clean(@es)
|
279
|
+
end
|
280
|
+
|
281
|
+
context 'with ilm enabled' do
|
282
|
+
let (:ilm_enabled) { true }
|
283
|
+
|
284
|
+
context 'when using the default policy' do
|
285
|
+
context 'with a custom pattern' do
|
286
|
+
let (:settings) { super.merge("ilm_pattern" => "000001")}
|
287
|
+
it 'should create a rollover alias' do
|
288
|
+
expect(@es.indices.exists_alias(index: "logstash")).to be_falsey
|
289
|
+
subject.register
|
290
|
+
sleep(1)
|
291
|
+
expect(@es.indices.exists_alias(index: "logstash")).to be_truthy
|
292
|
+
expect(@es.get_alias(name: "logstash")).to include("logstash-000001")
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
it 'should install it if it is not present' do
|
297
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
298
|
+
subject.register
|
299
|
+
sleep(1)
|
300
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.not_to raise_error
|
301
|
+
end
|
302
|
+
|
303
|
+
it 'should create the default rollover alias' do
|
304
|
+
expect(@es.indices.exists_alias(index: "logstash")).to be_falsey
|
305
|
+
subject.register
|
306
|
+
sleep(1)
|
307
|
+
expect(@es.indices.exists_alias(index: "logstash")).to be_truthy
|
308
|
+
expect(@es.get_alias(name: "logstash")).to include("logstash-#{todays_date}-000001")
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'should ingest into a single index' do
|
312
|
+
subject.register
|
313
|
+
subject.multi_receive([
|
314
|
+
LogStash::Event.new("message" => "sample message here"),
|
315
|
+
LogStash::Event.new("somemessage" => { "message" => "sample nested message here" }),
|
316
|
+
LogStash::Event.new("somevalue" => 100),
|
317
|
+
])
|
318
|
+
|
319
|
+
sleep(6)
|
320
|
+
|
321
|
+
subject.multi_receive([
|
322
|
+
LogStash::Event.new("country" => "us"),
|
323
|
+
LogStash::Event.new("country" => "at"),
|
324
|
+
LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0 ] })
|
325
|
+
])
|
326
|
+
|
327
|
+
@es.indices.refresh
|
328
|
+
|
329
|
+
# Wait or fail until everything's indexed.
|
330
|
+
Stud::try(20.times) do
|
331
|
+
r = @es.search
|
332
|
+
expect(r).to have_hits(6)
|
333
|
+
end
|
334
|
+
indexes_written = @es.search['hits']['hits'].each_with_object(Hash.new(0)) do |x, res|
|
335
|
+
index_written = x['_index']
|
336
|
+
res[index_written] += 1
|
337
|
+
end
|
338
|
+
|
339
|
+
expect(indexes_written.count).to eq(1)
|
340
|
+
expect(indexes_written["logstash-#{todays_date}-000001"]).to eq(6)
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
context 'when not using the default policy' do
|
345
|
+
let (:ilm_policy_name) {"new_one"}
|
346
|
+
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
347
|
+
let (:policy) { small_max_doc_policy }
|
348
|
+
|
349
|
+
before do
|
350
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
351
|
+
put_policy(@es,ilm_policy_name, policy)
|
352
|
+
end
|
353
|
+
|
354
|
+
it 'should not install the default policy if it is not used' do
|
355
|
+
subject.register
|
356
|
+
sleep(1)
|
357
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
context 'when using a time based policy' do
|
362
|
+
let (:ilm_policy_name) {"new_one"}
|
363
|
+
let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
|
364
|
+
let (:policy) { max_age_policy("1d") }
|
365
|
+
|
366
|
+
before do
|
367
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
368
|
+
put_policy(@es,ilm_policy_name, policy)
|
369
|
+
end
|
370
|
+
|
371
|
+
it 'should not install the default policy if it is not used' do
|
372
|
+
subject.register
|
373
|
+
sleep(1)
|
374
|
+
expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
context 'with the default template' do
|
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"]).to have_index_pattern("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 set index and a custom index pattern' do
|
399
|
+
if ESHelper.es_version_satisfies?(">= 7.0")
|
400
|
+
let (:template) { "spec/fixtures/template-with-policy-es7x.json" }
|
401
|
+
else
|
402
|
+
let (:template) { "spec/fixtures/template-with-policy-es6x.json" }
|
403
|
+
end
|
404
|
+
|
405
|
+
let (:settings) { super.merge("template" => template,
|
406
|
+
"index" => "overwrite-4")}
|
407
|
+
|
408
|
+
it 'should not overwrite the index patterns' do
|
409
|
+
subject.register
|
410
|
+
sleep(1)
|
411
|
+
expect(@es.indices.get_template(name: "logstash")["logstash"]).to have_index_pattern("overwrite-*")
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
|
416
|
+
context 'with a custom template' do
|
417
|
+
let (:ilm_rollover_alias) { "the_cat_in_the_hat" }
|
418
|
+
let (:index) { ilm_rollover_alias }
|
419
|
+
let(:expected_index) { index }
|
420
|
+
let (:settings) { super.merge("ilm_policy" => ilm_policy_name,
|
421
|
+
"template" => template,
|
422
|
+
"ilm_rollover_alias" => ilm_rollover_alias)}
|
423
|
+
|
424
|
+
|
425
|
+
if ESHelper.es_version_satisfies?(">= 7.0")
|
426
|
+
let (:template) { "spec/fixtures/template-with-policy-es7x.json" }
|
427
|
+
else
|
428
|
+
let (:template) { "spec/fixtures/template-with-policy-es6x.json" }
|
429
|
+
end
|
430
|
+
let (:ilm_enabled) { true }
|
431
|
+
let (:ilm_policy_name) { "custom-policy" }
|
432
|
+
let (:policy) { small_max_doc_policy }
|
433
|
+
|
434
|
+
before :each do
|
435
|
+
put_policy(@es,ilm_policy_name, policy)
|
436
|
+
end
|
437
|
+
|
438
|
+
it_behaves_like 'an ILM enabled Logstash'
|
439
|
+
|
440
|
+
it 'should create the rollover alias' do
|
441
|
+
expect(@es.indices.exists_alias(index: ilm_rollover_alias)).to be_falsey
|
442
|
+
subject.register
|
443
|
+
sleep(1)
|
444
|
+
expect(@es.indices.exists_alias(index: ilm_rollover_alias)).to be_truthy
|
445
|
+
expect(@es.get_alias(name: ilm_rollover_alias)).to include("#{ilm_rollover_alias}-#{todays_date}-000001")
|
446
|
+
end
|
447
|
+
|
448
|
+
context 'when the custom rollover alias already exists' do
|
449
|
+
it 'should ignore the already exists error' do
|
450
|
+
expect(@es.indices.exists_alias(index: ilm_rollover_alias)).to be_falsey
|
451
|
+
put_alias(@es, "#{ilm_rollover_alias}-#{todays_date}-000001", ilm_rollover_alias)
|
452
|
+
expect(@es.indices.exists_alias(index: ilm_rollover_alias)).to be_truthy
|
453
|
+
subject.register
|
454
|
+
sleep(1)
|
455
|
+
expect(@es.get_alias(name: ilm_rollover_alias)).to include("#{ilm_rollover_alias}-#{todays_date}-000001")
|
456
|
+
end
|
457
|
+
|
458
|
+
end
|
459
|
+
|
460
|
+
it 'should write the ILM settings into the template' do
|
461
|
+
subject.register
|
462
|
+
sleep(1)
|
463
|
+
expect(@es.indices.get_template(name: ilm_rollover_alias)[ilm_rollover_alias]).to have_index_pattern("#{ilm_rollover_alias}-*")
|
464
|
+
expect(@es.indices.get_template(name: ilm_rollover_alias)[ilm_rollover_alias]["settings"]['index']['lifecycle']['name']).to eq(ilm_policy_name)
|
465
|
+
expect(@es.indices.get_template(name: ilm_rollover_alias)[ilm_rollover_alias]["settings"]['index']['lifecycle']['rollover_alias']).to eq(ilm_rollover_alias)
|
466
|
+
end
|
467
|
+
|
468
|
+
context 'with a different template_name' do
|
469
|
+
let (:template_name) { "custom_template_name" }
|
470
|
+
let (:settings) { super.merge('template_name' => template_name)}
|
471
|
+
|
472
|
+
it_behaves_like 'an ILM enabled Logstash'
|
473
|
+
|
474
|
+
it 'should write the ILM settings into the template' do
|
475
|
+
subject.register
|
476
|
+
sleep(1)
|
477
|
+
expect(@es.indices.get_template(name: template_name)[template_name]).to have_index_pattern("#{ilm_rollover_alias}-*")
|
478
|
+
expect(@es.indices.get_template(name: template_name)[template_name]["settings"]['index']['lifecycle']['name']).to eq(ilm_policy_name)
|
479
|
+
expect(@es.indices.get_template(name: template_name)[template_name]["settings"]['index']['lifecycle']['rollover_alias']).to eq(ilm_rollover_alias)
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
context 'when ilm_enabled is set to "auto"' do
|
487
|
+
let (:ilm_enabled) { 'auto' }
|
488
|
+
|
489
|
+
if ESHelper.es_version_satisfies?(">=7.0")
|
490
|
+
context 'when Elasticsearch is version 7 or above' do
|
491
|
+
it_behaves_like 'an ILM enabled Logstash'
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
if ESHelper.es_version_satisfies?('< 7.0')
|
496
|
+
context 'when Elasticsearch is version 7 or below' do
|
497
|
+
it_behaves_like 'an ILM disabled Logstash'
|
498
|
+
end
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
context 'when ilm_enabled is the default' do
|
503
|
+
let (:settings) { super.tap{|x|x.delete('ilm_enabled')}}
|
504
|
+
|
505
|
+
if ESHelper.es_version_satisfies?(">=7.0")
|
506
|
+
context 'when Elasticsearch is version 7 or above' do
|
507
|
+
it_behaves_like 'an ILM enabled Logstash'
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
if ESHelper.es_version_satisfies?('< 7.0')
|
512
|
+
context 'when Elasticsearch is version 7 or below' do
|
513
|
+
it_behaves_like 'an ILM disabled Logstash'
|
514
|
+
end
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
context 'with ilm disabled' do
|
519
|
+
let (:settings) { super.merge('ilm_enabled' => false )}
|
520
|
+
|
521
|
+
it_behaves_like 'an ILM disabled Logstash'
|
522
|
+
end
|
523
|
+
|
524
|
+
context 'with ilm disabled using a string' do
|
525
|
+
let (:settings) { super.merge('ilm_enabled' => 'false' )}
|
526
|
+
|
527
|
+
it_behaves_like 'an ILM disabled Logstash'
|
528
|
+
end
|
529
|
+
|
530
|
+
end
|
531
|
+
end
|