logstash-output-elasticsearch 9.3.2-java → 9.4.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ae86a048dbbbc543991c0f0940002f81c13ef3619a3ab0dcfbd73030b4992be
4
- data.tar.gz: 8ccb17687bc962888d4a0f2eb94d62a29f27ec7460078deb98f4a789ef9ac13f
3
+ metadata.gz: 7a6c544ed5e43a7c722849336fedcd792b7f843e3ed12de12a2898d019a56084
4
+ data.tar.gz: 9db3b25912b6d104752a6eb73cc4d12fe900a41b7fad369720fbb56cf0d087cf
5
5
  SHA512:
6
- metadata.gz: 89be3b3bf2a12d130ae7d6c8da1f9961d827b12814901c180a9caa966ca15bb7b8ae2a1df0b79906edd48edaca7888ed9dd8f6c132a5b52170641a777fcd0e54
7
- data.tar.gz: 890f65b47189d95c7087095e7f1a0cfad288499428de0002cd260f40a67788b43a9f4b7c6a643d9428ee25cd5e326fe336191bda6e674f5eea264b21f413c97f
6
+ metadata.gz: f785bc20eaad291c9a5eb30e4aee4737ce55dbcc879267b71fe0a1bc13e938410374080c9c28094ae28406894890a7710b04fa9eea5aab1ec854efd18db5aae2
7
+ data.tar.gz: 50aef5de97548888460009d7148530b65b9b5ea62ae49bc7ee4ec31935e51bb7d4a870690d23015738682072c9c5fadac2390af19a633a5702f6dd1aef60793c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## 9.4.0
2
+ - Added 'auto' setting for ILM [#841](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/841)
3
+
1
4
  ## 9.3.2
2
5
  - Fixed sniffing support for 7.x [#827](https://github.com/logstash-plugins/logstash-output-elasticsearch/pull/827)
3
6
 
data/docs/index.asciidoc CHANGED
@@ -94,9 +94,8 @@ happens, the problem is logged as a warning, and the event is dropped. See
94
94
  <<dead-letter-queues>> for more information about processing events in the DLQ.
95
95
 
96
96
  [id="plugins-{type}s-{plugin}-ilm"]
97
- ==== Index Lifecycle Management (Beta)
97
+ ==== Index Lifecycle Management
98
98
 
99
- beta[]
100
99
 
101
100
  [NOTE]
102
101
  The Index Lifecycle Management feature requires plugin version `9.3.1` or higher.
@@ -104,18 +103,22 @@ The Index Lifecycle Management feature requires plugin version `9.3.1` or higher
104
103
  [NOTE]
105
104
  This feature requires an Elasticsearch instance of 6.6.0 or higher with at least a Basic license
106
105
 
107
- Logstash can use the {ref}/index-lifecycle-management.html[Index Lifecycle Management] to automate the management of indices over time.
106
+ Logstash can use {ref}/index-lifecycle-management.html[Index Lifecycle Management] to automate the management of indices over time.
108
107
 
109
- To configure the Elasticsearch output to use Index Lifecycle Management, set the `ilm_enabled` flag to true in the output definition:
108
+ The use of Index Lifecycle Management is controlled by the `ilm_enabled` setting.
109
+ The `ilm_enabled` flag can be set to `true`, `false` (default) or `auto`.
110
110
 
111
- [source,ruby]
112
- output {
113
- elasticsearch {
114
- ilm_enabled => true
115
- }
116
- }
111
+ The use of Index Lifecycle Management is controlled by the `ilm_enabled` setting.
112
+ The `ilm_enabled` flag can be set to `true`, `false` (default) or `auto`.
117
113
 
118
- This will overwrite the index settings and adjust the Logstash template to write the necessary settings for the template
114
+ Setting `ilm_enabled` to `auto` will automatically detect whether the
115
+ Elasticsearch instance is version `7.0.0` and above and has Index Lifecycle Management enabled, and will enable its usage if so.
116
+
117
+ Setting `ilm_enabled` to `true` will enable the Index Lifecycle Management feature if it is available on the
118
+ Elasticsearch cluster - the plugin will not start if `ilm_enabled` is set to `true` and the Elasticsearch cluster does
119
+ not support ILM.
120
+
121
+ Enabling ILM support will overwrite the index settings and adjust the Logstash template to write the necessary settings for the template
119
122
  to support index lifecycle management, including the index policy and rollover alias to be used.
120
123
 
121
124
  Logstash will create a rollover alias for the indices to be written to, including a pattern for how the actual indices will be named, and unless an ILM policy that already exists has been specified,
@@ -133,9 +136,9 @@ See config below for an example:
133
136
  output {
134
137
  elasticsearch {
135
138
  ilm_enabled => true
136
- ilm_rollover_alias: "custom"
137
- ilm_pattern: "000001"
138
- ilm_policy: "custom_policy"
139
+ ilm_rollover_alias => "custom"
140
+ ilm_pattern => "000001"
141
+ ilm_policy => "custom_policy"
139
142
  }
140
143
  }
141
144
 
@@ -192,7 +195,7 @@ This plugin supports the following configuration options plus the <<plugins-{typ
192
195
  | <<plugins-{type}s-{plugin}-healthcheck_path>> |<<string,string>>|No
193
196
  | <<plugins-{type}s-{plugin}-hosts>> |<<uri,uri>>|No
194
197
  | <<plugins-{type}s-{plugin}-http_compression>> |<<boolean,boolean>>|No
195
- | <<plugins-{type}s-{plugin}-ilm_enabled>> |<<boolean,boolean>>|No
198
+ | <<plugins-{type}s-{plugin}-ilm_enabled>> |<<string,string>>, one of `["true", "false", "auto"]`|No
196
199
  | <<plugins-{type}s-{plugin}-ilm_pattern>> |<<string,string>>|No
197
200
  | <<plugins-{type}s-{plugin}-ilm_policy>> |<<string,string>>|No
198
201
  | <<plugins-{type}s-{plugin}-ilm_rollover_alias>> |<<string,string>>|No
@@ -374,10 +377,16 @@ Enable gzip compression on requests. Note that response compression is on by def
374
377
  [id="plugins-{type}s-{plugin}-ilm_enabled"]
375
378
  ===== `ilm_enabled`
376
379
 
377
- * Value type is <<boolean,boolean>>
380
+ * Value can be any of: `true`, `false`, `auto`
378
381
  * Default value is `false`
379
382
 
380
- Setting this flag to `true` will enable indices to be managed by the Index Lifecycle Management feature in Elasticsearch.
383
+ The default setting of `false` will disable the Index Lifecycle Management feature.
384
+
385
+ Setting this flag to `true` will enable Index Lifecycle Management feature, if the Elasticsearch cluster supports it. This is required
386
+ to enable Index Lifecycle Management on a version of Elasticsearch earlier than version `7.0.0`.
387
+
388
+ Setting this flag to `auto` will automatically enable the Index Lifecycle Management feature, if the Elasticsearch
389
+ cluster is running Elasticsearch version `7.0.0` or higher with the ILM feature enabled, and disable it otherwise.
381
390
 
382
391
  NOTE: This feature requires a Basic License or above to be installed on an Elasticsearch cluster version 6.6.0 or later
383
392
 
@@ -47,7 +47,6 @@ module LogStash; module Outputs; class ElasticSearch;
47
47
  sleep_interval = next_sleep_interval(sleep_interval)
48
48
  end
49
49
  if successful_connection?
50
- verify_ilm_readiness if ilm_enabled?
51
50
  install_template
52
51
  setup_ilm if ilm_enabled?
53
52
  end
@@ -349,6 +348,10 @@ module LogStash; module Outputs; class ElasticSearch;
349
348
  end
350
349
  end
351
350
 
351
+ def default_index?(index)
352
+ @index == LogStash::Outputs::ElasticSearch::CommonConfigs::DEFAULT_INDEX_NAME
353
+ end
354
+
352
355
  def dlq_enabled?
353
356
  # TODO there should be a better way to query if DLQ is enabled
354
357
  # See more in: https://github.com/elastic/logstash/issues/8064
@@ -5,6 +5,7 @@ module LogStash; module Outputs; class ElasticSearch
5
5
 
6
6
  DEFAULT_INDEX_NAME = "logstash-%{+YYYY.MM.dd}"
7
7
  DEFAULT_POLICY = "logstash-policy"
8
+ DEFAULT_ROLLOVER_ALIAS = 'logstash'
8
9
 
9
10
  def self.included(mod)
10
11
  # The index to write events to. This can be dynamic using the `%{foo}` syntax.
@@ -146,10 +147,10 @@ module LogStash; module Outputs; class ElasticSearch
146
147
  # ILM configurations (beta)
147
148
  # -----
148
149
  # Flag for enabling Index Lifecycle Management integration.
149
- mod.config :ilm_enabled, :validate => :boolean, :default => false
150
+ mod.config :ilm_enabled, :validate => [true, false, 'true', 'false', 'auto'], :default => false
150
151
 
151
152
  # Rollover alias used for indexing data. If rollover alias doesn't exist, Logstash will create it and map it to the relevant index
152
- mod.config :ilm_rollover_alias, :validate => :string, :default => 'logstash'
153
+ mod.config :ilm_rollover_alias, :validate => :string, :default => DEFAULT_ROLLOVER_ALIAS
153
154
 
154
155
  # appends “{now/d}-000001” by default for new index creation, subsequent rollover indices will increment based on this pattern i.e. “000002”
155
156
  # {now/d} is date math, and will insert the appropriate value automatically.
@@ -5,41 +5,66 @@ module LogStash; module Outputs; class ElasticSearch
5
5
 
6
6
  def setup_ilm
7
7
  return unless ilm_enabled?
8
- @logger.info("Using Index lifecycle management - this feature is currently in beta.")
9
- @logger.warn "Overwriting supplied index name with rollover alias #{@ilm_rollover_alias}" if @index != LogStash::Outputs::ElasticSearch::CommonConfigs::DEFAULT_INDEX_NAME
10
- @index = ilm_rollover_alias
8
+ if default_index?(@index) || !default_rollover_alias?(@ilm_rollover_alias)
9
+ logger.warn("Overwriting supplied index #{@index} with rollover alias #{@ilm_rollover_alias}") unless default_index?(@index)
10
+ @index = @ilm_rollover_alias
11
+ maybe_create_rollover_alias
12
+ maybe_create_ilm_policy
13
+ end
14
+ end
11
15
 
12
- maybe_create_rollover_alias
13
- maybe_create_ilm_policy
16
+ def default_rollover_alias?(rollover_alias)
17
+ rollover_alias == LogStash::Outputs::ElasticSearch::DEFAULT_ROLLOVER_ALIAS
14
18
  end
15
19
 
16
20
  def ilm_enabled?
17
- @ilm_enabled
21
+ return @ilm_actually_enabled if defined?(@ilm_actually_enabled)
22
+ @ilm_actually_enabled =
23
+ begin
24
+ if @ilm_enabled == 'auto'
25
+ if ilm_on_by_default?
26
+ ilm_ready, error = ilm_ready?
27
+ if !ilm_ready
28
+ @logger.info("Index Lifecycle Management is set to 'auto', but will be disabled - #{error}")
29
+ false
30
+ else
31
+ true
32
+ end
33
+ else
34
+ @logger.info("Index Lifecycle Management is set to 'auto', but will be disabled - Your Elasticsearch cluster is before 7.0.0, which is the minimum version required to automatically run Index Lifecycle Management")
35
+ false
36
+ end
37
+ elsif @ilm_enabled.to_s == 'true'
38
+ ilm_ready, error = ilm_ready?
39
+ raise LogStash::ConfigurationError,"Index Lifecycle Management is set to enabled in Logstash, but cannot be used - #{error}" unless ilm_ready
40
+ true
41
+ else
42
+ false
43
+ end
44
+ end
18
45
  end
19
46
 
20
- def verify_ilm_readiness
21
- return unless ilm_enabled?
47
+ def ilm_on_by_default?
48
+ maximum_seen_major_version >= 7
49
+ end
22
50
 
51
+ def ilm_ready?
23
52
  # Check the Elasticsearch instance for ILM readiness - this means that the version has to be a non-OSS release, with ILM feature
24
53
  # available and enabled.
25
54
  begin
26
55
  xpack = client.get_xpack_info
27
- features = xpack["features"]
56
+ features = xpack.nil? || xpack.empty? ? nil : xpack["features"]
28
57
  ilm = features.nil? ? nil : features["ilm"]
29
- raise LogStash::ConfigurationError, "Index Lifecycle management is enabled in logstash, but not installed on your Elasticsearch cluster" if features.nil? || ilm.nil?
30
- raise LogStash::ConfigurationError, "Index Lifecycle management is enabled in logstash, but not available in your Elasticsearch cluster" unless ilm['available']
31
- raise LogStash::ConfigurationError, "Index Lifecycle management is enabled in logstash, but not enabled in your Elasticsearch cluster" unless ilm['enabled']
32
-
33
- unless ilm_policy_default? || client.ilm_policy_exists?(ilm_policy)
34
- raise LogStash::ConfigurationError, "The specified ILM policy #{ilm_policy} does not exist on your Elasticsearch instance"
35
- end
36
-
58
+ return false, "Index Lifecycle management is not installed on your Elasticsearch cluster" if features.nil? || ilm.nil?
59
+ return false, "Index Lifecycle management is not available in your Elasticsearch cluster" unless ilm['available']
60
+ return false, "Index Lifecycle management is not enabled in your Elasticsearch cluster" unless ilm['enabled']
61
+ return true, nil
37
62
  rescue ::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError => e
38
63
  # Check xpack endpoint: If no xpack endpoint, then this version of Elasticsearch is not compatible
39
64
  if e.response_code == 404
40
- raise LogStash::ConfigurationError, "Index Lifecycle management is enabled in logstash, but not installed on your Elasticsearch cluster"
65
+ return false, "Index Lifecycle management is not installed on your Elasticsearch cluster"
41
66
  elsif e.response_code == 400
42
- raise LogStash::ConfigurationError, "Index Lifecycle management is enabled in logstash, but not installed on your Elasticsearch cluster"
67
+ return false, "Index Lifecycle management is not installed on your Elasticsearch cluster"
43
68
  else
44
69
  raise e
45
70
  end
@@ -53,8 +78,10 @@ module LogStash; module Outputs; class ElasticSearch
53
78
  end
54
79
 
55
80
  def maybe_create_ilm_policy
56
- if ilm_policy_default? && !client.ilm_policy_exists?(ilm_policy)
57
- client.ilm_policy_put(ilm_policy, policy_payload)
81
+ if ilm_policy_default?
82
+ client.ilm_policy_put(ilm_policy, policy_payload) unless client.ilm_policy_exists?(ilm_policy)
83
+ else
84
+ raise LogStash::ConfigurationError, "The specified ILM policy #{ilm_policy} does not exist on your Elasticsearch instance" unless client.ilm_policy_exists?(ilm_policy)
58
85
  end
59
86
  end
60
87
 
@@ -3,7 +3,13 @@ module LogStash; module Outputs; class ElasticSearch
3
3
  # To be mixed into the elasticsearch plugin base
4
4
  def self.install_template(plugin)
5
5
  return unless plugin.manage_template
6
- plugin.logger.info("Using mapping template from", :path => plugin.template)
6
+ if plugin.template.nil?
7
+ plugin.logger.info("Using default mapping template")
8
+ else
9
+ plugin.logger.info("Using mapping template from", :path => plugin.template)
10
+ end
11
+
12
+
7
13
  template = get_template(plugin.template, plugin.maximum_seen_major_version)
8
14
  add_ilm_settings_to_template(plugin, template) if plugin.ilm_enabled?
9
15
  plugin.logger.info("Attempting to install template", :manage_template => template)
@@ -23,7 +29,6 @@ module LogStash; module Outputs; class ElasticSearch
23
29
  end
24
30
 
25
31
  def self.add_ilm_settings_to_template(plugin, template)
26
- plugin.logger.info("Overwriting index patterns, as ILM is enabled.")
27
32
  # Overwrite any index patterns, and use the rollover alias. Use 'index_patterns' rather than 'template' for pattern
28
33
  # definition - remove any existing definition of 'template'
29
34
  template.delete('template') if template.include?('template')
@@ -48,7 +53,7 @@ module LogStash; module Outputs; class ElasticSearch
48
53
  end
49
54
 
50
55
  def self.read_template_file(template_path)
51
- raise ArgumentError, "Template file '#{@template_path}' could not be found!" unless ::File.exists?(template_path)
56
+ raise ArgumentError, "Template file '#{template_path}' could not be found!" unless ::File.exists?(template_path)
52
57
  template_data = ::IO.read(template_path)
53
58
  LogStash::Json.load(template_data)
54
59
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'logstash-output-elasticsearch'
3
- s.version = '9.3.2'
3
+ s.version = '9.4.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"
@@ -67,6 +67,13 @@ module ESHelper
67
67
  end
68
68
  end
69
69
 
70
+ RSpec::Matchers.define :have_index_pattern do |expected|
71
+ match do |actual|
72
+ test_against = Array(actual['index_patterns'].nil? ? actual['template'] : actual['index_patterns'])
73
+ test_against.include?(expected)
74
+ end
75
+ end
76
+
70
77
 
71
78
  def self.es_version_satisfies?(*requirement)
72
79
  es_version = RSpec.configuration.filter[:es_version] || ENV['ES_VERSION']
@@ -125,6 +132,38 @@ module ESHelper
125
132
  false
126
133
  end
127
134
  end
135
+
136
+ def max_docs_policy(max_docs)
137
+ {
138
+ "policy" => {
139
+ "phases"=> {
140
+ "hot" => {
141
+ "actions" => {
142
+ "rollover" => {
143
+ "max_docs" => max_docs
144
+ }
145
+ }
146
+ }
147
+ }
148
+ }
149
+ }
150
+ end
151
+
152
+ def max_age_policy(max_age)
153
+ {
154
+ "policy" => {
155
+ "phases"=> {
156
+ "hot" => {
157
+ "actions" => {
158
+ "rollover" => {
159
+ "max_age" => max_age
160
+ }
161
+ }
162
+ }
163
+ }
164
+ }
165
+ }
166
+ end
128
167
  end
129
168
 
130
169
  RSpec.configure do |config|
@@ -60,7 +60,11 @@ if ESHelper.es_version_satisfies?(">= 5")
60
60
  end
61
61
 
62
62
  it "sets the correct content-encoding header and body is compressed" do
63
- allow(subject.client.pool.adapter.client).to receive(:send).with(anything, /_template/, anything).and_call_original
63
+ # Allow xpack endpoint to be checked\
64
+ allow(subject.client.pool.adapter.client).to receive(:send).at_least(:once).with(anything, /_template/, anything).and_call_original
65
+ allow(subject.client.pool.adapter.client).to receive(:send).with(anything, /_xpack/, anything).and_call_original
66
+ allow(subject.client.pool.adapter.client).to receive(:send).with(anything, /logstash/, anything).and_call_original
67
+ allow(subject.client.pool.adapter.client).to receive(:send).with(anything, /_ilm/, anything).and_call_original
64
68
  expect(subject.client.pool.adapter.client).to receive(:send).
65
69
  with(anything, anything, {:headers=>{"Content-Encoding"=>"gzip", "Content-Type"=>"application/json"}, :body => a_valid_gzip_encoded_string}).
66
70
  and_call_original
@@ -1,47 +1,14 @@
1
1
  require_relative "../../../spec/es_spec_helper"
2
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 }
3
+ shared_examples_for 'an ILM enabled Logstash' do
30
4
 
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
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)}
42
9
 
