logstash-output-elasticsearch-test 10.3.0-x86_64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +397 -0
- data/CONTRIBUTORS +33 -0
- data/Gemfile +15 -0
- data/LICENSE +13 -0
- data/NOTICE.TXT +5 -0
- data/README.md +106 -0
- data/docs/index.asciidoc +899 -0
- data/lib/logstash/outputs/elasticsearch/common.rb +441 -0
- data/lib/logstash/outputs/elasticsearch/common_configs.rb +167 -0
- data/lib/logstash/outputs/elasticsearch/default-ilm-policy.json +14 -0
- data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es2x.json +95 -0
- data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es5x.json +46 -0
- data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es6x.json +45 -0
- data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es7x.json +44 -0
- data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es8x.json +44 -0
- data/lib/logstash/outputs/elasticsearch/http_client/manticore_adapter.rb +131 -0
- data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +495 -0
- data/lib/logstash/outputs/elasticsearch/http_client.rb +432 -0
- data/lib/logstash/outputs/elasticsearch/http_client_builder.rb +159 -0
- data/lib/logstash/outputs/elasticsearch/ilm.rb +113 -0
- data/lib/logstash/outputs/elasticsearch/template_manager.rb +61 -0
- data/lib/logstash/outputs/elasticsearch.rb +263 -0
- data/logstash-output-elasticsearch.gemspec +33 -0
- data/spec/es_spec_helper.rb +189 -0
- data/spec/fixtures/_nodes/2x_1x.json +27 -0
- data/spec/fixtures/_nodes/5x_6x.json +81 -0
- data/spec/fixtures/_nodes/7x.json +92 -0
- data/spec/fixtures/htpasswd +2 -0
- data/spec/fixtures/nginx_reverse_proxy.conf +22 -0
- data/spec/fixtures/scripts/groovy/scripted_update.groovy +2 -0
- data/spec/fixtures/scripts/groovy/scripted_update_nested.groovy +2 -0
- data/spec/fixtures/scripts/groovy/scripted_upsert.groovy +2 -0
- data/spec/fixtures/scripts/painless/scripted_update.painless +2 -0
- data/spec/fixtures/scripts/painless/scripted_update_nested.painless +1 -0
- data/spec/fixtures/scripts/painless/scripted_upsert.painless +1 -0
- data/spec/fixtures/template-with-policy-es6x.json +48 -0
- data/spec/fixtures/template-with-policy-es7x.json +45 -0
- data/spec/fixtures/test_certs/ca/ca.crt +32 -0
- data/spec/fixtures/test_certs/ca/ca.key +51 -0
- data/spec/fixtures/test_certs/test.crt +36 -0
- data/spec/fixtures/test_certs/test.key +51 -0
- data/spec/integration/outputs/compressed_indexing_spec.rb +69 -0
- data/spec/integration/outputs/create_spec.rb +67 -0
- data/spec/integration/outputs/delete_spec.rb +65 -0
- data/spec/integration/outputs/groovy_update_spec.rb +150 -0
- data/spec/integration/outputs/ilm_spec.rb +531 -0
- data/spec/integration/outputs/index_spec.rb +178 -0
- data/spec/integration/outputs/index_version_spec.rb +102 -0
- data/spec/integration/outputs/ingest_pipeline_spec.rb +74 -0
- data/spec/integration/outputs/metrics_spec.rb +70 -0
- data/spec/integration/outputs/no_es_on_startup_spec.rb +58 -0
- data/spec/integration/outputs/painless_update_spec.rb +189 -0
- data/spec/integration/outputs/parent_spec.rb +102 -0
- data/spec/integration/outputs/retry_spec.rb +169 -0
- data/spec/integration/outputs/routing_spec.rb +61 -0
- data/spec/integration/outputs/sniffer_spec.rb +133 -0
- data/spec/integration/outputs/templates_5x_spec.rb +98 -0
- data/spec/integration/outputs/templates_spec.rb +98 -0
- data/spec/integration/outputs/update_spec.rb +116 -0
- data/spec/support/elasticsearch/api/actions/delete_ilm_policy.rb +19 -0
- data/spec/support/elasticsearch/api/actions/get_alias.rb +18 -0
- data/spec/support/elasticsearch/api/actions/get_ilm_policy.rb +18 -0
- data/spec/support/elasticsearch/api/actions/put_alias.rb +24 -0
- data/spec/support/elasticsearch/api/actions/put_ilm_policy.rb +25 -0
- data/spec/unit/http_client_builder_spec.rb +185 -0
- data/spec/unit/outputs/elasticsearch/http_client/manticore_adapter_spec.rb +149 -0
- data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +274 -0
- data/spec/unit/outputs/elasticsearch/http_client_spec.rb +250 -0
- data/spec/unit/outputs/elasticsearch/template_manager_spec.rb +25 -0
- data/spec/unit/outputs/elasticsearch_proxy_spec.rb +72 -0
- data/spec/unit/outputs/elasticsearch_spec.rb +675 -0
- data/spec/unit/outputs/elasticsearch_ssl_spec.rb +82 -0
- data/spec/unit/outputs/error_whitelist_spec.rb +54 -0
- metadata +300 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
require_relative "../../../spec/es_spec_helper"
|
2
|
+
|
3
|
+
if ESHelper.es_version_satisfies?(">= 2")
|
4
|
+
describe "Update actions without scripts", :integration => true do
|
5
|
+
require "logstash/outputs/elasticsearch"
|
6
|
+
|
7
|
+
def get_es_output( options={} )
|
8
|
+
settings = {
|
9
|
+
"manage_template" => true,
|
10
|
+
"index" => "logstash-update",
|
11
|
+
"template_overwrite" => true,
|
12
|
+
"hosts" => get_host_port(),
|
13
|
+
"action" => "update"
|
14
|
+
}
|
15
|
+
LogStash::Outputs::ElasticSearch.new(settings.merge!(options))
|
16
|
+
end
|
17
|
+
|
18
|
+
before :each do
|
19
|
+
@es = get_client
|
20
|
+
# Delete all templates first.
|
21
|
+
# Clean ES of data before we start.
|
22
|
+
@es.indices.delete_template(:name => "*")
|
23
|
+
# This can fail if there are no indexes, ignore failure.
|
24
|
+
@es.indices.delete(:index => "*") rescue nil
|
25
|
+
@es.index(
|
26
|
+
:index => 'logstash-update',
|
27
|
+
:type => doc_type,
|
28
|
+
:id => "123",
|
29
|
+
:body => { :message => 'Test', :counter => 1 }
|
30
|
+
)
|
31
|
+
@es.indices.refresh
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should fail without a document_id" do
|
35
|
+
subject = get_es_output
|
36
|
+
expect { subject.register }.to raise_error(LogStash::ConfigurationError)
|
37
|
+
end
|
38
|
+
|
39
|
+
context "when update only" do
|
40
|
+
it "should not create new document" do
|
41
|
+
subject = get_es_output({ 'document_id' => "456" } )
|
42
|
+
subject.register
|
43
|
+
subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
|
44
|
+
expect {@es.get(:index => 'logstash-update', :type => doc_type, :id => "456", :refresh => true)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should update existing document" do
|
48
|
+
subject = get_es_output({ 'document_id' => "123" })
|
49
|
+
subject.register
|
50
|
+
subject.multi_receive([LogStash::Event.new("message" => "updated message here")])
|
51
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "123", :refresh => true)
|
52
|
+
expect(r["_source"]["message"]).to eq('updated message here')
|
53
|
+
end
|
54
|
+
|
55
|
+
# The es ruby client treats the data field differently. Make sure this doesn't
|
56
|
+
# raise an exception
|
57
|
+
it "should update an existing document that has a 'data' field" do
|
58
|
+
subject = get_es_output({ 'document_id' => "123" })
|
59
|
+
subject.register
|
60
|
+
subject.multi_receive([LogStash::Event.new("data" => "updated message here", "message" => "foo")])
|
61
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "123", :refresh => true)
|
62
|
+
expect(r["_source"]["data"]).to eq('updated message here')
|
63
|
+
expect(r["_source"]["message"]).to eq('foo')
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should allow default (internal) version" do
|
67
|
+
subject = get_es_output({ 'document_id' => "123", "version" => "99" })
|
68
|
+
subject.register
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should allow internal version" do
|
72
|
+
subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "internal" })
|
73
|
+
subject.register
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should not allow external version" do
|
77
|
+
subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "external" })
|
78
|
+
expect { subject.register }.to raise_error(LogStash::ConfigurationError)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should not allow external_gt version" do
|
82
|
+
subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "external_gt" })
|
83
|
+
expect { subject.register }.to raise_error(LogStash::ConfigurationError)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should not allow external_gte version" do
|
87
|
+
subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "external_gte" })
|
88
|
+
expect { subject.register }.to raise_error(LogStash::ConfigurationError)
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
context "when update with upsert" do
|
94
|
+
it "should create new documents with provided upsert" do
|
95
|
+
subject = get_es_output({ 'document_id' => "456", 'upsert' => '{"message": "upsert message"}' })
|
96
|
+
subject.register
|
97
|
+
subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
|
98
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "456", :refresh => true)
|
99
|
+
expect(r["_source"]["message"]).to eq('upsert message')
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should create new documents with event/doc as upsert" do
|
103
|
+
subject = get_es_output({ 'document_id' => "456", 'doc_as_upsert' => true })
|
104
|
+
subject.register
|
105
|
+
subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
|
106
|
+
r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "456", :refresh => true)
|
107
|
+
expect(r["_source"]["message"]).to eq('sample message here')
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should fail on documents with event/doc as upsert at external version" do
|
111
|
+
subject = get_es_output({ 'document_id' => "456", 'doc_as_upsert' => true, 'version' => 999, "version_type" => "external" })
|
112
|
+
expect { subject.register }.to raise_error(LogStash::ConfigurationError)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
2
|
+
# or more contributor license agreements. Licensed under the Elastic License;
|
3
|
+
# you may not use this file except in compliance with the Elastic License.
|
4
|
+
|
5
|
+
module Elasticsearch
|
6
|
+
module API
|
7
|
+
module Actions
|
8
|
+
|
9
|
+
# Update the password of the specified user
|
10
|
+
def delete_ilm_policy(arguments={})
|
11
|
+
method = HTTP_DELETE
|
12
|
+
path = Utils.__pathify '_ilm/policy/',
|
13
|
+
Utils.__escape(arguments[:name])
|
14
|
+
params = {}
|
15
|
+
perform_request(method, path, params, nil).body
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
2
|
+
# or more contributor license agreements. Licensed under the Elastic License;
|
3
|
+
# you may not use this file except in compliance with the Elastic License.
|
4
|
+
|
5
|
+
module Elasticsearch
|
6
|
+
module API
|
7
|
+
module Actions
|
8
|
+
|
9
|
+
# Retrieve the list of index lifecycle management policies
|
10
|
+
def get_alias(arguments={})
|
11
|
+
method = HTTP_GET
|
12
|
+
path = Utils.__pathify '_alias', Utils.__escape(arguments[:name])
|
13
|
+
params = {}
|
14
|
+
perform_request(method, path, params, nil).body
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
2
|
+
# or more contributor license agreements. Licensed under the Elastic License;
|
3
|
+
# you may not use this file except in compliance with the Elastic License.
|
4
|
+
|
5
|
+
module Elasticsearch
|
6
|
+
module API
|
7
|
+
module Actions
|
8
|
+
|
9
|
+
# Retrieve the list of index lifecycle management policies
|
10
|
+
def get_ilm_policy(arguments={})
|
11
|
+
method = HTTP_GET
|
12
|
+
path = Utils.__pathify '_ilm/policy', Utils.__escape(arguments[:name])
|
13
|
+
params = {}
|
14
|
+
perform_request(method, path, params, nil).body
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
2
|
+
# or more contributor license agreements. Licensed under the Elastic License;
|
3
|
+
# you may not use this file except in compliance with the Elastic License.
|
4
|
+
|
5
|
+
module Elasticsearch
|
6
|
+
module API
|
7
|
+
module Actions
|
8
|
+
|
9
|
+
# @option arguments [String] :name The name of the alias (*Required*)
|
10
|
+
# @option arguments [Hash] :The alias definition(*Required*)
|
11
|
+
|
12
|
+
def put_alias(arguments={})
|
13
|
+
raise ArgumentError, "Required argument 'name' missing" unless arguments[:name]
|
14
|
+
raise ArgumentError, "Required argument 'body' missing" unless arguments[:body]
|
15
|
+
method = HTTP_PUT
|
16
|
+
path = Utils.__pathify Utils.__escape(arguments[:name])
|
17
|
+
|
18
|
+
params = Utils.__validate_and_extract_params arguments
|
19
|
+
body = arguments[:body]
|
20
|
+
perform_request(method, path, params, body.to_json).body
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
2
|
+
# or more contributor license agreements. Licensed under the Elastic License;
|
3
|
+
# you may not use this file except in compliance with the Elastic License.
|
4
|
+
|
5
|
+
module Elasticsearch
|
6
|
+
module API
|
7
|
+
module Actions
|
8
|
+
|
9
|
+
# @option arguments [String] :name The name of the policy (*Required*)
|
10
|
+
# @option arguments [Hash] :body The policy definition (*Required*)
|
11
|
+
|
12
|
+
def put_ilm_policy(arguments={})
|
13
|
+
raise ArgumentError, "Required argument 'name' missing" unless arguments[:name]
|
14
|
+
raise ArgumentError, "Required argument 'body' missing" unless arguments[:body]
|
15
|
+
method = HTTP_PUT
|
16
|
+
path = Utils.__pathify '_ilm/policy/', Utils.__escape(arguments[:name])
|
17
|
+
|
18
|
+
params = Utils.__validate_and_extract_params arguments
|
19
|
+
|
20
|
+
body = arguments[:body]
|
21
|
+
perform_request(method, path, params, body.to_json).body
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require "logstash/devutils/rspec/spec_helper"
|
2
|
+
require "logstash/outputs/elasticsearch"
|
3
|
+
require "logstash/outputs/elasticsearch/http_client"
|
4
|
+
require "logstash/outputs/elasticsearch/http_client_builder"
|
5
|
+
|
6
|
+
describe LogStash::Outputs::ElasticSearch::HttpClientBuilder do
|
7
|
+
describe "auth setup with url encodable passwords" do
|
8
|
+
let(:klass) { LogStash::Outputs::ElasticSearch::HttpClientBuilder }
|
9
|
+
let(:user) { "foo@bar"}
|
10
|
+
let(:password) {"baz@blah" }
|
11
|
+
let(:password_secured) do
|
12
|
+
secured = double("password")
|
13
|
+
allow(secured).to receive(:value).and_return(password)
|
14
|
+
secured
|
15
|
+
end
|
16
|
+
let(:options) { {"user" => user, "password" => password} }
|
17
|
+
let(:logger) { mock("logger") }
|
18
|
+
let(:auth_setup) { klass.setup_basic_auth(double("logger"), {"user" => user, "password" => password_secured}) }
|
19
|
+
|
20
|
+
it "should return the user escaped" do
|
21
|
+
expect(auth_setup[:user]).to eql(CGI.escape(user))
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return the password escaped" do
|
25
|
+
expect(auth_setup[:password]).to eql(CGI.escape(password))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "customizing action paths" do
|
30
|
+
let(:hosts) { [ ::LogStash::Util::SafeURI.new("http://localhost:9200") ] }
|
31
|
+
let(:options) { {"hosts" => hosts } }
|
32
|
+
let(:logger) { double("logger") }
|
33
|
+
before :each do
|
34
|
+
[:debug, :debug?, :info?, :info, :warn].each do |level|
|
35
|
+
allow(logger).to receive(level)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "healthcheck_path" do
|
40
|
+
|
41
|
+
context "when setting bulk_path" do
|
42
|
+
let(:bulk_path) { "/meh" }
|
43
|
+
let(:options) { super.merge("bulk_path" => bulk_path) }
|
44
|
+
|
45
|
+
context "when using path" do
|
46
|
+
let(:options) { super.merge("path" => "/path") }
|
47
|
+
it "ignores the path setting" do
|
48
|
+
expect(described_class).to receive(:create_http_client) do |options|
|
49
|
+
expect(options[:bulk_path]).to eq(bulk_path)
|
50
|
+
end
|
51
|
+
described_class.build(logger, hosts, options)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
context "when not using path" do
|
55
|
+
|
56
|
+
it "uses the bulk_path setting" do
|
57
|
+
expect(described_class).to receive(:create_http_client) do |options|
|
58
|
+
expect(options[:bulk_path]).to eq(bulk_path)
|
59
|
+
end
|
60
|
+
described_class.build(logger, hosts, options)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when not setting bulk_path" do
|
66
|
+
|
67
|
+
context "when using path" do
|
68
|
+
let(:path) { "/meh" }
|
69
|
+
let(:options) { super.merge("path" => path) }
|
70
|
+
it "sets bulk_path to path+_bulk" do
|
71
|
+
expect(described_class).to receive(:create_http_client) do |options|
|
72
|
+
expect(options[:bulk_path]).to eq("#{path}/_bulk")
|
73
|
+
end
|
74
|
+
described_class.build(logger, hosts, options)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "when not using path" do
|
79
|
+
it "sets the bulk_path to _bulk" do
|
80
|
+
expect(described_class).to receive(:create_http_client) do |options|
|
81
|
+
expect(options[:bulk_path]).to eq("/_bulk")
|
82
|
+
end
|
83
|
+
described_class.build(logger, hosts, options)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
describe "healthcheck_path" do
|
89
|
+
context "when setting healthcheck_path" do
|
90
|
+
let(:healthcheck_path) { "/meh" }
|
91
|
+
let(:options) { super.merge("healthcheck_path" => healthcheck_path) }
|
92
|
+
|
93
|
+
context "when using path" do
|
94
|
+
let(:options) { super.merge("path" => "/path") }
|
95
|
+
it "ignores the path setting" do
|
96
|
+
expect(described_class).to receive(:create_http_client) do |options|
|
97
|
+
expect(options[:healthcheck_path]).to eq(healthcheck_path)
|
98
|
+
end
|
99
|
+
described_class.build(logger, hosts, options)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
context "when not using path" do
|
103
|
+
|
104
|
+
it "uses the healthcheck_path setting" do
|
105
|
+
expect(described_class).to receive(:create_http_client) do |options|
|
106
|
+
expect(options[:healthcheck_path]).to eq(healthcheck_path)
|
107
|
+
end
|
108
|
+
described_class.build(logger, hosts, options)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "when not setting healthcheck_path" do
|
114
|
+
|
115
|
+
context "when using path" do
|
116
|
+
let(:path) { "/meh" }
|
117
|
+
let(:options) { super.merge("path" => path) }
|
118
|
+
it "sets healthcheck_path to path" do
|
119
|
+
expect(described_class).to receive(:create_http_client) do |options|
|
120
|
+
expect(options[:healthcheck_path]).to eq(path)
|
121
|
+
end
|
122
|
+
described_class.build(logger, hosts, options)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context "when not using path" do
|
127
|
+
it "sets the healthcheck_path to root" do
|
128
|
+
expect(described_class).to receive(:create_http_client) do |options|
|
129
|
+
expect(options[:healthcheck_path]).to eq("/")
|
130
|
+
end
|
131
|
+
described_class.build(logger, hosts, options)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
describe "sniffing_path" do
|
137
|
+
context "when setting sniffing_path" do
|
138
|
+
let(:sniffing_path) { "/meh" }
|
139
|
+
let(:options) { super.merge("sniffing_path" => sniffing_path) }
|
140
|
+
|
141
|
+
context "when using path" do
|
142
|
+
let(:options) { super.merge("path" => "/path") }
|
143
|
+
it "ignores the path setting" do
|
144
|
+
expect(described_class).to receive(:create_http_client) do |options|
|
145
|
+
expect(options[:sniffing_path]).to eq(sniffing_path)
|
146
|
+
end
|
147
|
+
described_class.build(logger, hosts, options)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
context "when not using path" do
|
151
|
+
|
152
|
+
it "uses the sniffing_path setting" do
|
153
|
+
expect(described_class).to receive(:create_http_client) do |options|
|
154
|
+
expect(options[:sniffing_path]).to eq(sniffing_path)
|
155
|
+
end
|
156
|
+
described_class.build(logger, hosts, options)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context "when not setting sniffing_path" do
|
162
|
+
|
163
|
+
context "when using path" do
|
164
|
+
let(:path) { "/meh" }
|
165
|
+
let(:options) { super.merge("path" => path) }
|
166
|
+
it "sets sniffing_path to path+_nodes/http" do
|
167
|
+
expect(described_class).to receive(:create_http_client) do |options|
|
168
|
+
expect(options[:sniffing_path]).to eq("#{path}/_nodes/http")
|
169
|
+
end
|
170
|
+
described_class.build(logger, hosts, options)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context "when not using path" do
|
175
|
+
it "sets the sniffing_path to _nodes/http" do
|
176
|
+
expect(described_class).to receive(:create_http_client) do |options|
|
177
|
+
expect(options[:sniffing_path]).to eq("/_nodes/http")
|
178
|
+
end
|
179
|
+
described_class.build(logger, hosts, options)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require "logstash/devutils/rspec/spec_helper"
|
2
|
+
require "logstash/outputs/elasticsearch/http_client"
|
3
|
+
|
4
|
+
describe LogStash::Outputs::ElasticSearch::HttpClient::ManticoreAdapter do
|
5
|
+
let(:logger) { Cabin::Channel.get }
|
6
|
+
let(:options) { {} }
|
7
|
+
|
8
|
+
subject { described_class.new(logger, options) }
|
9
|
+
|
10
|
+
it "should raise an exception if requests are issued after close" do
|
11
|
+
subject.close
|
12
|
+
expect { subject.perform_request(::LogStash::Util::SafeURI.new("http://localhost:9200"), :get, '/') }.to raise_error(::Manticore::ClientStoppedException)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should implement host unreachable exceptions" do
|
16
|
+
expect(subject.host_unreachable_exceptions).to be_a(Array)
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "auth" do
|
20
|
+
let(:user) { "myuser" }
|
21
|
+
let(:password) { "mypassword" }
|
22
|
+
let(:noauth_uri) { clone = uri.clone; clone.user=nil; clone.password=nil; clone }
|
23
|
+
let(:uri) { ::LogStash::Util::SafeURI.new("http://#{user}:#{password}@localhost:9200") }
|
24
|
+
|
25
|
+
it "should convert the auth to params" do
|
26
|
+
resp = double("response")
|
27
|
+
allow(resp).to receive(:call)
|
28
|
+
allow(resp).to receive(:code).and_return(200)
|
29
|
+
|
30
|
+
expected_uri = noauth_uri.clone
|
31
|
+
expected_uri.path = "/"
|
32
|
+
|
33
|
+
expect(subject.manticore).to receive(:get).
|
34
|
+
with(expected_uri.to_s, {
|
35
|
+
:headers => {"Content-Type" => "application/json"},
|
36
|
+
:auth => {
|
37
|
+
:user => user,
|
38
|
+
:password => password,
|
39
|
+
:eager => true
|
40
|
+
}
|
41
|
+
}).and_return resp
|
42
|
+
|
43
|
+
subject.perform_request(uri, :get, "/")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "bad response codes" do
|
48
|
+
let(:uri) { ::LogStash::Util::SafeURI.new("http://localhost:9200") }
|
49
|
+
|
50
|
+
it "should raise a bad response code error" do
|
51
|
+
resp = double("response")
|
52
|
+
allow(resp).to receive(:call)
|
53
|
+
allow(resp).to receive(:code).and_return(500)
|
54
|
+
allow(resp).to receive(:body).and_return("a body")
|
55
|
+
|
56
|
+
expect(subject.manticore).to receive(:get).
|
57
|
+
with(uri.to_s + "/", anything).
|
58
|
+
and_return(resp)
|
59
|
+
|
60
|
+
uri_with_path = uri.clone
|
61
|
+
uri_with_path.path = "/"
|
62
|
+
|
63
|
+
expect(::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError).to receive(:new).
|
64
|
+
with(resp.code, uri_with_path, nil, resp.body).and_call_original
|
65
|
+
|
66
|
+
expect do
|
67
|
+
subject.perform_request(uri, :get, "/")
|
68
|
+
end.to raise_error(::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "format_url" do
|
73
|
+
let(:url) { ::LogStash::Util::SafeURI.new("http://localhost:9200/path/") }
|
74
|
+
let(:path) { "_bulk" }
|
75
|
+
subject { described_class.new(double("logger"), {}) }
|
76
|
+
|
77
|
+
it "should add the path argument to the uri's path" do
|
78
|
+
expect(subject.format_url(url, path).path).to eq("/path/_bulk")
|
79
|
+
end
|
80
|
+
|
81
|
+
context "when uri contains query parameters" do
|
82
|
+
let(:query_params) { "query=value&key=value2" }
|
83
|
+
let(:url) { ::LogStash::Util::SafeURI.new("http://localhost:9200/path/?#{query_params}") }
|
84
|
+
let(:formatted) { subject.format_url(url, path)}
|
85
|
+
|
86
|
+
it "should retain query_params after format" do
|
87
|
+
expect(formatted.query).to eq(query_params)
|
88
|
+
end
|
89
|
+
|
90
|
+
context "and the path contains query parameters" do
|
91
|
+
let(:path) { "/special_path?specialParam=123" }
|
92
|
+
|
93
|
+
it "should join the query correctly" do
|
94
|
+
expect(formatted.query).to eq(query_params + "&specialParam=123")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when the path contains query parameters" do
|
100
|
+
let(:path) { "/special_bulk?pathParam=1"}
|
101
|
+
let(:formatted) { subject.format_url(url, path) }
|
102
|
+
|
103
|
+
it "should add the path correctly" do
|
104
|
+
expect(formatted.path).to eq("#{url.path}special_bulk")
|
105
|
+
expect(subject.remove_double_escaping(formatted.path)).to eq("#{url.path}special_bulk")
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should add the query parameters correctly" do
|
109
|
+
expect(formatted.query).to eq("pathParam=1")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "when uri contains credentials" do
|
114
|
+
let(:url) { ::LogStash::Util::SafeURI.new("http://myuser:mypass@localhost:9200") }
|
115
|
+
let(:formatted) { subject.format_url(url, path) }
|
116
|
+
|
117
|
+
it "should remove credentials after format" do
|
118
|
+
expect(formatted.userinfo).to be_nil
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'when uri contains date math' do
|
123
|
+
let(:url) { ::LogStash::Util::SafeURI.new("http://localhost:9200") }
|
124
|
+
let(:path) { CGI.escape("<logstash-{now/d}-0001>") }
|
125
|
+
let(:formatted) { subject.format_url(url, path) }
|
126
|
+
|
127
|
+
it 'should escape the uri correctly' do
|
128
|
+
expect(subject.remove_double_escaping(formatted.path)).to eq("/%3Clogstash-%7Bnow%2Fd%7D-0001%3E")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'when uri does not contain date math' do
|
133
|
+
let(:url) { ::LogStash::Util::SafeURI.new("http://localhost:9200") }
|
134
|
+
let(:path) { CGI.escape("logstash-0001") }
|
135
|
+
let(:formatted) { subject.format_url(url, path) }
|
136
|
+
|
137
|
+
it 'should escape the uri correctly' do
|
138
|
+
expect(subject.remove_double_escaping(formatted.path)).to eq("/logstash-0001")
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "integration specs", :integration => true do
|
144
|
+
it "should perform correct tests without error" do
|
145
|
+
resp = subject.perform_request(::LogStash::Util::SafeURI.new("http://localhost:9200"), :get, "/")
|
146
|
+
expect(resp.code).to eql(200)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|