logstash-output-elasticsearch-test 10.3.0-x86_64-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +397 -0
  3. data/CONTRIBUTORS +33 -0
  4. data/Gemfile +15 -0
  5. data/LICENSE +13 -0
  6. data/NOTICE.TXT +5 -0
  7. data/README.md +106 -0
  8. data/docs/index.asciidoc +899 -0
  9. data/lib/logstash/outputs/elasticsearch/common.rb +441 -0
  10. data/lib/logstash/outputs/elasticsearch/common_configs.rb +167 -0
  11. data/lib/logstash/outputs/elasticsearch/default-ilm-policy.json +14 -0
  12. data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es2x.json +95 -0
  13. data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es5x.json +46 -0
  14. data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es6x.json +45 -0
  15. data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es7x.json +44 -0
  16. data/lib/logstash/outputs/elasticsearch/elasticsearch-template-es8x.json +44 -0
  17. data/lib/logstash/outputs/elasticsearch/http_client/manticore_adapter.rb +131 -0
  18. data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +495 -0
  19. data/lib/logstash/outputs/elasticsearch/http_client.rb +432 -0
  20. data/lib/logstash/outputs/elasticsearch/http_client_builder.rb +159 -0
  21. data/lib/logstash/outputs/elasticsearch/ilm.rb +113 -0
  22. data/lib/logstash/outputs/elasticsearch/template_manager.rb +61 -0
  23. data/lib/logstash/outputs/elasticsearch.rb +263 -0
  24. data/logstash-output-elasticsearch.gemspec +33 -0
  25. data/spec/es_spec_helper.rb +189 -0
  26. data/spec/fixtures/_nodes/2x_1x.json +27 -0
  27. data/spec/fixtures/_nodes/5x_6x.json +81 -0
  28. data/spec/fixtures/_nodes/7x.json +92 -0
  29. data/spec/fixtures/htpasswd +2 -0
  30. data/spec/fixtures/nginx_reverse_proxy.conf +22 -0
  31. data/spec/fixtures/scripts/groovy/scripted_update.groovy +2 -0
  32. data/spec/fixtures/scripts/groovy/scripted_update_nested.groovy +2 -0
  33. data/spec/fixtures/scripts/groovy/scripted_upsert.groovy +2 -0
  34. data/spec/fixtures/scripts/painless/scripted_update.painless +2 -0
  35. data/spec/fixtures/scripts/painless/scripted_update_nested.painless +1 -0
  36. data/spec/fixtures/scripts/painless/scripted_upsert.painless +1 -0
  37. data/spec/fixtures/template-with-policy-es6x.json +48 -0
  38. data/spec/fixtures/template-with-policy-es7x.json +45 -0
  39. data/spec/fixtures/test_certs/ca/ca.crt +32 -0
  40. data/spec/fixtures/test_certs/ca/ca.key +51 -0
  41. data/spec/fixtures/test_certs/test.crt +36 -0
  42. data/spec/fixtures/test_certs/test.key +51 -0
  43. data/spec/integration/outputs/compressed_indexing_spec.rb +69 -0
  44. data/spec/integration/outputs/create_spec.rb +67 -0
  45. data/spec/integration/outputs/delete_spec.rb +65 -0
  46. data/spec/integration/outputs/groovy_update_spec.rb +150 -0
  47. data/spec/integration/outputs/ilm_spec.rb +531 -0
  48. data/spec/integration/outputs/index_spec.rb +178 -0
  49. data/spec/integration/outputs/index_version_spec.rb +102 -0
  50. data/spec/integration/outputs/ingest_pipeline_spec.rb +74 -0
  51. data/spec/integration/outputs/metrics_spec.rb +70 -0
  52. data/spec/integration/outputs/no_es_on_startup_spec.rb +58 -0
  53. data/spec/integration/outputs/painless_update_spec.rb +189 -0
  54. data/spec/integration/outputs/parent_spec.rb +102 -0
  55. data/spec/integration/outputs/retry_spec.rb +169 -0
  56. data/spec/integration/outputs/routing_spec.rb +61 -0
  57. data/spec/integration/outputs/sniffer_spec.rb +133 -0
  58. data/spec/integration/outputs/templates_5x_spec.rb +98 -0
  59. data/spec/integration/outputs/templates_spec.rb +98 -0
  60. data/spec/integration/outputs/update_spec.rb +116 -0
  61. data/spec/support/elasticsearch/api/actions/delete_ilm_policy.rb +19 -0
  62. data/spec/support/elasticsearch/api/actions/get_alias.rb +18 -0
  63. data/spec/support/elasticsearch/api/actions/get_ilm_policy.rb +18 -0
  64. data/spec/support/elasticsearch/api/actions/put_alias.rb +24 -0
  65. data/spec/support/elasticsearch/api/actions/put_ilm_policy.rb +25 -0
  66. data/spec/unit/http_client_builder_spec.rb +185 -0
  67. data/spec/unit/outputs/elasticsearch/http_client/manticore_adapter_spec.rb +149 -0
  68. data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +274 -0
  69. data/spec/unit/outputs/elasticsearch/http_client_spec.rb +250 -0
  70. data/spec/unit/outputs/elasticsearch/template_manager_spec.rb +25 -0
  71. data/spec/unit/outputs/elasticsearch_proxy_spec.rb +72 -0
  72. data/spec/unit/outputs/elasticsearch_spec.rb +675 -0
  73. data/spec/unit/outputs/elasticsearch_ssl_spec.rb +82 -0
  74. data/spec/unit/outputs/error_whitelist_spec.rb +54 -0
  75. 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