43
- context 'when ilm is disabled in Logstash' do
44
- it 'should index documents normally' do
10
+ it 'should rollover when the policy max docs is reached' do
11
+ put_policy(@es,ilm_policy_name, policy)
45
12
  subject.register
46
13
 
47
14
  subject.multi_receive([
@@ -58,31 +25,38 @@ shared_examples_for 'an Elasticsearch instance that does not support index lifec
58
25
  LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0 ] })
59
26
  ])
60
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
+
61
36
  @es.indices.refresh
62
37
 
63
38
  # Wait or fail until everything's indexed.
64
39
  Stud::try(20.times) do
65
40
  r = @es.search
66
- expect(r).to have_hits(6)
41
+ expect(r).to have_hits(9)
67
42
  end
68
43
  indexes_written = @es.search['hits']['hits'].each_with_object(Hash.new(0)) do |x, res|
69
44
  index_written = x['_index']
70
45
  res[index_written] += 1
71
46
  end
72
- expect(indexes_written.count).to eq(1)
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)
73
51
  end
74
52
  end
75
53
 
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 }
54
+ context 'with a policy where the maximum number of documents is not reached' do
55
+ let (:policy) { large_max_doc_policy }
82
56
  let (:ilm_policy_name) { "custom-policy"}
83
57
  let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
