logstash-input-elasticsearch 4.23.1 → 5.0.0

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.
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-input-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.23.1
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
- date: 2026-07-17 00:00:00.000000000 Z
11
+ date: 2024-12-18 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
- name: logstash-core-plugin-api
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - ">="
@@ -19,6 +19,7 @@ dependencies:
19
19
  - - "<="
20
20
  - !ruby/object:Gem::Version
21
21
  version: '2.99'
22
+ name: logstash-core-plugin-api
22
23
  type: :runtime
23
24
  prerelease: false
24
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -30,12 +31,12 @@ dependencies:
30
31
  - !ruby/object:Gem::Version
31
32
  version: '2.99'
32
33
  - !ruby/object:Gem::Dependency
33
- name: logstash-mixin-ecs_compatibility_support
34
34
  requirement: !ruby/object:Gem::Requirement
35
35
  requirements:
36
36
  - - "~>"
37
37
  - !ruby/object:Gem::Version
38
38
  version: '1.3'
39
+ name: logstash-mixin-ecs_compatibility_support
39
40
  type: :runtime
40
41
  prerelease: false
41
42
  version_requirements: !ruby/object:Gem::Requirement
@@ -44,12 +45,12 @@ dependencies:
44
45
  - !ruby/object:Gem::Version
45
46
  version: '1.3'
46
47
  - !ruby/object:Gem::Dependency
47
- name: logstash-mixin-event_support
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  requirements:
50
50
  - - "~>"
51
51
  - !ruby/object:Gem::Version
52
52
  version: '1.0'
53
+ name: logstash-mixin-event_support
53
54
  type: :runtime
54
55
  prerelease: false
55
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,12 +59,12 @@ dependencies:
58
59
  - !ruby/object:Gem::Version
59
60
  version: '1.0'
60
61
  - !ruby/object:Gem::Dependency
61
- name: logstash-mixin-validator_support
62
62
  requirement: !ruby/object:Gem::Requirement
63
63
  requirements:
64
64
  - - "~>"
65
65
  - !ruby/object:Gem::Version
66
66
  version: '1.0'
67
+ name: logstash-mixin-validator_support
67
68
  type: :runtime
68
69
  prerelease: false
69
70
  version_requirements: !ruby/object:Gem::Requirement
@@ -72,12 +73,12 @@ dependencies:
72
73
  - !ruby/object:Gem::Version
73
74
  version: '1.0'
74
75
  - !ruby/object:Gem::Dependency
75
- name: logstash-mixin-scheduler
76
76
  requirement: !ruby/object:Gem::Requirement
77
77
  requirements:
78
78
  - - "~>"
79
79
  - !ruby/object:Gem::Version
80
80
  version: '1.0'
81
+ name: logstash-mixin-scheduler
81
82
  type: :runtime
82
83
  prerelease: false
83
84
  version_requirements: !ruby/object:Gem::Requirement
@@ -86,15 +87,12 @@ dependencies:
86
87
  - !ruby/object:Gem::Version
87
88
  version: '1.0'
88
89
  - !ruby/object:Gem::Dependency
89
- name: elasticsearch
90
90
  requirement: !ruby/object:Gem::Requirement
91
91
  requirements:
92
92
  - - ">="
93
93
  - !ruby/object:Gem::Version
94
94
  version: 7.17.9
95
- - - "<"
96
- - !ruby/object:Gem::Version
97
- version: '9'
95
+ name: elasticsearch
98
96
  type: :runtime
99
97
  prerelease: false
100
98
  version_requirements: !ruby/object:Gem::Requirement
@@ -102,16 +100,13 @@ dependencies:
102
100
  - - ">="
103
101
  - !ruby/object:Gem::Version
104
102
  version: 7.17.9
105
- - - "<"
106
- - !ruby/object:Gem::Version
107
- version: '9'
108
103
  - !ruby/object:Gem::Dependency
109
- name: logstash-mixin-ca_trusted_fingerprint_support
110
104
  requirement: !ruby/object:Gem::Requirement
111
105
  requirements:
112
106
  - - "~>"
113
107
  - !ruby/object:Gem::Version
114
108
  version: '1.0'
109
+ name: logstash-mixin-ca_trusted_fingerprint_support
115
110
  type: :runtime
