logstash-output-opensearch 1.1.0-java → 2.0.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/COMPATIBILITY.md +5 -3
- data/CONTRIBUTING.md +26 -0
- data/DEVELOPER_GUIDE.md +9 -0
- data/Gemfile +1 -1
- data/MAINTAINERS.md +3 -0
- data/README.md +90 -3
- data/docs/ecs_compatibility.md +42 -0
- data/lib/logstash/outputs/opensearch/http_client/manticore_adapter.rb +122 -10
- data/lib/logstash/outputs/opensearch/http_client/pool.rb +11 -2
- data/lib/logstash/outputs/opensearch/http_client.rb +22 -25
- data/lib/logstash/outputs/opensearch/http_client_builder.rb +9 -3
- data/lib/logstash/outputs/opensearch/template_manager.rb +6 -5
- data/lib/logstash/outputs/opensearch/templates/ecs-disabled/1x_index.json +66 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-disabled/2x.json +44 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-disabled/2x_index.json +66 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-disabled/7x_index.json +66 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v1/1x.json +3629 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v1/1x_index.json +3631 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v1/2x.json +3629 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v1/2x_index.json +3631 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v1/7x.json +3629 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v1/7x_index.json +3631 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v8/1x.json +5252 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v8/1x_index.json +5254 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v8/2x.json +5252 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v8/2x_index.json +5254 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v8/7x.json +5252 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v8/7x_index.json +5254 -0
- data/lib/logstash/outputs/opensearch.rb +10 -3
- data/lib/logstash/plugin_mixins/opensearch/api_configs.rb +26 -0
- data/logstash-output-opensearch.gemspec +19 -3
- data/spec/integration/outputs/compressed_indexing_spec.rb +10 -4
- data/spec/integration/outputs/create_spec.rb +7 -7
- data/spec/integration/outputs/delete_spec.rb +8 -8
- data/spec/integration/outputs/index_spec.rb +52 -10
- data/spec/integration/outputs/index_version_spec.rb +11 -11
- data/spec/integration/outputs/ingest_pipeline_spec.rb +2 -3
- data/spec/integration/outputs/metrics_spec.rb +0 -2
- data/spec/integration/outputs/no_opensearch_on_startup_spec.rb +0 -1
- data/spec/integration/outputs/painless_update_spec.rb +10 -10
- data/spec/integration/outputs/parent_spec.rb +1 -1
- data/spec/integration/outputs/retry_spec.rb +2 -2
- data/spec/integration/outputs/sniffer_spec.rb +2 -2
- data/spec/integration/outputs/templates_spec.rb +83 -59
- data/spec/integration/outputs/update_spec.rb +14 -14
- data/spec/opensearch_spec_helper.rb +12 -2
- data/spec/unit/outputs/opensearch/http_client/manticore_adapter_spec.rb +86 -3
- data/spec/unit/outputs/opensearch/http_client_spec.rb +26 -5
- data/spec/unit/outputs/opensearch/template_manager_spec.rb +11 -4
- data/spec/unit/outputs/opensearch_spec.rb +18 -2
- data.tar.gz.sig +0 -0
- metadata +74 -9
- metadata.gz.sig +0 -0
|
@@ -78,7 +78,7 @@ class LogStash::Outputs::OpenSearch < LogStash::Outputs::Base
|
|
|
78
78
|
include(LogStash::PluginMixins::OpenSearch::Common)
|
|
79
79
|
|
|
80
80
|
# ecs_compatibility option, provided by Logstash core or the support adapter.
|
|
81
|
-
include(LogStash::PluginMixins::ECSCompatibilitySupport)
|
|
81
|
+
include(LogStash::PluginMixins::ECSCompatibilitySupport(:disabled, :v1, :v8))
|
|
82
82
|
|
|
83
83
|
# Generic/API config options that any document indexer output needs
|
|
84
84
|
include(LogStash::PluginMixins::OpenSearch::APIConfigs)
|
|
@@ -95,7 +95,7 @@ class LogStash::Outputs::OpenSearch < LogStash::Outputs::Base
|
|
|
95
95
|
# - A sprintf style string to change the action based on the content of the event. The value `%{[foo]}`
|
|
96
96
|
# would use the foo field for the action
|
|
97
97
|
#
|
|
98
|
-
# For more details on actions, check out the https://
|
|
98
|
+
# For more details on actions, check out the https://opensearch.org/docs/opensearch/rest-api/document-apis/bulk/[OpenSearch bulk API documentation]
|
|
99
99
|
config :action, :validate => :string, :default => "index"
|
|
100
100
|
|
|
101
101
|
# The index to write events to. This can be dynamic using the `%{foo}` syntax.
|
|
@@ -199,6 +199,13 @@ class LogStash::Outputs::OpenSearch < LogStash::Outputs::Base
|
|
|
199
199
|
# Set which ingest pipeline you wish to execute for an event. You can also use event dependent configuration
|
|
200
200
|
# here like `pipeline => "%{INGEST_PIPELINE}"`
|
|
201
201
|
config :pipeline, :validate => :string, :default => nil
|
|
202
|
+
|
|
203
|
+
# When set to true, use legacy templates via the _template API
|
|
204
|
+
# When false, use index templates using the _index_template API
|
|
205
|
+
config :legacy_template, :validate => :boolean, :default => true
|
|
206
|
+
|
|
207
|
+
# The OpenSearch server major version to use when it's not available from the Healthcheck endpoint.
|
|
208
|
+
config :default_server_major_version, :validate => :number
|
|
202
209
|
|
|
203
210
|
attr_reader :client
|
|
204
211
|
attr_reader :default_index
|
|
@@ -419,7 +426,7 @@ class LogStash::Outputs::OpenSearch < LogStash::Outputs::Base
|
|
|
419
426
|
when :disabled
|
|
420
427
|
@default_index = "logstash-%{+yyyy.MM.dd}"
|
|
421
428
|
@default_template_name = 'logstash'
|
|
422
|
-
when :v1
|
|
429
|
+
when :v1, :v8
|
|
423
430
|
@default_index = "ecs-logstash-%{+yyyy.MM.dd}"
|
|
424
431
|
@default_template_name = 'ecs-logstash'
|
|
425
432
|
else
|
|
@@ -20,6 +20,18 @@ module LogStash; module PluginMixins; module OpenSearch
|
|
|
20
20
|
# Password to authenticate to a secure OpenSearch cluster
|
|
21
21
|
:password => { :validate => :password },
|
|
22
22
|
|
|
23
|
+
# if auth_type is "aws_iam" then
|
|
24
|
+
# Credential resolution logic works as follows :
|
|
25
|
+
#
|
|
26
|
+
# - User passed aws_access_key_id and aws_secret_access_key in opensearch configuration
|
|
27
|
+
# - Environment Variables - AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
|
|
28
|
+
# (RECOMMENDED since they are recognized by all the AWS SDKs and CLI except for .NET),
|
|
29
|
+
# or AWS_ACCESS_KEY and AWS_SECRET_KEY (only recognized by Java SDK)
|
|
30
|
+
# - Credential profiles file at the default location (~/.aws/credentials) shared by all AWS SDKs and the AWS CLI
|
|
31
|
+
# - Instance profile credentials delivered through the Amazon EC2 metadata service
|
|
32
|
+
# - type in auth_type specifies the type of authentication
|
|
33
|
+
:auth_type => { },
|
|
34
|
+
|
|
23
35
|
# The document ID for the index. Useful for overwriting existing entries in
|
|
24
36
|
# OpenSearch with the same ID.
|
|
25
37
|
:document_id => { :validate => :string },
|
|
@@ -34,6 +46,20 @@ module LogStash; module PluginMixins; module OpenSearch
|
|
|
34
46
|
# this defaults to a concatenation of the path parameter and "_bulk"
|
|
35
47
|
:bulk_path => { :validate => :string },
|
|
36
48
|
|
|
49
|
+
# Maximum number of bytes in bulk requests
|
|
50
|
+
# The criteria for deciding the default value of target_bulk_bytes is:
|
|
51
|
+
# 1. We need a number that's less than 10MiB because OpenSearch is commonly
|
|
52
|
+
# configured (particular in AWS Opensearch Service) to not accept
|
|
53
|
+
# bulks larger than that.
|
|
54
|
+
# 2. It must be large enough to amortize the connection constant
|
|
55
|
+
# across multiple requests.
|
|
56
|
+
# 3. It must be small enough that even if multiple threads hit this size
|
|
57
|
+
# we won't use a lot of heap.
|
|
58
|
+
:target_bulk_bytes => {
|
|
59
|
+
:validate => :number,
|
|
60
|
+
:default => 9 * 1024 * 1024 # 9MiB
|
|
61
|
+
},
|
|
62
|
+
|
|
37
63
|
# Pass a set of key value pairs as the URL query string. This query string is added
|
|
38
64
|
# to every host listed in the 'hosts' configuration. If the 'hosts' list contains
|
|
39
65
|
# urls that already have query strings, the one specified here will be appended.
|
|
@@ -1,6 +1,17 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
#
|
|
3
|
+
# The OpenSearch Contributors require contributions made to
|
|
4
|
+
# this file be licensed under the Apache-2.0 license or a
|
|
5
|
+
# compatible open source license.
|
|
6
|
+
#
|
|
7
|
+
# Modifications Copyright OpenSearch Contributors. See
|
|
8
|
+
# GitHub history for details.
|
|
9
|
+
|
|
10
|
+
signing_key_path = "gem-private_key.pem"
|
|
11
|
+
|
|
1
12
|
Gem::Specification.new do |s|
|
|
2
13
|
s.name = 'logstash-output-opensearch'
|
|
3
|
-
s.version = '
|
|
14
|
+
s.version = '2.0.0'
|
|
4
15
|
|
|
5
16
|
s.licenses = ['Apache-2.0']
|
|
6
17
|
s.summary = "Stores logs in OpenSearch"
|
|
@@ -18,8 +29,10 @@ Gem::Specification.new do |s|
|
|
|
18
29
|
# Tests
|
|
19
30
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
|
20
31
|
|
|
21
|
-
|
|
22
|
-
|
|
32
|
+
if $PROGRAM_NAME.end_with?("gem") && ARGV == ["build", __FILE__] && File.exist?(signing_key_path)
|
|
33
|
+
s.signing_key = signing_key_path
|
|
34
|
+
s.cert_chain = ['certs/opensearch-rubygems.pem']
|
|
35
|
+
end
|
|
23
36
|
|
|
24
37
|
# Special flag to let us know this is actually a logstash plugin
|
|
25
38
|
s.metadata = {
|
|
@@ -32,9 +45,12 @@ Gem::Specification.new do |s|
|
|
|
32
45
|
s.add_runtime_dependency 'stud', ['>= 0.0.17', '~> 0.0']
|
|
33
46
|
s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
|
|
34
47
|
s.add_runtime_dependency 'logstash-mixin-ecs_compatibility_support', '~>1.0'
|
|
48
|
+
s.add_runtime_dependency 'aws-sdk', '~> 3'
|
|
49
|
+
s.add_runtime_dependency 'json', '>= 2.3.0', '~> 2'
|
|
35
50
|
|
|
36
51
|
s.add_development_dependency 'logstash-codec-plain'
|
|
37
52
|
s.add_development_dependency 'logstash-devutils'
|
|
38
53
|
s.add_development_dependency 'flores'
|
|
39
54
|
s.add_development_dependency 'cabin', ['~> 0.6']
|
|
55
|
+
s.add_development_dependency 'opensearch-ruby', '~> 1'
|
|
40
56
|
end
|
|
@@ -33,8 +33,8 @@ describe "indexing with http_compression turned on", :integration => true do
|
|
|
33
33
|
}
|
|
34
34
|
subject { LogStash::Outputs::OpenSearch.new(config) }
|
|
35
35
|
|
|
36
|
-
let(:
|
|
37
|
-
let(:index_url) {"#{
|
|
36
|
+
let(:opensearch_url) { "http://#{get_host_port}" }
|
|
37
|
+
let(:index_url) {"#{opensearch_url}/#{index}"}
|
|
38
38
|
let(:http_client_options) { {} }
|
|
39
39
|
let(:http_client) do
|
|
40
40
|
Manticore::Client.new(http_client_options)
|
|
@@ -49,7 +49,7 @@ describe "indexing with http_compression turned on", :integration => true do
|
|
|
49
49
|
it "ships events" do
|
|
50
50
|
subject.multi_receive(events)
|
|
51
51
|
|
|
52
|
-
http_client.post("#{
|
|
52
|
+
http_client.post("#{opensearch_url}/_refresh").call
|
|
53
53
|
|
|
54
54
|
response = http_client.get("#{index_url}/_count?q=*")
|
|
55
55
|
result = LogStash::Json.load(response.body)
|
|
@@ -59,7 +59,13 @@ describe "indexing with http_compression turned on", :integration => true do
|
|
|
59
59
|
response = http_client.get("#{index_url}/_search?q=*&size=1000")
|
|
60
60
|
result = LogStash::Json.load(response.body)
|
|
61
61
|
result["hits"]["hits"].each do |doc|
|
|
62
|
-
|
|
62
|
+
# FIXME This checks for OpenSearch 1.x or OpenDistro which has version 7.10.x
|
|
63
|
+
# need a cleaner way to check this.
|
|
64
|
+
if OpenSearchHelper.check_version?("< 2") || OpenSearchHelper.check_version?("> 7")
|
|
65
|
+
expect(doc["_type"]).to eq(type)
|
|
66
|
+
else
|
|
67
|
+
expect(doc).not_to include("_type")
|
|
68
|
+
end
|
|
63
69
|
expect(doc["_index"]).to eq(index)
|
|
64
70
|
end
|
|
65
71
|
end
|
|
@@ -12,7 +12,7 @@ require_relative "../../../spec/opensearch_spec_helper"
|
|
|
12
12
|
describe "client create actions", :integration => true do
|
|
13
13
|
require "logstash/outputs/opensearch"
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def get_output(action, id, version=nil, version_type=nil)
|
|
16
16
|
settings = {
|
|
17
17
|
"manage_template" => true,
|
|
18
18
|
"index" => "logstash-create",
|
|
@@ -37,7 +37,7 @@ describe "client create actions", :integration => true do
|
|
|
37
37
|
|
|
38
38
|
context "when action => create" do
|
|
39
39
|
it "should create new documents with or without id" do
|
|
40
|
-
subject =
|
|
40
|
+
subject = get_output("create", "id123")
|
|
41
41
|
subject.register
|
|
42
42
|
subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
|
|
43
43
|
@client.indices.refresh
|
|
@@ -49,27 +49,27 @@ describe "client create actions", :integration => true do
|
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
it "should allow default (internal) version" do
|
|
52
|
-
subject =
|
|
52
|
+
subject = get_output("create", "id123", 43)
|
|
53
53
|
subject.register
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
it "should allow internal version" do
|
|
57
|
-
subject =
|
|
57
|
+
subject = get_output("create", "id123", 43, "internal")
|
|
58
58
|
subject.register
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
it "should not allow external version" do
|
|
62
|
-
subject =
|
|
62
|
+
subject = get_output("create", "id123", 43, "external")
|
|
63
63
|
expect { subject.register }.to raise_error(LogStash::ConfigurationError)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
it "should not allow external_gt version" do
|
|
67
|
-
subject =
|
|
67
|
+
subject = get_output("create", "id123", 43, "external_gt")
|
|
68
68
|
expect { subject.register }.to raise_error(LogStash::ConfigurationError)
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
it "should not allow external_gte version" do
|
|
72
|
-
subject =
|
|
72
|
+
subject = get_output("create", "id123", 43, "external_gte")
|
|
73
73
|
expect { subject.register }.to raise_error(LogStash::ConfigurationError)
|
|
74
74
|
end
|
|
75
75
|
end
|
|
@@ -14,15 +14,15 @@ require "logstash/outputs/opensearch"
|
|
|
14
14
|
describe "Versioned delete", :integration => true do
|
|
15
15
|
require "logstash/outputs/opensearch"
|
|
16
16
|
|
|
17
|
-
let(:
|
|
17
|
+
let(:client) { get_client }
|
|
18
18
|
|
|
19
19
|
before :each do
|
|
20
20
|
# Delete all templates first.
|
|
21
21
|
# Clean ES of data before we start.
|
|
22
|
-
|
|
22
|
+
client.indices.delete_template(:name => "*")
|
|
23
23
|
# This can fail if there are no indexes, ignore failure.
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
client.indices.delete(:index => "*") rescue nil
|
|
25
|
+
client.indices.refresh
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
context "when delete only" do
|
|
@@ -48,12 +48,12 @@ describe "Versioned delete", :integration => true do
|
|
|
48
48
|
it "should ignore non-monotonic external version updates" do
|
|
49
49
|
id = "ev2"
|
|
50
50
|
subject.multi_receive([LogStash::Event.new("my_id" => id, "my_action" => "index", "message" => "foo", "my_version" => 99)])
|
|
51
|
-
r =
|
|
51
|
+
r = client.get(:index => 'logstash-delete', :type => doc_type, :id => id, :refresh => true)
|
|
52
52
|
expect(r['_version']).to eq(99)
|
|
53
53
|
expect(r['_source']['message']).to eq('foo')
|
|
54
54
|
|
|
55
55
|
subject.multi_receive([LogStash::Event.new("my_id" => id, "my_action" => "delete", "message" => "foo", "my_version" => 98)])
|
|
56
|
-
r2 =
|
|
56
|
+
r2 = client.get(:index => 'logstash-delete', :type => doc_type, :id => id, :refresh => true)
|
|
57
57
|
expect(r2['_version']).to eq(99)
|
|
58
58
|
expect(r2['_source']['message']).to eq('foo')
|
|
59
59
|
end
|
|
@@ -61,12 +61,12 @@ describe "Versioned delete", :integration => true do
|
|
|
61
61
|
it "should commit monotonic external version updates" do
|
|
62
62
|
id = "ev3"
|
|
63
63
|
subject.multi_receive([LogStash::Event.new("my_id" => id, "my_action" => "index", "message" => "foo", "my_version" => 99)])
|
|
64
|
-
r =
|
|
64
|
+
r = client.get(:index => 'logstash-delete', :type => doc_type, :id => id, :refresh => true)
|
|
65
65
|
expect(r['_version']).to eq(99)
|
|
66
66
|
expect(r['_source']['message']).to eq('foo')
|
|
67
67
|
|
|
68
68
|
subject.multi_receive([LogStash::Event.new("my_id" => id, "my_action" => "delete", "message" => "foo", "my_version" => 100)])
|
|
69
|
-
expect {
|
|
69
|
+
expect { client.get(:index => 'logstash-delete', :type => doc_type, :id => id, :refresh => true) }.to raise_error(OpenSearch::Transport::Transport::Errors::NotFound)
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
end
|
|
@@ -10,8 +10,7 @@
|
|
|
10
10
|
require_relative "../../../spec/opensearch_spec_helper"
|
|
11
11
|
require "logstash/outputs/opensearch"
|
|
12
12
|
|
|
13
|
-
describe "
|
|
14
|
-
let(:target_bulk_bytes) { LogStash::Outputs::OpenSearch::TARGET_BULK_BYTES }
|
|
13
|
+
describe "target_bulk_bytes", :integration => true do
|
|
15
14
|
let(:event_count) { 1000 }
|
|
16
15
|
let(:events) { event_count.times.map { event }.to_a }
|
|
17
16
|
let(:config) {
|
|
@@ -32,11 +31,11 @@ describe "TARGET_BULK_BYTES", :integration => true do
|
|
|
32
31
|
end
|
|
33
32
|
|
|
34
33
|
describe "batches that are too large for one" do
|
|
35
|
-
let(:event) { LogStash::Event.new("message" => "a " * (((target_bulk_bytes/2) / event_count)+1)) }
|
|
34
|
+
let(:event) { LogStash::Event.new("message" => "a " * (((subject.client.target_bulk_bytes/2) / event_count)+1)) }
|
|
36
35
|
|
|
37
36
|
it "should send in two batches" do
|
|
38
37
|
expect(subject.client).to have_received(:bulk_send).twice do |payload|
|
|
39
|
-
expect(payload.size).to be <= target_bulk_bytes
|
|
38
|
+
expect(payload.size).to be <= subject.client.target_bulk_bytes
|
|
40
39
|
end
|
|
41
40
|
end
|
|
42
41
|
|
|
@@ -47,7 +46,7 @@ describe "TARGET_BULK_BYTES", :integration => true do
|
|
|
47
46
|
|
|
48
47
|
it "should send in one batch" do
|
|
49
48
|
expect(subject.client).to have_received(:bulk_send).once do |payload|
|
|
50
|
-
expect(payload.size).to be <= target_bulk_bytes
|
|
49
|
+
expect(payload.size).to be <= subject.client.target_bulk_bytes
|
|
51
50
|
end
|
|
52
51
|
end
|
|
53
52
|
end
|
|
@@ -63,8 +62,8 @@ describe "indexing" do
|
|
|
63
62
|
let(:events) { event_count.times.map { event }.to_a }
|
|
64
63
|
subject { LogStash::Outputs::OpenSearch.new(config) }
|
|
65
64
|
|
|
66
|
-
let(:
|
|
67
|
-
let(:index_url) {"#{
|
|
65
|
+
let(:opensearch_url) { "http://#{get_host_port}" }
|
|
66
|
+
let(:index_url) {"#{opensearch_url}/#{index}"}
|
|
68
67
|
let(:http_client_options) { {} }
|
|
69
68
|
let(:http_client) do
|
|
70
69
|
Manticore::Client.new(http_client_options)
|
|
@@ -79,7 +78,7 @@ describe "indexing" do
|
|
|
79
78
|
it "ships events" do
|
|
80
79
|
subject.multi_receive(events)
|
|
81
80
|
|
|
82
|
-
http_client.post("#{
|
|
81
|
+
http_client.post("#{opensearch_url}/_refresh").call
|
|
83
82
|
|
|
84
83
|
response = http_client.get("#{index_url}/_count?q=*")
|
|
85
84
|
result = LogStash::Json.load(response.body)
|
|
@@ -89,7 +88,13 @@ describe "indexing" do
|
|
|
89
88
|
response = http_client.get("#{index_url}/_search?q=*&size=1000")
|
|
90
89
|
result = LogStash::Json.load(response.body)
|
|
91
90
|
result["hits"]["hits"].each do |doc|
|
|
92
|
-
|
|
91
|
+
# FIXME This checks for OpenSearch 1.x or OpenDistro which has version 7.10.x
|
|
92
|
+
# need a cleaner way to check this.
|
|
93
|
+
if OpenSearchHelper.check_version?("< 2") || OpenSearchHelper.check_version?("> 7")
|
|
94
|
+
expect(doc["_type"]).to eq(type)
|
|
95
|
+
else
|
|
96
|
+
expect(doc).not_to include("_type")
|
|
97
|
+
end
|
|
93
98
|
expect(doc["_index"]).to eq(index)
|
|
94
99
|
end
|
|
95
100
|
end
|
|
@@ -136,7 +141,7 @@ describe "indexing" do
|
|
|
136
141
|
describe "a secured indexer", :secure_integration => true do
|
|
137
142
|
let(:user) { "admin" }
|
|
138
143
|
let(:password) { "admin" }
|
|
139
|
-
let(:
|
|
144
|
+
let(:opensearch_url) {"https://integration:9200"}
|
|
140
145
|
let(:config) do
|
|
141
146
|
{
|
|
142
147
|
"hosts" => ["integration:9200"],
|
|
@@ -161,4 +166,41 @@ describe "indexing" do
|
|
|
161
166
|
end
|
|
162
167
|
it_behaves_like("an indexer", true)
|
|
163
168
|
end
|
|
169
|
+
|
|
170
|
+
describe "a basic auth secured indexer", :secure_integration => true do
|
|
171
|
+
let(:options) { {
|
|
172
|
+
:auth_type => {
|
|
173
|
+
"type"=>"basic",
|
|
174
|
+
"user" => "admin",
|
|
175
|
+
"password" => "admin"}
|
|
176
|
+
} }
|
|
177
|
+
let(:user) {options[:auth_type]["user"]}
|
|
178
|
+
let(:password) {options[:auth_type]["password"]}
|
|
179
|
+
let(:opensearch_url) {"https://integration:9200"}
|
|
180
|
+
let(:config) do
|
|
181
|
+
{
|
|
182
|
+
"hosts" => ["integration:9200"],
|
|
183
|
+
"auth_type" => {
|
|
184
|
+
"type"=>"basic",
|
|
185
|
+
"user" => user,
|
|
186
|
+
"password" => password},
|
|
187
|
+
"ssl" => true,
|
|
188
|
+
"ssl_certificate_verification" => false,
|
|
189
|
+
"index" => index
|
|
190
|
+
}
|
|
191
|
+
end
|
|
192
|
+
let(:http_client_options) do
|
|
193
|
+
{
|
|
194
|
+
:auth => {
|
|
195
|
+
:user => user,
|
|
196
|
+
:password => password
|
|
197
|
+
},
|
|
198
|
+
:ssl => {
|
|
199
|
+
:enabled => true,
|
|
200
|
+
:verify => false
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
end
|
|
204
|
+
it_behaves_like("an indexer", true)
|
|
205
|
+
end
|
|
164
206
|
end
|
|
@@ -13,15 +13,15 @@ require "logstash/outputs/opensearch"
|
|
|
13
13
|
describe "Versioned indexing", :integration => true do
|
|
14
14
|
require "logstash/outputs/opensearch"
|
|
15
15
|
|
|
16
|
-
let(:
|
|
16
|
+
let(:client) { get_client }
|
|
17
17
|
|
|
18
18
|
before :each do
|
|
19
19
|
# Delete all templates first.
|
|
20
20
|
# Clean OpenSearch of data before we start.
|
|
21
|
-
|
|
21
|
+
client.indices.delete_template(:name => "*")
|
|
22
22
|
# This can fail if there are no indexes, ignore failure.
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
client.indices.delete(:index => "*") rescue nil
|
|
24
|
+
client.indices.refresh
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
context "when index only" do
|
|
@@ -46,11 +46,11 @@ describe "Versioned indexing", :integration => true do
|
|
|
46
46
|
|
|
47
47
|
it "should default to OpenSearch version" do
|
|
48
48
|
subject.multi_receive([LogStash::Event.new("my_id" => "123", "message" => "foo")])
|
|
49
|
-
r =
|
|
49
|
+
r = client.get(:index => 'logstash-index', :type => doc_type, :id => "123", :refresh => true)
|
|
50
50
|
expect(r["_version"]).to eq(1)
|
|
51
51
|
expect(r["_source"]["message"]).to eq('foo')
|
|
52
52
|
subject.multi_receive([LogStash::Event.new("my_id" => "123", "message" => "foobar")])
|
|
53
|
-
r2 =
|
|
53
|
+
r2 = client.get(:index => 'logstash-index', :type => doc_type, :id => "123", :refresh => true)
|
|
54
54
|
expect(r2["_version"]).to eq(2)
|
|
55
55
|
expect(r2["_source"]["message"]).to eq('foobar')
|
|
56
56
|
end
|
|
@@ -74,7 +74,7 @@ describe "Versioned indexing", :integration => true do
|
|
|
74
74
|
it "should respect the external version" do
|
|
75
75
|
id = "ev1"
|
|
76
76
|
subject.multi_receive([LogStash::Event.new("my_id" => id, "my_version" => "99", "message" => "foo")])
|
|
77
|
-
r =
|
|
77
|
+
r = client.get(:index => 'logstash-index', :type => doc_type, :id => id, :refresh => true)
|
|
78
78
|
expect(r["_version"]).to eq(99)
|
|
79
79
|
expect(r["_source"]["message"]).to eq('foo')
|
|
80
80
|
end
|
|
@@ -82,12 +82,12 @@ describe "Versioned indexing", :integration => true do
|
|
|
82
82
|
it "should ignore non-monotonic external version updates" do
|
|
83
83
|
id = "ev2"
|
|
84
84
|
subject.multi_receive([LogStash::Event.new("my_id" => id, "my_version" => "99", "message" => "foo")])
|
|
85
|
-
r =
|
|
85
|
+
r = client.get(:index => 'logstash-index', :type => doc_type, :id => id, :refresh => true)
|
|
86
86
|
expect(r["_version"]).to eq(99)
|
|
87
87
|
expect(r["_source"]["message"]).to eq('foo')
|
|
88
88
|
|
|
89
89
|
subject.multi_receive([LogStash::Event.new("my_id" => id, "my_version" => "98", "message" => "foo")])
|
|
90
|
-
r2 =
|
|
90
|
+
r2 = client.get(:index => 'logstash-index', :type => doc_type, :id => id, :refresh => true)
|
|
91
91
|
expect(r2["_version"]).to eq(99)
|
|
92
92
|
expect(r2["_source"]["message"]).to eq('foo')
|
|
93
93
|
end
|
|
@@ -95,12 +95,12 @@ describe "Versioned indexing", :integration => true do
|
|
|
95
95
|
it "should commit monotonic external version updates" do
|
|
96
96
|
id = "ev3"
|
|
97
97
|
subject.multi_receive([LogStash::Event.new("my_id" => id, "my_version" => "99", "message" => "foo")])
|
|
98
|
-
r =
|
|
98
|
+
r = client.get(:index => 'logstash-index', :type => doc_type, :id => id, :refresh => true)
|
|
99
99
|
expect(r["_version"]).to eq(99)
|
|
100
100
|
expect(r["_source"]["message"]).to eq('foo')
|
|
101
101
|
|
|
102
102
|
subject.multi_receive([LogStash::Event.new("my_id" => id, "my_version" => "100", "message" => "foo")])
|
|
103
|
-
r2 =
|
|
103
|
+
r2 = client.get(:index => 'logstash-index', :type => doc_type, :id => id, :refresh => true)
|
|
104
104
|
expect(r2["_version"]).to eq(100)
|
|
105
105
|
expect(r2["_source"]["message"]).to eq('foo')
|
|
106
106
|
end
|
|
@@ -14,7 +14,8 @@ describe "Ingest pipeline execution behavior", :integration => true do
|
|
|
14
14
|
require "logstash/outputs/opensearch"
|
|
15
15
|
settings = {
|
|
16
16
|
"hosts" => "#{get_host_port()}",
|
|
17
|
-
"pipeline" => "apache-logs"
|
|
17
|
+
"pipeline" => "apache-logs",
|
|
18
|
+
"ecs_compatibility" => "disabled" # specs are tightly tied to non-ECS defaults
|
|
18
19
|
}
|
|
19
20
|
next LogStash::Outputs::OpenSearch.new(settings)
|
|
20
21
|
end
|
|
@@ -37,8 +38,6 @@ describe "Ingest pipeline execution behavior", :integration => true do
|
|
|
37
38
|
|
|
38
39
|
before :each do
|
|
39
40
|
# Delete all templates first.
|
|
40
|
-
require "elasticsearch"
|
|
41
|
-
|
|
42
41
|
# Clean OpenSearch of data before we start.
|
|
43
42
|
@client = get_client
|
|
44
43
|
@client.indices.delete_template(:name => "*")
|
|
@@ -24,8 +24,6 @@ describe "metrics", :integration => true do
|
|
|
24
24
|
let(:document_level_metrics) { subject.instance_variable_get(:@document_level_metrics) }
|
|
25
25
|
|
|
26
26
|
before :each do
|
|
27
|
-
require "elasticsearch"
|
|
28
|
-
|
|
29
27
|
# Clean OpenSearch of data before we start.
|
|
30
28
|
@client = get_client
|
|
31
29
|
clean(@client)
|
|
@@ -12,7 +12,7 @@ require_relative "../../../spec/opensearch_spec_helper"
|
|
|
12
12
|
describe "Update actions using painless scripts", :integration => true, :update_tests => 'painless' do
|
|
13
13
|
require "logstash/outputs/opensearch"
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def get_output( options={} )
|
|
16
16
|
settings = {
|
|
17
17
|
"manage_template" => true,
|
|
18
18
|
"index" => "logstash-update",
|
|
@@ -42,7 +42,7 @@ describe "Update actions using painless scripts", :integration => true, :update_
|
|
|
42
42
|
context "scripted updates" do
|
|
43
43
|
|
|
44
44
|
it "should increment a counter with event/doc 'count' variable with inline script" do
|
|
45
|
-
subject =
|
|
45
|
+
subject = get_output({
|
|
46
46
|
'document_id' => "123",
|
|
47
47
|
'script' => 'ctx._source.counter += params.event.counter',
|
|
48
48
|
'script_type' => 'inline'
|
|
@@ -54,7 +54,7 @@ describe "Update actions using painless scripts", :integration => true, :update_
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
it "should increment a counter with event/doc 'count' variable with event/doc as upsert and inline script" do
|
|
57
|
-
subject =
|
|
57
|
+
subject = get_output({
|
|
58
58
|
'document_id' => "123",
|
|
59
59
|
'doc_as_upsert' => true,
|
|
60
60
|
'script' => 'if( ctx._source.containsKey("counter") ){ ctx._source.counter += params.event.counter; } else { ctx._source.counter = params.event.counter; }',
|
|
@@ -67,7 +67,7 @@ describe "Update actions using painless scripts", :integration => true, :update_
|
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
it "should, with new doc, set a counter with event/doc 'count' variable with event/doc as upsert and inline script" do
|
|
70
|
-
subject =
|
|
70
|
+
subject = get_output({
|
|
71
71
|
'document_id' => "456",
|
|
72
72
|
'doc_as_upsert' => true,
|
|
73
73
|
'script' => 'if( ctx._source.containsKey("counter") ){ ctx._source.counter += params.event.counter; } else { ctx._source.counter = params.event.counter; }',
|
|
@@ -90,7 +90,7 @@ describe "Update actions using painless scripts", :integration => true, :update_
|
|
|
90
90
|
|
|
91
91
|
plugin_parameters.merge!('script_lang' => '')
|
|
92
92
|
|
|
93
|
-
subject =
|
|
93
|
+
subject = get_output(plugin_parameters)
|
|
94
94
|
subject.register
|
|
95
95
|
subject.multi_receive([LogStash::Event.new("count" => 4 )])
|
|
96
96
|
r = @client.get(:index => 'logstash-update', :type => doc_type, :id => "123", :refresh => true)
|
|
@@ -101,7 +101,7 @@ describe "Update actions using painless scripts", :integration => true, :update_
|
|
|
101
101
|
|
|
102
102
|
context "when update with upsert" do
|
|
103
103
|
it "should create new documents with provided upsert" do
|
|
104
|
-
subject =
|
|
104
|
+
subject = get_output({ 'document_id' => "456", 'upsert' => '{"message": "upsert message"}' })
|
|
105
105
|
subject.register
|
|
106
106
|
subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
|
|
107
107
|
r = @client.get(:index => 'logstash-update', :type => doc_type, :id => "456", :refresh => true)
|
|
@@ -109,7 +109,7 @@ describe "Update actions using painless scripts", :integration => true, :update_
|
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
it "should create new documents with event/doc as upsert" do
|
|
112
|
-
subject =
|
|
112
|
+
subject = get_output({ 'document_id' => "456", 'doc_as_upsert' => true })
|
|
113
113
|
subject.register
|
|
114
114
|
subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
|
|
115
115
|
r = @client.get(:index => 'logstash-update', :type => doc_type, :id => "456", :refresh => true)
|
|
@@ -117,7 +117,7 @@ describe "Update actions using painless scripts", :integration => true, :update_
|
|
|
117
117
|
end
|
|
118
118
|
|
|
119
119
|
it "should fail on documents with event/doc as upsert at external version" do
|
|
120
|
-
subject =
|
|
120
|
+
subject = get_output({ 'document_id' => "456", 'doc_as_upsert' => true, 'version' => 999, "version_type" => "external" })
|
|
121
121
|
expect { subject.register }.to raise_error(LogStash::ConfigurationError)
|
|
122
122
|
end
|
|
123
123
|
end
|
|
@@ -126,7 +126,7 @@ describe "Update actions using painless scripts", :integration => true, :update_
|
|
|
126
126
|
|
|
127
127
|
context 'with an inline script' do
|
|
128
128
|
it "should create new documents with upsert content" do
|
|
129
|
-
subject =
|
|
129
|
+
subject = get_output({ 'document_id' => "456", 'script' => 'ctx._source.counter = params.event.counter', 'upsert' => '{"message": "upsert message"}', 'script_type' => 'inline' })
|
|
130
130
|
subject.register
|
|
131
131
|
|
|
132
132
|
subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
|
|
@@ -135,7 +135,7 @@ describe "Update actions using painless scripts", :integration => true, :update_
|
|
|
135
135
|
end
|
|
136
136
|
|
|
137
137
|
it "should create new documents with event/doc as script params" do
|
|
138
|
-
subject =
|
|
138
|
+
subject = get_output({ 'document_id' => "456", 'script' => 'ctx._source.counter = params.event.counter', 'scripted_upsert' => true, 'script_type' => 'inline' })
|
|
139
139
|
subject.register
|
|
140
140
|
subject.multi_receive([LogStash::Event.new("counter" => 1)])
|
|
141
141
|
@client.indices.refresh
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
require_relative "../../../spec/opensearch_spec_helper"
|
|
11
11
|
require "logstash/outputs/opensearch"
|
|
12
12
|
|
|
13
|
-
context "join field tests", :integration => true do
|
|
13
|
+
context "join field tests", :integration => true && OpenSearchHelper.check_version?("<2") do
|
|
14
14
|
|
|
15
15
|
shared_examples "a join field based parent indexer" do
|
|
16
16
|
let(:index) { 10.times.collect { rand(10).to_s }.join("") }
|
|
@@ -46,14 +46,14 @@ describe "failures in bulk class expected behavior", :integration => true do
|
|
|
46
46
|
"template_overwrite" => true,
|
|
47
47
|
"hosts" => get_host_port(),
|
|
48
48
|
"retry_max_interval" => 64,
|
|
49
|
-
"retry_initial_interval" => 2
|
|
49
|
+
"retry_initial_interval" => 2,
|
|
50
|
+
"ecs_compatibility" => "disabled" # specs are tightly tied to non-ECS defaults
|
|
50
51
|
}
|
|
51
52
|
next LogStash::Outputs::OpenSearch.new(settings)
|
|
52
53
|
end
|
|
53
54
|
|
|
54
55
|
before :each do
|
|
55
56
|
# Delete all templates first.
|
|
56
|
-
require "elasticsearch"
|
|
57
57
|
allow(Stud).to receive(:stoppable_sleep)
|
|
58
58
|
|
|
59
59
|
# Clean OpenSearch of data before we start.
|
|
@@ -15,9 +15,9 @@ require "socket"
|
|
|
15
15
|
describe "pool sniffer", :integration => true do
|
|
16
16
|
let(:logger) { Cabin::Channel.get }
|
|
17
17
|
let(:adapter) { LogStash::Outputs::OpenSearch::HttpClient::ManticoreAdapter.new(logger) }
|
|
18
|
-
let(:
|
|
18
|
+
let(:opensearch_host) { get_host_port.split(":").first }
|
|
19
19
|
let(:es_port) { get_host_port.split(":").last }
|
|
20
|
-
let(:
|
|
20
|
+
let(:opensearch_ip) { IPSocket.getaddress(opensearch_host) }
|
|
21
21
|
let(:initial_urls) { [::LogStash::Util::SafeURI.new("http://#{get_host_port}")] }
|
|
22
22
|
let(:options) do
|
|
23
23
|
{
|