84
58
 
85
- it 'should rollover when the policy max docs is reached' do
59
+ it 'should ingest into a single index when max docs is not reached' do
86
60
  put_policy(@es,ilm_policy_name, policy)
87
61
  subject.register
88
62
 
@@ -100,41 +74,53 @@ shared_examples_for 'an ILM enabled Logstash' do
100
74
  LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0 ] })
101
75
  ])
102
76
 
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
77
  @es.indices.refresh
112
78
 
113
79
  # Wait or fail until everything's indexed.
114
80
  Stud::try(20.times) do
115
81
  r = @es.search
116
- expect(r).to have_hits(9)
82
+ expect(r).to have_hits(6)
117
83
  end
118
84
  indexes_written = @es.search['hits']['hits'].each_with_object(Hash.new(0)) do |x, res|
119
85
  index_written = x['_index']
120
86
  res[index_written] += 1
121
87
  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)
88
+ expect(indexes_written.count).to eq(1)
89
+ expect(indexes_written["#{expected_index}-#{todays_date}-000001"]).to eq(6)
126
90
  end
127
91
  end
92
+ end
128
93
 
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"}
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"}
132
120
  let (:settings) { super.merge("ilm_policy" => ilm_policy_name)}
133
121
 
134
- it 'should ingest into a single index when max docs is not reached' do
135
- put_policy(@es,ilm_policy_name, policy)
122
+ it 'should not roll over indices' do
136
123
  subject.register