116
111
  prerelease: false
117
112
  version_requirements: !ruby/object:Gem::Requirement
@@ -120,12 +115,12 @@ dependencies:
120
115
  - !ruby/object:Gem::Version
121
116
  version: '1.0'
122
117
  - !ruby/object:Gem::Dependency
123
- name: logstash-mixin-normalize_config_support
124
118
  requirement: !ruby/object:Gem::Requirement
125
119
  requirements:
126
120
  - - "~>"
127
121
  - !ruby/object:Gem::Version
128
122
  version: '1.0'
123
+ name: logstash-mixin-normalize_config_support
129
124
  type: :runtime
130
125
  prerelease: false
131
126
  version_requirements: !ruby/object:Gem::Requirement
@@ -134,12 +129,12 @@ dependencies:
134
129
  - !ruby/object:Gem::Version
135
130
  version: '1.0'
136
131
  - !ruby/object:Gem::Dependency
137
- name: tzinfo
138
132
  requirement: !ruby/object:Gem::Requirement
139
133
  requirements:
140
134
  - - ">="
141
135
  - !ruby/object:Gem::Version
142
136
  version: '0'
137
+ name: tzinfo
143
138
  type: :runtime
144
139
  prerelease: false
145
140
  version_requirements: !ruby/object:Gem::Requirement
@@ -148,12 +143,12 @@ dependencies:
148
143
  - !ruby/object:Gem::Version
149
144
  version: '0'
150
145
  - !ruby/object:Gem::Dependency
151
- name: tzinfo-data
152
146
  requirement: !ruby/object:Gem::Requirement
153
147
  requirements:
154
148
  - - ">="
155
149
  - !ruby/object:Gem::Version
156
150
  version: '0'
151
+ name: tzinfo-data
157
152
  type: :runtime
158
153
  prerelease: false
159
154
  version_requirements: !ruby/object:Gem::Requirement
@@ -162,12 +157,12 @@ dependencies:
162
157
  - !ruby/object:Gem::Version
163
158
  version: '0'
164
159
  - !ruby/object:Gem::Dependency
165
- name: manticore
166
160
  requirement: !ruby/object:Gem::Requirement
167
161
  requirements:
168
162
  - - ">="
169
163
  - !ruby/object:Gem::Version
170
164
  version: 0.7.1
165
+ name: manticore
171
166
  type: :runtime
172
167
  prerelease: false
173
168
  version_requirements: !ruby/object:Gem::Requirement
@@ -176,12 +171,12 @@ dependencies:
176
171
  - !ruby/object:Gem::Version
177
172
  version: 0.7.1
178
173
  - !ruby/object:Gem::Dependency
179
- name: logstash-codec-plain
180
174
  requirement: !ruby/object:Gem::Requirement
181
175
  requirements:
182
176
  - - ">="
183
177
  - !ruby/object:Gem::Version
184
178
  version: '0'
179
+ name: logstash-codec-plain
185
180
  type: :development
186
181
  prerelease: false
187
182
  version_requirements: !ruby/object:Gem::Requirement
@@ -190,12 +185,12 @@ dependencies:
190
185
  - !ruby/object:Gem::Version
191
186
  version: '0'
192
187
  - !ruby/object:Gem::Dependency
193
- name: logstash-devutils
194
188
  requirement: !ruby/object:Gem::Requirement
195
189
  requirements:
196
190
  - - ">="
197
191
  - !ruby/object:Gem::Version
198
192
  version: '0'
193
+ name: logstash-devutils
199
194
  type: :development
200
195
  prerelease: false
201
196
  version_requirements: !ruby/object:Gem::Requirement
@@ -204,12 +199,12 @@ dependencies:
204
199
  - !ruby/object:Gem::Version
205
200
  version: '0'
206
201
  - !ruby/object:Gem::Dependency
207
- name: timecop
208
202
  requirement: !ruby/object:Gem::Requirement
209
203
  requirements:
210
204
  - - ">="
211
205
  - !ruby/object:Gem::Version
212
206
  version: '0'
207
+ name: timecop
213
208
  type: :development
214
209
  prerelease: false
215
210
  version_requirements: !ruby/object:Gem::Requirement
