logstash-output-opensearch 1.0.0-java → 1.3.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/COMPATIBILITY.md +27 -0
- data/CONTRIBUTING.md +27 -5
- data/DEVELOPER_GUIDE.md +16 -7
- data/Gemfile +1 -1
- data/MAINTAINERS.md +3 -0
- data/NOTICE +9 -2
- data/README.md +75 -5
- data/lib/logstash/outputs/opensearch/http_client/manticore_adapter.rb +101 -4
- data/lib/logstash/outputs/opensearch/http_client/pool.rb +3 -16
- data/lib/logstash/outputs/opensearch/http_client.rb +12 -23
- data/lib/logstash/outputs/opensearch/http_client_builder.rb +5 -2
- data/lib/logstash/outputs/opensearch/templates/ecs-disabled/2x.json +44 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v8/1x.json +5252 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v8/2x.json +5252 -0
- data/lib/logstash/outputs/opensearch/templates/ecs-v8/7x.json +5252 -0
- data/lib/logstash/outputs/opensearch.rb +4 -5
- data/lib/logstash/plugin_mixins/opensearch/api_configs.rb +26 -0
- data/lib/logstash/plugin_mixins/opensearch/common.rb +2 -2
- data/logstash-output-opensearch.gemspec +20 -4
- data/spec/integration/outputs/compressed_indexing_spec.rb +11 -5
- 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 +54 -12
- data/spec/integration/outputs/index_version_spec.rb +11 -11
- data/spec/integration/outputs/ingest_pipeline_spec.rb +3 -4
- 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 +2 -2
- 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 +74 -4
- data/spec/unit/outputs/opensearch/http_client/pool_spec.rb +4 -87
- data/spec/unit/outputs/opensearch/http_client_spec.rb +6 -5
- data/spec/unit/outputs/opensearch/template_manager_spec.rb +23 -4
- data/spec/unit/outputs/opensearch_spec.rb +18 -2
- data.tar.gz.sig +0 -0
- metadata +75 -19
- metadata.gz.sig +0 -0
- data/lib/logstash/outputs/opensearch/distribution_checker.rb +0 -44
- data/lib/logstash/plugin_mixins/opensearch/noop_distribution_checker.rb +0 -18
@@ -68,7 +68,6 @@ require "forwardable"
|
|
68
68
|
class LogStash::Outputs::OpenSearch < LogStash::Outputs::Base
|
69
69
|
declare_threadsafe!
|
70
70
|
|
71
|
-
require "logstash/outputs/opensearch/distribution_checker"
|
72
71
|
require "logstash/outputs/opensearch/http_client"
|
73
72
|
require "logstash/outputs/opensearch/http_client_builder"
|
74
73
|
require "logstash/plugin_mixins/opensearch/api_configs"
|
@@ -79,7 +78,7 @@ class LogStash::Outputs::OpenSearch < LogStash::Outputs::Base
|
|
79
78
|
include(LogStash::PluginMixins::OpenSearch::Common)
|
80
79
|
|
81
80
|
# ecs_compatibility option, provided by Logstash core or the support adapter.
|
82
|
-
include(LogStash::PluginMixins::ECSCompatibilitySupport)
|
81
|
+
include(LogStash::PluginMixins::ECSCompatibilitySupport(:disabled, :v1, :v8))
|
83
82
|
|
84
83
|
# Generic/API config options that any document indexer output needs
|
85
84
|
include(LogStash::PluginMixins::OpenSearch::APIConfigs)
|
@@ -96,7 +95,7 @@ class LogStash::Outputs::OpenSearch < LogStash::Outputs::Base
|
|
96
95
|
# - A sprintf style string to change the action based on the content of the event. The value `%{[foo]}`
|
97
96
|
# would use the foo field for the action
|
98
97
|
#
|
99
|
-
# 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]
|
100
99
|
config :action, :validate => :string, :default => "index"
|
101
100
|
|
102
101
|
# The index to write events to. This can be dynamic using the `%{foo}` syntax.
|
@@ -218,7 +217,7 @@ class LogStash::Outputs::OpenSearch < LogStash::Outputs::Base
|
|
218
217
|
|
219
218
|
@logger.info("New OpenSearch output", :class => self.class.name, :hosts => @hosts.map(&:sanitized).map(&:to_s))
|
220
219
|
|
221
|
-
@client = build_client
|
220
|
+
@client = build_client
|
222
221
|
|
223
222
|
@after_successful_connection_thread = after_successful_connection do
|
224
223
|
begin
|
@@ -420,7 +419,7 @@ class LogStash::Outputs::OpenSearch < LogStash::Outputs::Base
|
|
420
419
|
when :disabled
|
421
420
|
@default_index = "logstash-%{+yyyy.MM.dd}"
|
422
421
|
@default_template_name = 'logstash'
|
423
|
-
when :v1
|
422
|
+
when :v1, :v8
|
424
423
|
@default_index = "ecs-logstash-%{+yyyy.MM.dd}"
|
425
424
|
@default_template_name = 'ecs-logstash'
|
426
425
|
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.
|
@@ -24,8 +24,8 @@ module LogStash; module PluginMixins; module OpenSearch
|
|
24
24
|
# Perform some OpenSearch options validations and Build the HttpClient.
|
25
25
|
# Note that this methods may sets the @user, @password, @hosts and @client ivars as a side effect.
|
26
26
|
# @return [HttpClient] the new http client
|
27
|
-
def build_client
|
28
|
-
|
27
|
+
def build_client
|
28
|
+
|
29
29
|
# the following 3 options validation & setup methods are called inside build_client
|
30
30
|
# because they must be executed prior to building the client and logstash
|
31
31
|
# monitoring and management rely on directly calling build_client
|
@@ -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 = '1.
|
14
|
+
s.version = '1.3.0'
|
4
15
|
|
5
16
|
s.licenses = ['Apache-2.0']
|
6
17
|
s.summary = "Stores logs in OpenSearch"
|
@@ -18,6 +29,11 @@ Gem::Specification.new do |s|
|
|
18
29
|
# Tests
|
19
30
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
20
31
|
|
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
|
36
|
+
|
21
37
|
# Special flag to let us know this is actually a logstash plugin
|
22
38
|
s.metadata = {
|
23
39
|
"logstash_plugin" => "true",
|
@@ -25,16 +41,16 @@ Gem::Specification.new do |s|
|
|
25
41
|
"source_code_uri" => "https://github.com/opensearch-project/logstash-output-opensearch"
|
26
42
|
}
|
27
43
|
|
28
|
-
s.cert_chain = ['public.pem']
|
29
|
-
s.signing_key = File.expand_path("private.pem") if $0 =~ /gem\z/
|
30
|
-
|
31
44
|
s.add_runtime_dependency "manticore", '>= 0.5.4', '< 1.0.0'
|
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', '>= 2.11.632', '~> 2'
|
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
|
@@ -67,7 +73,7 @@ describe "indexing with http_compression turned on", :integration => true do
|
|
67
73
|
|
68
74
|
it "sets the correct content-encoding header and body is compressed" do
|
69
75
|
expect(subject.client.pool.adapter.client).to receive(:send).
|
70
|
-
with(anything, anything, {:headers=>{"Content-Encoding"=>"gzip", "
|
76
|
+
with(anything, anything, {:headers=>{"Content-Encoding"=>"gzip", "content-type"=>"application/json"}, :body => a_valid_gzip_encoded_string}).
|
71
77
|
and_call_original
|
72
78
|
subject.multi_receive(events)
|
73
79
|
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,16 +88,22 @@ 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
|
96
101
|
|
97
102
|
it "sets the correct content-type header" do
|
98
|
-
expected_manticore_opts = {:headers => {"
|
103
|
+
expected_manticore_opts = {:headers => {"content-type" => "application/json"}, :body => anything}
|
99
104
|
if secure
|
100
105
|
expected_manticore_opts = {
|
101
|
-
:headers => {"
|
106
|
+
:headers => {"content-type" => "application/json"},
|
102
107
|
:body => anything,
|
103
108
|
:auth => {
|
104
109
|
:user => user,
|
@@ -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 => "*")
|
@@ -50,7 +49,7 @@ describe "Ingest pipeline execution behavior", :integration => true do
|
|
50
49
|
http_client.delete(ingest_url).call
|
51
50
|
|
52
51
|
# register pipeline
|
53
|
-
http_client.put(ingest_url, :body => apache_logs_pipeline, :headers => {"
|
52
|
+
http_client.put(ingest_url, :body => apache_logs_pipeline, :headers => {"content-type" => "application/json" }).call
|
54
53
|
|
55
54
|
#TODO: Use esclient
|
56
55
|
#@client.ingest.put_pipeline :id => 'apache_pipeline', :body => pipeline_defintion
|
@@ -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("") }
|
@@ -25,7 +25,7 @@ context "join field tests", :integration => true do
|
|
25
25
|
let(:parent_relation) { "parent_type" }
|
26
26
|
let(:child_relation) { "child_type" }
|
27
27
|
let(:default_headers) {
|
28
|
-
{"
|
28
|
+
{"content-type" => "application/json"}
|
29
29
|
}
|
30
30
|
subject { LogStash::Outputs::OpenSearch.new(config) }
|
31
31
|
|