137
-
138
124
  subject.multi_receive([
139
125
  LogStash::Event.new("message" => "sample message here"),
140
126
  LogStash::Event.new("somemessage" => { "message" => "sample nested message here" }),
@@ -161,11 +147,82 @@ shared_examples_for 'an ILM enabled Logstash' do
161
147
  res[index_written] += 1
162
148
  end
163
149
  expect(indexes_written.count).to eq(1)
164
- expect(indexes_written["#{expected_index}-#{todays_date}-000001"]).to eq(6)
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
165
166
  end
166
167
  end
167
168
  end
168
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
169
226
 
170
227
  if ESHelper.es_version_satisfies?("<= 6.5")
171
228
  describe 'Pre-ILM versions of Elasticsearch', :integration => true do
@@ -179,9 +236,9 @@ if ESHelper.es_version_satisfies?(">= 6.6")
179
236
  end
180
237
 
181
238
  describe 'Elasticsearch has index lifecycle management enabled', :distribution => 'xpack', :integration => true do
239
+
182
240
  DEFAULT_INTERVAL = '600s'
183
241
 
184
- require "logstash/outputs/elasticsearch"
185
242
  let (:ilm_enabled) { true }
186
243
 
187
244
  let (:settings) {
@@ -190,38 +247,9 @@ if ESHelper.es_version_satisfies?(">= 6.6")
190
247
  "hosts" => "#{get_host_port()}"
191
248
  }
192
249
  }
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
-
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 }
225
253
 