@@ -218,12 +213,12 @@ dependencies:
218
213
  - !ruby/object:Gem::Version
219
214
  version: '0'
220
215
  - !ruby/object:Gem::Dependency
221
- name: cabin
222
216
  requirement: !ruby/object:Gem::Requirement
223
217
  requirements:
224
218
  - - "~>"
225
219
  - !ruby/object:Gem::Version
226
220
  version: '0.6'
221
+ name: cabin
227
222
  type: :development
228
223
  prerelease: false
229
224
  version_requirements: !ruby/object:Gem::Requirement
@@ -232,12 +227,12 @@ dependencies:
232
227
  - !ruby/object:Gem::Version
233
228
  version: '0.6'
234
229
  - !ruby/object:Gem::Dependency
235
- name: webrick
236
230
  requirement: !ruby/object:Gem::Requirement
237
231
  requirements:
238
232
  - - ">="
239
233
  - !ruby/object:Gem::Version
240
234
  version: '0'
235
+ name: webrick
241
236
  type: :development
242
237
  prerelease: false
243
238
  version_requirements: !ruby/object:Gem::Requirement
@@ -246,12 +241,12 @@ dependencies:
246
241
  - !ruby/object:Gem::Version
247
242
  version: '0'
248
243
  - !ruby/object:Gem::Dependency
249
- name: rufus-scheduler
250
244
  requirement: !ruby/object:Gem::Requirement
251
245
  requirements:
252
246
  - - "~>"
253
247
  - !ruby/object:Gem::Version
254
248
  version: 3.0.9
249
+ name: rufus-scheduler
255
250
  type: :development
256
251
  prerelease: false
257
252
  version_requirements: !ruby/object:Gem::Requirement
@@ -277,35 +272,27 @@ files:
277
272
  - lib/logstash/helpers/loggable_try.rb
278
273
  - lib/logstash/inputs/elasticsearch.rb
279
274
  - lib/logstash/inputs/elasticsearch/aggregation.rb
280
- - lib/logstash/inputs/elasticsearch/cursor_tracker.rb
281
- - lib/logstash/inputs/elasticsearch/esql.rb
282
275
  - lib/logstash/inputs/elasticsearch/paginated_search.rb
283
276
  - lib/logstash/inputs/elasticsearch/patches/_elasticsearch_transport_connections_selector.rb
284
277
  - lib/logstash/inputs/elasticsearch/patches/_elasticsearch_transport_http_manticore.rb
285
278
  - logstash-input-elasticsearch.gemspec
286
279
  - spec/es_helper.rb
287
- - spec/fixtures/test_certs/GENERATED_AT
288
280
  - spec/fixtures/test_certs/ca.crt
289
281
  - spec/fixtures/test_certs/ca.der.sha256
290
282
  - spec/fixtures/test_certs/ca.key
291
- - spec/fixtures/test_certs/es.chain.crt
292
283
  - spec/fixtures/test_certs/es.crt
293
284
  - spec/fixtures/test_certs/es.key
294
- - spec/fixtures/test_certs/renew.sh
295
- - spec/inputs/cursor_tracker_spec.rb
296
- - spec/inputs/elasticsearch_esql_spec.rb
297
285
  - spec/inputs/elasticsearch_spec.rb
298
286
  - spec/inputs/elasticsearch_ssl_spec.rb
299
- - spec/inputs/integration/elasticsearch_esql_spec.rb
300
287
  - spec/inputs/integration/elasticsearch_spec.rb
301
288
  - spec/inputs/paginated_search_spec.rb
302
- - version
303
- homepage: https://elastic.co/logstash
289
+ homepage: http://www.elastic.co/guide/en/logstash/current/index.html
304
290
  licenses:
305
291
  - Apache License (2.0)
306
292
  metadata:
307
293
  logstash_plugin: 'true'
308
294
  logstash_group: input
295
+ post_install_message:
309
296
  rdoc_options: []
310
297
  require_paths:
311
298
  - lib
@@ -320,23 +307,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
320
307
  - !ruby/object:Gem::Version
321
308
  version: '0'
322
309
  requirements: []
323
- rubygems_version: 3.6.3
310
+ rubygems_version: 3.3.26
311
+ signing_key:
324
312
  specification_version: 4