226
254
  subject { LogStash::Outputs::ElasticSearch.new(settings) }
227
255
 
@@ -250,11 +278,9 @@ if ESHelper.es_version_satisfies?(">= 6.6")
250
278
  clean(@es)
251
279
  end
252
280
 
253
-
254
281
  context 'with ilm enabled' do
255
282
  let (:ilm_enabled) { true }
256
283
 
257
-
258
284
  context 'when using the default policy' do
259
285
  context 'with a custom pattern' do
260
286
  let (:settings) { super.merge("ilm_pattern" => "000001")}
@@ -267,7 +293,6 @@ if ESHelper.es_version_satisfies?(">= 6.6")
267
293
  end
268
294
  end
269
295
 
270
-
271
296
  it 'should install it if it is not present' do
272
297
  expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
273
298
  subject.register
@@ -283,10 +308,8 @@ if ESHelper.es_version_satisfies?(">= 6.6")
283
308
  expect(@es.get_alias(name: "logstash")).to include("logstash-#{todays_date}-000001")
284
309
  end
285
310
 
286
-
287
311
  it 'should ingest into a single index' do
288
312
  subject.register
289
-
290
313
  subject.multi_receive([
291
314
  LogStash::Event.new("message" => "sample message here"),
292
315
  LogStash::Event.new("somemessage" => { "message" => "sample nested message here" }),
@@ -321,18 +344,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
321
344
  context 'when not using the default policy' do
322
345
  let (:ilm_policy_name) {"new_one"}
323
346
  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
- }}}
347
+ let (:policy) { small_max_doc_policy }
336
348
 
337
349
  before do
338
350
  expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
@@ -349,18 +361,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
349
361
  context 'when using a time based policy' do
350
362
  let (:ilm_policy_name) {"new_one"}
351
363
  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
+ let (:policy) { max_age_policy("1d") }
364
365
 
365
366
  before do
366
367
  expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
@@ -373,9 +374,8 @@ if ESHelper.es_version_satisfies?(">= 6.6")
373
374
  expect{get_policy(@es, LogStash::Outputs::ElasticSearch::DEFAULT_POLICY)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
374
375
  end
375
376
  end
376
- context 'with the default template' do
377
- let(:expected_index) { "logstash" }
378
377
 
378
+ context 'with the default template' do
379
379
  it 'should create the rollover alias' do
380
380
  expect(@es.indices.exists_alias(index: expected_index)).to be_falsey
381
381
  subject.register
@@ -387,7 +387,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
387
387
  it 'should write the ILM settings into the template' do
388
388
  subject.register
389
389
  sleep(1)
390
- expect(@es.indices.get_template(name: "logstash")["logstash"]["index_patterns"]).to eq(["logstash-*"])
390
+ expect(@es.indices.get_template(name: "logstash")["logstash"]).to have_index_pattern("logstash-*")
391
391
  expect(@es.indices.get_template(name: "logstash")["logstash"]["settings"]['index']['lifecycle']['name']).to eq("logstash-policy")
392
392
  expect(@es.indices.get_template(name: "logstash")["logstash"]["settings"]['index']['lifecycle']['rollover_alias']).to eq("logstash")
393
393
  end
@@ -411,7 +411,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
411
411
  end
412
412
  let (:ilm_enabled) { true }
413
413
  let (:ilm_policy_name) { "custom-policy" }
414
-
414
+ let (:policy) { small_max_doc_policy }
415
415
 
416
416
  before :each do
417
417
  put_policy(@es,ilm_policy_name, policy)
@@ -442,7 +442,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
442
442
  it 'should write the ILM settings into the template' do
443
443
  subject.register
444
444
  sleep(1)
445
- expect(@es.indices.get_template(name: ilm_rollover_alias)[ilm_rollover_alias]["index_patterns"]).to eq(["#{ilm_rollover_alias}-*"])
445
+ expect(@es.indices.get_template(name: ilm_rollover_alias)[ilm_rollover_alias]).to have_index_pattern("#{ilm_rollover_alias}-*")
446
446
  expect(@es.indices.get_template(name: ilm_rollover_alias)[ilm_rollover_alias]["settings"]['index']['lifecycle']['name']).to eq(ilm_policy_name)
447
447
  expect(@es.indices.get_template(name: ilm_rollover_alias)[ilm_rollover_alias]["settings"]['index']['lifecycle']['rollover_alias']).to eq(ilm_rollover_alias)
448
448
  end
@@ -456,7 +456,7 @@ if ESHelper.es_version_satisfies?(">= 6.6")
456
456
  it 'should write the ILM settings into the template' do
457
457
  subject.register
458
458
  sleep(1)
459
- expect(@es.indices.get_template(name: template_name)[template_name]["index_patterns"]).to eq(["#{ilm_rollover_alias}-*"])
459
+ expect(@es.indices.get_template(name: template_name)[template_name]).to have_index_pattern("#{ilm_rollover_alias}-*")
460
460
  expect(@es.indices.get_template(name: template_name)[template_name]["settings"]['index']['lifecycle']['name']).to eq(ilm_policy_name)
461
461
  expect(@es.indices.get_template(name: template_name)[template_name]["settings"]['index']['lifecycle']['rollover_alias']).to eq(ilm_rollover_alias)
462
462
  end
@@ -465,78 +465,49 @@ if ESHelper.es_version_satisfies?(">= 6.6")
465
465
  end
466
466
  end
467
467
 
468
- context 'with ilm disabled' do
469
- let (:ilm_enabled) { false }
468
+ context 'when ilm_enabled is set to "auto"' do
469
+ let (:ilm_enabled) { 'auto' }
470
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)
471
+ if ESHelper.es_version_satisfies?(">=7.0")
472
+ context 'when Elasticsearch is version 7 or above' do
473
+ it_behaves_like 'an ILM enabled Logstash'
474
+ end
482
475
  end