325
313
  summary: Reads query results from an Elasticsearch cluster
326
314
  test_files:
327
315
  - spec/es_helper.rb
328
- - spec/fixtures/test_certs/GENERATED_AT
329
316
  - spec/fixtures/test_certs/ca.crt
330
317
  - spec/fixtures/test_certs/ca.der.sha256
331
318
  - spec/fixtures/test_certs/ca.key
332
- - spec/fixtures/test_certs/es.chain.crt
333
319
  - spec/fixtures/test_certs/es.crt
334
320
  - spec/fixtures/test_certs/es.key
335
- - spec/fixtures/test_certs/renew.sh
336
- - spec/inputs/cursor_tracker_spec.rb
337
- - spec/inputs/elasticsearch_esql_spec.rb
338
321
  - spec/inputs/elasticsearch_spec.rb
339
322
  - spec/inputs/elasticsearch_ssl_spec.rb
340
- - spec/inputs/integration/elasticsearch_esql_spec.rb
341
323
  - spec/inputs/integration/elasticsearch_spec.rb
342
324
  - spec/inputs/paginated_search_spec.rb
@@ -1,58 +0,0 @@
1
- require 'fileutils'
2
-
3
- module LogStash; module Inputs; class Elasticsearch
4
- class CursorTracker
5
- include LogStash::Util::Loggable
6
-
7
- attr_reader :last_value
8
-
9
- def initialize(last_run_metadata_path:, tracking_field:, tracking_field_seed:)
10
- @last_run_metadata_path = last_run_metadata_path
11
- @last_value_hashmap = Java::java.util.concurrent.ConcurrentHashMap.new
12
- @last_value = IO.read(@last_run_metadata_path) rescue nil || tracking_field_seed
13
- @tracking_field = tracking_field
14
- logger.info "Starting value for cursor field \"#{@tracking_field}\": #{@last_value}"
15
- @mutex = Mutex.new
16
- end
17
-
18
- def checkpoint_cursor(intermediate: true)
19
- @mutex.synchronize do
20
- if intermediate
21
- # in intermediate checkpoints pick the smallest
22
- converge_last_value {|v1, v2| v1 < v2 ? v1 : v2}
23
- else
24
- # in the last search of a PIT choose the largest
25
- converge_last_value {|v1, v2| v1 > v2 ? v1 : v2}
26
- @last_value_hashmap.clear
27
- end
28
- IO.write(@last_run_metadata_path, @last_value)
29
- end
30
- end
31
-
32
- def converge_last_value(&block)
33
- return if @last_value_hashmap.empty?
34
- new_last_value = @last_value_hashmap.reduceValues(1000, &block)
35
- logger.debug? && logger.debug("converge_last_value: got #{@last_value_hashmap.values.inspect}. won: #{new_last_value}")
36
- return if new_last_value == @last_value
37
- @last_value = new_last_value
38
- logger.info "New cursor value for field \"#{@tracking_field}\" is: #{new_last_value}"
39
- end
40
-
41
- def record_last_value(event)
42
- value = event.get(@tracking_field)
43
- logger.trace? && logger.trace("storing last_value if #{@tracking_field} for #{Thread.current.object_id}: #{value}")
44
- @last_value_hashmap.put(Thread.current.object_id, value)
45
- end
46
-
47
- def inject_cursor(query_json)
48
- # ":present" means "now - 30s" to avoid grabbing partially visible data in the PIT
49
- result = query_json.gsub(":last_value", @last_value.to_s).gsub(":present", now_minus_30s)
50
- logger.debug("inject_cursor: injected values for ':last_value' and ':present'", :query => result)
51
- result
52
- end
53
-
54
- def now_minus_30s
55
- Java::java.time.Instant.now.minusSeconds(30).to_s
56
- end
57
- end
58
- end; end; end
@@ -1,153 +0,0 @@
1
- require 'logstash/helpers/loggable_try'
2
-
3
- module LogStash
4
- module Inputs
5
- class Elasticsearch
6
- class Esql
7
- include LogStash::Util::Loggable
8
-
9
- ESQL_JOB = "ES|QL job"
10
-
11
- ESQL_PARSERS_BY_TYPE = Hash.new(lambda { |x| x }).merge(
12
- 'date' => ->(value) { value && LogStash::Timestamp.new(value) },
13
- )
14
-
15
- # Initialize the ESQL query executor
16
- # @param client [Elasticsearch::Client] The Elasticsearch client instance
17
- # @param plugin [LogStash::Inputs::Elasticsearch] The parent plugin instance
18
- def initialize(client, plugin)
19
- @client = client
20
- @event_decorator = plugin.method(:decorate_event)
21
- @retries = plugin.params["retries"]
22
-
23
- target_field = plugin.params["target"]
24
- if target_field
25
- def self.apply_target(path); "[#{target_field}][#{path}]"; end
26
- else
27
- def self.apply_target(path); path; end
28
- end
29
-
30
- @query = plugin.params["query"]
31
- unless @query.include?('METADATA')
32
- logger.info("`METADATA` not found the query. `_id`, `_version` and `_index` will not be available in the result", {:query => @query})
33
- end
34
- logger.debug("ES|QL executor initialized with", {:query => @query})
35
- end
36
-
37
- # Execute the ESQL query and process results
38
- # @param output_queue [Queue] The queue to push processed events to
39
- # @param query A query (to obey interface definition)
40
- def do_run(output_queue, query)
41
- logger.info("ES|QL executor has started")
42
- response = retryable(ESQL_JOB) do
43
- @client.esql.query({ body: { query: @query }, format: 'json', drop_null_columns: true })
44
- end
45
- # retriable already printed error details
46
- return if response == false
47
-
48
- if response&.headers&.dig("warning")
49
- logger.warn("ES|QL executor received warning", {:warning_message => response.headers["warning"]})
50
- end
51
- columns = response['columns']&.freeze
52
- values = response['values']&.freeze
53
- logger.debug("ES|QL query response size: #{values&.size}")
54
-
55
- process_response(columns, values, output_queue) if columns && values
56
- end
57
-
58
- # Execute a retryable operation with proper error handling
59
- # @param job_name [String] Name of the job for logging purposes
60
- # @yield The block to execute
61
- # @return [Boolean] true if successful, false otherwise
62
- def retryable(job_name, &block)
63
- stud_try = ::LogStash::Helpers::LoggableTry.new(logger, job_name)
64
- stud_try.try((@retries + 1).times) { yield }
65
- rescue => e
66
- error_details = {:message => e.message, :cause => e.cause}
67
- error_details[:backtrace] = e.backtrace if logger.debug?
68
- logger.error("#{job_name} failed with ", error_details)
69
- false
70
- end
71
-
72
- private
73
-
74
- # Process the ESQL response and push events to the output queue
75
- # @param columns [Array[Hash]] The ESQL query response columns
76
- # @param values [Array[Array]] The ESQL query response hits
77
- # @param output_queue [Queue] The queue to push processed events to
78
- def process_response(columns, values, output_queue)
79
- column_specs = columns.map { |column| ColumnSpec.new(column) }
80
- sub_element_mark_map = mark_sub_elements(column_specs)
81
- multi_fields = sub_element_mark_map.filter_map { |key, val| key.name if val == true }
82
- logger.warn("Multi-fields found in ES|QL result and they will not be available in the event. Please use `RENAME` command if you want to include them.", { :detected_multi_fields => multi_fields }) if multi_fields.any?
83
-
84
- values.each do |row|
85
- event = column_specs.zip(row).each_with_object(LogStash::Event.new) do |(column, value), event|
86
- # `unless value.nil?` is a part of `drop_null_columns` that if some of columns' values are not `nil`, `nil` values appear
87
- # we should continuously filter out them to achieve full `drop_null_columns` on each individual row (ideal `LIMIT 1` result)
88
- # we also exclude sub-elements of main field
89
- if value && sub_element_mark_map[column] == false
90
- field_reference = apply_target(column.field_reference)
91
- event.set(field_reference, ESQL_PARSERS_BY_TYPE[column.type].call(value))
92
- end
93
- end
94
- @event_decorator.call(event)
95
- output_queue << event
96
- rescue => e
97
- # if event creation fails with whatever reason, inform user and tag with failure and return entry as it is
98
- logger.warn("Event creation error, ", message: e.message, exception: e.class, data: { "columns" => columns, "values" => [row] })
99
- failed_event = LogStash::Event.new("columns" => columns, "values" => [row], "tags" => ['_elasticsearch_input_failure'])
100
- output_queue << failed_event
101
- end
102
- end
103
-
104
- # Determines whether each column in a collection is a nested sub-element (example "user.age")
105
- # of another column in the same collection (example "user").
106
- #
107
- # @param columns [Array<ColumnSpec>] An array of objects with a `name` attribute representing field paths.
108
- # @return [Hash<ColumnSpec, Boolean>] A hash mapping each column to `true` if it is a sub-element of another field, `false` otherwise.
109
- # Time complexity: (O(NlogN+N*K)) where K is the number of conflict depth
110
- # without (`prefix_set`) memoization, it would be O(N^2)
111
- def mark_sub_elements(columns)
112
- # Sort columns by name length (ascending)
113
- sorted_columns = columns.sort_by { |c| c.name.length }
114
- prefix_set = Set.new # memoization set
115
-
116
- sorted_columns.each_with_object({}) do |column, memo|
117
- # Split the column name into parts (e.g., "user.profile.age" → ["user", "profile", "age"])
118
- parts = column.name.split('.')
119
-
120
- # Generate all possible parent prefixes (e.g., "user", "user.profile")
121
- # and check if any parent prefix exists in the set
122
- parent_prefixes = (0...parts.size - 1).map { |i| parts[0..i].join('.') }
123
- memo[column] = parent_prefixes.any? { |prefix| prefix_set.include?(prefix) }
124
- prefix_set.add(column.name)
125
- end
126
- end
127
- end
128
-
129
- # Class representing a column specification in the ESQL response['columns']
130
- # The class's main purpose is to provide a structure for the event key
131
- # columns is an array with `name` and `type` pair (example: `{"name"=>"@timestamp", "type"=>"date"}`)
132
- # @attr_reader :name [String] The name of the column
133
- # @attr_reader :type [String] The type of the column
134
- class ColumnSpec
135
- attr_reader :name, :type
136
-
137
- def initialize(spec)
138
- @name = isolate(spec.fetch('name'))
139
- @type = isolate(spec.fetch('type'))
140
- end
141
-
142
- def field_reference
143
- @_field_reference ||= '[' + name.gsub('.', '][') + ']'
144
- end
145
-
146
- private
147
- def isolate(value)
148
- value.frozen? ? value : value.clone.freeze
149
- end
150
- end
151
- end
152
- end
153
- end
@@ -1 +0,0 @@
1
- 2026-01-23T17:38:25+01:00
@@ -1,38 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIDIzCCAgugAwIBAgIBATANBgkqhkiG9w0BAQsFADA0MTIwMAYDVQQDEylFbGFz
3
- dGljIENlcnRpZmljYXRlIFRvb2wgQXV0b2dlbmVyYXRlZCBDQTAeFw0yNjAxMjMx
4
- NjM4MjVaFw0yNzAxMjMxNjM4MjVaMA0xCzAJBgNVBAMTAmVzMIIBIjANBgkqhkiG
5
- 9w0BAQEFAAOCAQ8AMIIBCgKCAQEArZLZvLSWDK7Ul+AaBnjU81dsfaow8zOjCC5V
6
- V21nXpYzQJoQbuWcvGYxwL7ZDs2ca4Wc8BVCj1NDduHuP7U+QIlUdQpl8kh5a0Zz
7
- 36pcFw7UyF51/AzWixJrht/Azzkb5cpZtE22ZK0KhS4oCsjJmTN0EABAsGhDI9/c
8
- MjNrUC7iP0dvfOuzAPp7ufY83h98jKKXUYV24snbbvmqoWI6GQQNSG/sEo1+1UGH
9
- /z07/mVKoBAa5DVoNGvxN0fCE7vW7hkhT8+frJcsYFatAbnf6ql0KzEa8lN9u0gR
10
- hQNM3zcKKsjEMomBzVBc4SV3KXO0d/jGdDtlqsm2oXqlTMdtGwIDAQABo2cwZTAY
11
- BgNVHREEETAPgg1lbGFzdGljc2VhcmNoMAkGA1UdEwQCMAAwHQYDVR0OBBYEFFQU
12
- K+6Cg2kExRj1xSDzEi4kkgKXMB8GA1UdIwQYMBaAFMgkye5+2l+TE0I6RsXRHjGB
13
- wpBGMA0GCSqGSIb3DQEBCwUAA4IBAQCDFHoe8ntx/D69gb8uVQhUDI2ERb0Hocbh
14
- BpQVidsKEv220zmZW3O9PX0aN4j3e4HUeRNSdLmtN+sXJ1xCMjHlzA5z5wYJOk2y
15
- 4B/eCOzHoHfvR+l5NUSemZ5mk8V+gThGydPmLZBN3afjzd3NJ7NVaCA8cyKwe2jr
16
- AMrIdGL5usoBSdbd7Ww0nWhLhqxmmV79+orCwAPJxkzsgFDK+vfIw4VHERXNoIPe
17
- WKVBGpUCFPSfosLo9fSziNDXL71CrWZlPXt3Otip4QKQV5sZI2zxm1JtHdHX6Ul1
18
- X7xkcUR5cOF0InxefGl9VHIZTYC5kSzAz95WV068j2Jxgu28GRP5
19
- -----END CERTIFICATE-----
20
- -----BEGIN CERTIFICATE-----
21
- MIIDFTCCAf2gAwIBAgIBATANBgkqhkiG9w0BAQsFADA0MTIwMAYDVQQDEylFbGFz
22
- dGljIENlcnRpZmljYXRlIFRvb2wgQXV0b2dlbmVyYXRlZCBDQTAeFw0yNjAxMjMx
23
- NjM4MjVaFw0yNzAxMjMxNjM4MjVaMDQxMjAwBgNVBAMTKUVsYXN0aWMgQ2VydGlm
24
- aWNhdGUgVG9vbCBBdXRvZ2VuZXJhdGVkIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
25
- AQ8AMIIBCgKCAQEArUe66xG4Y2zO13gRC+rBwyvxe+c01pqV6ukw6isIbJIQWs1/
26
- QfEMhUwYwKs6/UXxK+VwardcA2zYwngXbGGEtms+mpUfH5CdJnrqW7lHz1BVK4yH
27
- 90IzGE0GU4D90OW/L4QkGX0fv3VQbL8KGFKBoF04pXIaSGMStFN4wirutHtQboYv
28
- 99X4kbLjVSIuubUpA/v9dUP1TNl8ar+HKUWRM96ijHkFTF3FR0NnZyt44gP5qC0h
29
- i4lUiR6Uo9D6WMFjeRYFF7GolCy/I1SzWBmmOnNhQLO5VxcNG4ldhBcapZeGwE98
30
- m/5lxLIwgFR9ZP8bXdxZTWLC58/LQ2NqOjA9mwIDAQABozIwMDAPBgNVHRMBAf8E
31
- BTADAQH/MB0GA1UdDgQWBBTIJMnuftpfkxNCOkbF0R4xgcKQRjANBgkqhkiG9w0B
32
- AQsFAAOCAQEAgZPz/e29AepHZu8uuO6+75b6Uf88m8x5m7XL13m9+vTTSqLvCiBw
33
- JCf5caO73iOx8AlTT2iSlKPAS/7ogik5anZziqweHmBakb+HNQcUB4Vv4VBo5Ai3
34
- SdOm28uu4EznVLUILPUHl4FQGxhn6ba1tLEWgxlD/ynBtfcmh9UFtBqIawrpAArv
35
- TKwGBSkcSxh/yOIo+qbyBh9EyxxlGW/Z08m9qjNqHATDxCelcTsQLhCHkvNShR4j
36
- v1sFw5XQ8H3zQU6w4WzV81A3K8erIU8WnvdisXLk0T1VB5KURy4+UDyw44tOAPD2
37
- vBq3gYLgcVEMYVfOWCzDy7LS49leXRzAOA==
38
- -----END CERTIFICATE-----
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- set -e
4
- cd "$(dirname "$0")"
5
-
6
- openssl x509 -x509toreq -in ca.crt -copy_extensions copyall -signkey ca.key -out ca.csr
7
- openssl x509 -req -copy_extensions copyall -days 365 -in ca.csr -set_serial 0x01 -signkey ca.key -out ca.crt && rm ca.csr
8
- openssl x509 -in ca.crt -outform der | sha256sum | awk '{print $1}' > ca.der.sha256
9
-
10
- openssl x509 -x509toreq -in es.crt -copy_extensions copyall -signkey es.key -out es.csr
11
- openssl x509 -req -copy_extensions copyall -days 365 -in es.csr -set_serial 0x01 -CA ca.crt -CAkey ca.key -out es.crt && rm es.csr
12
- cat es.crt ca.crt > es.chain.crt
13
-
14
- # output ISO8601 timestamp to file
15
- date -Iseconds > GENERATED_AT
@@ -1,72 +0,0 @@
1
- # encoding: utf-8
2
- require "logstash/devutils/rspec/spec_helper"
3
- require "logstash/devutils/rspec/shared_examples"
4
- require "logstash/inputs/elasticsearch"
5
- require "logstash/inputs/elasticsearch/cursor_tracker"
6
-
7
- describe LogStash::Inputs::Elasticsearch::CursorTracker do
8
-
9
- let(:last_run_metadata_path) { Tempfile.new('cursor_tracker_testing').path }
10
- let(:tracking_field_seed) { "1980-01-01T23:59:59.999999999Z" }
11
- let(:options) do
12
- {
13
- :last_run_metadata_path => last_run_metadata_path,
14
- :tracking_field => "my_field",
15
- :tracking_field_seed => tracking_field_seed
16
- }
17
- end
18
-
19
- subject { described_class.new(**options) }
20
-
21
- it "creating a class works" do
22
- expect(subject).to be_a described_class
23
- end
24
-
25
- describe "checkpoint_cursor" do
26
- before(:each) do
27
- subject.checkpoint_cursor(intermediate: false) # store seed value
28
- [
29
- Thread.new(subject) {|subject| subject.record_last_value(LogStash::Event.new("my_field" => "2025-01-03T23:59:59.999999999Z")) },
30
- Thread.new(subject) {|subject| subject.record_last_value(LogStash::Event.new("my_field" => "2025-01-01T23:59:59.999999999Z")) },
31
- Thread.new(subject) {|subject| subject.record_last_value(LogStash::Event.new("my_field" => "2025-01-02T23:59:59.999999999Z")) },
32
- ].each(&:join)
33
- end
34
- context "when doing intermediate checkpoint" do
35
- it "persists the smallest value" do
36
- subject.checkpoint_cursor(intermediate: true)
37
- expect(IO.read(last_run_metadata_path)).to eq("2025-01-01T23:59:59.999999999Z")
38
- end
39
- end
40
- context "when doing non-intermediate checkpoint" do
41
- it "persists the largest value" do
42
- subject.checkpoint_cursor(intermediate: false)
43
- expect(IO.read(last_run_metadata_path)).to eq("2025-01-03T23:59:59.999999999Z")
44
- end
45
- end
46
- end
47
-
48
- describe "inject_cursor" do
49
- let(:new_value) { "2025-01-03T23:59:59.999999999Z" }
50
- let(:fake_now) { "2026-09-19T23:59:59.999999999Z" }
51
-
52
- let(:query) do
53
- %q[
54
- { "query": { "range": { "event.ingested": { "gt": :last_value, "lt": :present}}}, "sort": [ { "event.ingested": {"order": "asc", "format": "strict_date_optional_time_nanos", "numeric_type" : "date_nanos" } } ] }
55
- ]
56
- end
57
-
58
- before(:each) do
59
- subject.record_last_value(LogStash::Event.new("my_field" => new_value))
60
- subject.checkpoint_cursor(intermediate: false)
61
- allow(subject).to receive(:now_minus_30s).and_return(fake_now)
62
- end
63
-
64
- it "injects the value of the cursor into json query if it contains :last_value" do
65
- expect(subject.inject_cursor(query)).to match(/#{new_value}/)
66
- end
67
-
68
- it "injects current time into json query if it contains :present" do
69
- expect(subject.inject_cursor(query)).to match(/#{fake_now}/)
70
- end
71
- end
72
- end