483
476
 
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
477
+ if ESHelper.es_version_satisfies?('< 7.0')
478
+ context 'when Elasticsearch is version 7 or below' do
479
+ it_behaves_like 'an ILM disabled Logstash'
480
+ end
489
481
  end
482
+ end
490
483
 
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
484
+ context 'when ilm_enabled is the default' do
485
+ let (:settings) { super.tap{|x|x.delete('ilm_enabled')}}
513
486
 
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)
487
+ if ESHelper.es_version_satisfies?(">=7.0")
488
+ context 'when Elasticsearch is version 7 or above' do
489
+ it_behaves_like 'an ILM disabled Logstash'
525
490
  end
526
491
  end
527
492
 
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
493
+ if ESHelper.es_version_satisfies?('< 7.0')
494
+ context 'when Elasticsearch is version 7 or below' do
495
+ it_behaves_like 'an ILM disabled Logstash'
537
496
  end
538
497
  end
498
+ end
499
+
500
+ context 'with ilm disabled' do
501
+ let (:settings) { super.merge('ilm_enabled' => false )}
539
502
 
503
+ it_behaves_like 'an ILM disabled Logstash'
540
504
  end
505
+
506
+ context 'with ilm disabled using a string' do
507
+ let (:settings) { super.merge('ilm_enabled' => 'false' )}
508
+
509
+ it_behaves_like 'an ILM disabled Logstash'
510
+ end
511
+
541
512
  end
542
513
  end
@@ -100,7 +100,13 @@ describe "indexing" do
100
100
  }}
101
101
  end
102
102
  # Allow template to be checked for existence/installed
103
- allow(subject.client.pool.adapter.client).to receive(:send).with(anything, /_template/, anything).and_call_original
103
+ allow(subject.client.pool.adapter.client).to receive(:send).at_least(:once).with(anything, /_template/, anything).and_call_original
104
+ # Allow xpack endpoint to be checked\
105
+ allow(subject.client.pool.adapter.client).to receive(:send).with(anything, /_xpack/, anything).and_call_original
106
+ # Allow ilm policy to be checked for existence/installed
107
+ allow(subject.client.pool.adapter.client).to receive(:send).with(anything, /_ilm/, anything).and_call_original
108
+ # Allow write alias to be checked for existence/installed
109
+ allow(subject.client.pool.adapter.client).to receive(:send).with(anything, /logstash/, anything).and_call_original
104
110
  expect(subject.client.pool.adapter.client).to receive(:send).
105
111
  with(anything, anything, expected_manticore_opts).at_least(:once).
106
112
  and_call_original
@@ -19,6 +19,7 @@ describe LogStash::Outputs::ElasticSearch do
19
19
  allow(subject.client.pool).to receive(:start_sniffer)
20
20
  allow(subject.client.pool).to receive(:healthcheck!)
21
21
  allow(subject.client).to receive(:maximum_seen_major_version).at_least(:once).and_return(maximum_seen_major_version)
22
+ allow(subject.client).to receive(:get_xpack_info)
22
23
  subject.register
23
24
  subject.client.pool.adapter.manticore.respond_with(:body => "{}")
24
25
  end
@@ -15,6 +15,7 @@ describe "whitelisting error types in expected behavior" do
15
15
  subject.register
16
16
 
17
17
  allow(subject.client).to receive(:maximum_seen_major_version).and_return(0)
18
+ allow(subject.client).to receive(:get_xpack_info)
18
19
  allow(subject.client).to receive(:bulk).and_return(
19
20
  {
20
21
  "errors" => true,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-output-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.3.2
4
+ version: 9.4.0
5
5
  platform: java
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-05 00:00:00.000000000 Z
11
+ date: 2019-02-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement