logstash-output-opensearch 1.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/ADMINS.md +29 -0
  5. data/CODE_OF_CONDUCT.md +25 -0
  6. data/CONTRIBUTING.md +99 -0
  7. data/DEVELOPER_GUIDE.md +208 -0
  8. data/Gemfile +20 -0
  9. data/LICENSE +202 -0
  10. data/MAINTAINERS.md +71 -0
  11. data/NOTICE +2 -0
  12. data/README.md +37 -0
  13. data/RELEASING.md +36 -0
  14. data/SECURITY.md +3 -0
  15. data/lib/logstash/outputs/opensearch.rb +449 -0
  16. data/lib/logstash/outputs/opensearch/distribution_checker.rb +44 -0
  17. data/lib/logstash/outputs/opensearch/http_client.rb +465 -0
  18. data/lib/logstash/outputs/opensearch/http_client/manticore_adapter.rb +140 -0
  19. data/lib/logstash/outputs/opensearch/http_client/pool.rb +467 -0
  20. data/lib/logstash/outputs/opensearch/http_client_builder.rb +182 -0
  21. data/lib/logstash/outputs/opensearch/template_manager.rb +60 -0
  22. data/lib/logstash/outputs/opensearch/templates/ecs-disabled/1x.json +44 -0
  23. data/lib/logstash/outputs/opensearch/templates/ecs-disabled/7x.json +44 -0
  24. data/lib/logstash/plugin_mixins/opensearch/api_configs.rb +168 -0
  25. data/lib/logstash/plugin_mixins/opensearch/common.rb +294 -0
  26. data/lib/logstash/plugin_mixins/opensearch/noop_distribution_checker.rb +18 -0
  27. data/logstash-output-opensearch.gemspec +40 -0
  28. data/spec/fixtures/_nodes/nodes.json +74 -0
  29. data/spec/fixtures/htpasswd +2 -0
  30. data/spec/fixtures/nginx_reverse_proxy.conf +22 -0
  31. data/spec/fixtures/scripts/painless/scripted_update.painless +2 -0
  32. data/spec/fixtures/scripts/painless/scripted_update_nested.painless +1 -0
  33. data/spec/fixtures/scripts/painless/scripted_upsert.painless +1 -0
  34. data/spec/integration/outputs/compressed_indexing_spec.rb +76 -0
  35. data/spec/integration/outputs/create_spec.rb +76 -0
  36. data/spec/integration/outputs/delete_spec.rb +72 -0
  37. data/spec/integration/outputs/index_spec.rb +164 -0
  38. data/spec/integration/outputs/index_version_spec.rb +110 -0
  39. data/spec/integration/outputs/ingest_pipeline_spec.rb +82 -0
  40. data/spec/integration/outputs/metrics_spec.rb +75 -0
  41. data/spec/integration/outputs/no_opensearch_on_startup_spec.rb +67 -0
  42. data/spec/integration/outputs/painless_update_spec.rb +147 -0
  43. data/spec/integration/outputs/parent_spec.rb +103 -0
  44. data/spec/integration/outputs/retry_spec.rb +182 -0
  45. data/spec/integration/outputs/routing_spec.rb +70 -0
  46. data/spec/integration/outputs/sniffer_spec.rb +70 -0
  47. data/spec/integration/outputs/templates_spec.rb +105 -0
  48. data/spec/integration/outputs/update_spec.rb +123 -0
  49. data/spec/opensearch_spec_helper.rb +141 -0
  50. data/spec/spec_helper.rb +19 -0
  51. data/spec/unit/http_client_builder_spec.rb +194 -0
  52. data/spec/unit/outputs/error_whitelist_spec.rb +62 -0
  53. data/spec/unit/outputs/opensearch/http_client/manticore_adapter_spec.rb +159 -0
  54. data/spec/unit/outputs/opensearch/http_client/pool_spec.rb +306 -0
  55. data/spec/unit/outputs/opensearch/http_client_spec.rb +292 -0
  56. data/spec/unit/outputs/opensearch/template_manager_spec.rb +36 -0
  57. data/spec/unit/outputs/opensearch_proxy_spec.rb +112 -0
  58. data/spec/unit/outputs/opensearch_spec.rb +800 -0
  59. data/spec/unit/outputs/opensearch_ssl_spec.rb +179 -0
  60. metadata +289 -0
  61. metadata.gz.sig +0 -0
@@ -0,0 +1,141 @@
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
+ require_relative './spec_helper'
11
+
12
+ require 'elasticsearch'
13
+
14
+ require 'json'
15
+ require 'cabin'
16
+
17
+ module OpenSearchHelper
18
+ def get_host_port
19
+ if ENV["INTEGRATION"] == "true"
20
+ "integration:9200"
21
+ else
22
+ "localhost:9200"
23
+ end
24
+ end
25
+
26
+ def get_client
27
+ Elasticsearch::Client.new(:hosts => [get_host_port])
28
+ end
29
+
30
+ def doc_type
31
+ "_doc"
32
+ end
33
+
34
+ def todays_date
35
+ Time.now.strftime("%Y.%m.%d")
36
+ end
37
+
38
+ def field_properties_from_template(template_name, field)
39
+ template = get_template(@client, template_name)
40
+ mappings = get_template_mappings(template)
41
+ mappings["properties"][field]["properties"]
42
+ end
43
+
44
+ def routing_field_name
45
+ :routing
46
+ end
47
+
48
+ def self.version
49
+ RSpec.configuration.filter[:version]
50
+ end
51
+
52
+ RSpec::Matchers.define :have_hits do |expected|
53
+ match do |actual|
54
+ expected == actual['hits']['total']['value']
55
+ end
56
+ end
57
+
58
+ RSpec::Matchers.define :have_index_pattern do |expected|
59
+ match do |actual|
60
+ test_against = Array(actual['index_patterns'].nil? ? actual['template'] : actual['index_patterns'])
61
+ test_against.include?(expected)
62
+ end
63
+ end
64
+
65
+ def clean(client)
66
+ client.indices.delete_template(:name => "*")
67
+ client.indices.delete_index_template(:name => "logstash*") rescue nil
68
+ # This can fail if there are no indexes, ignore failure.
69
+ client.indices.delete(:index => "*") rescue nil
70
+ end
71
+
72
+ def set_cluster_settings(client, cluster_settings)
73
+ client.cluster.put_settings(body: cluster_settings)
74
+ get_cluster_settings(client)
75
+ end
76
+
77
+ def get_cluster_settings(client)
78
+ client.cluster.get_settings
79
+ end
80
+
81
+ def put_alias(client, the_alias, index)
82
+ body = {
83
+ "aliases" => {
84
+ index => {
85
+ "is_write_index"=> true
86
+ }
87
+ }
88
+ }
89
+ client.put_alias({name: the_alias, body: body})
90
+ end
91
+
92
+ def max_docs_policy(max_docs)
93
+ {
94
+ "policy" => {
95
+ "phases"=> {
96
+ "hot" => {
97
+ "actions" => {
98
+ "rollover" => {
99
+ "max_docs" => max_docs
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }
106
+ end
107
+
108
+ def max_age_policy(max_age)
109
+ {
110
+ "policy" => {
111
+ "phases"=> {
112
+ "hot" => {
113
+ "actions" => {
114
+ "rollover" => {
115
+ "max_age" => max_age
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+ }
122
+ end
123
+
124
+ def get_template(client, name)
125
+ t = client.indices.get_template(name: name)
126
+ # TODO: use index template if version >= 7.8 & OpenSearch
127
+ t[name]
128
+ end
129
+
130
+ def get_template_settings(template)
131
+ template['template']
132
+ end
133
+
134
+ def get_template_mappings(template)
135
+ template['mappings']
136
+ end
137
+ end
138
+
139
+ RSpec.configure do |config|
140
+ config.include OpenSearchHelper
141
+ end
@@ -0,0 +1,19 @@
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
+ require "logstash/devutils/rspec/spec_helper"
11
+
12
+ require "logstash/outputs/opensearch"
13
+
14
+ module LogStash::Outputs::OpenSearch::SpecHelper
15
+ end
16
+
17
+ RSpec.configure do |config|
18
+ config.include LogStash::Outputs::OpenSearch::SpecHelper
19
+ end
@@ -0,0 +1,194 @@
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
+ require "logstash/devutils/rspec/spec_helper"
11
+ require "logstash/outputs/opensearch"
12
+ require "logstash/outputs/opensearch/http_client"
13
+ require "logstash/outputs/opensearch/http_client_builder"
14
+
15
+ describe LogStash::Outputs::OpenSearch::HttpClientBuilder do
16
+ describe "auth setup with url encodable passwords" do
17
+ let(:klass) { LogStash::Outputs::OpenSearch::HttpClientBuilder }
18
+ let(:user) { "foo@bar"}
19
+ let(:password) {"baz@blah" }
20
+ let(:password_secured) do
21
+ secured = double("password")
22
+ allow(secured).to receive(:value).and_return(password)
23
+ secured
24
+ end
25
+ let(:options) { {"user" => user, "password" => password} }
26
+ let(:logger) { mock("logger") }
27
+ let(:auth_setup) { klass.setup_basic_auth(double("logger"), {"user" => user, "password" => password_secured}) }
28
+
29
+ it "should return the user escaped" do
30
+ expect(auth_setup[:user]).to eql(CGI.escape(user))
31
+ end
32
+
33
+ it "should return the password escaped" do
34
+ expect(auth_setup[:password]).to eql(CGI.escape(password))
35
+ end
36
+ end
37
+
38
+ describe "customizing action paths" do
39
+ let(:hosts) { [ ::LogStash::Util::SafeURI.new("http://localhost:9200") ] }
40
+ let(:options) { {"hosts" => hosts } }
41
+ let(:logger) { double("logger") }
42
+ before :each do
43
+ [:debug, :debug?, :info?, :info, :warn].each do |level|
44
+ allow(logger).to receive(level)
45
+ end
46
+ end
47
+
48
+ describe "healthcheck_path" do
49
+
50
+ context "when setting bulk_path" do
51
+ let(:bulk_path) { "/meh" }
52
+ let(:options) { super().merge("bulk_path" => bulk_path) }
53
+
54
+ context "when using path" do
55
+ let(:options) { super().merge("path" => "/path") }
56
+ it "ignores the 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
+ context "when not using path" do
64
+
65
+ it "uses the bulk_path setting" do
66
+ expect(described_class).to receive(:create_http_client) do |options|
67
+ expect(options[:bulk_path]).to eq(bulk_path)
68
+ end
69
+ described_class.build(logger, hosts, options)
70
+ end
71
+ end
72
+ end
73
+
74
+ context "when not setting bulk_path" do
75
+
76
+ context "when using path" do
77
+ let(:path) { "/meh" }
78
+ let(:options) { super().merge("path" => path) }
79
+ it "sets bulk_path to path+_bulk" do
80
+ expect(described_class).to receive(:create_http_client) do |options|
81
+ expect(options[:bulk_path]).to eq("#{path}/_bulk")
82
+ end
83
+ described_class.build(logger, hosts, options)
84
+ end
85
+ end
86
+
87
+ context "when not using path" do
88
+ it "sets the bulk_path to _bulk" do
89
+ expect(described_class).to receive(:create_http_client) do |options|
90
+ expect(options[:bulk_path]).to eq("/_bulk")
91
+ end
92
+ described_class.build(logger, hosts, options)
93
+ end
94
+ end
95
+ end
96
+ end
97
+ describe "healthcheck_path" do
98
+ context "when setting healthcheck_path" do
99
+ let(:healthcheck_path) { "/meh" }
100
+ let(:options) { super().merge("healthcheck_path" => healthcheck_path) }
101
+
102
+ context "when using path" do
103
+ let(:options) { super().merge("path" => "/path") }
104
+ it "ignores the 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
+ context "when not using path" do
112
+
113
+ it "uses the healthcheck_path setting" do
114
+ expect(described_class).to receive(:create_http_client) do |options|
115
+ expect(options[:healthcheck_path]).to eq(healthcheck_path)
116
+ end
117
+ described_class.build(logger, hosts, options)
118
+ end
119
+ end
120
+ end
121
+
122
+ context "when not setting healthcheck_path" do
123
+
124
+ context "when using path" do
125
+ let(:path) { "/meh" }
126
+ let(:options) { super().merge("path" => path) }
127
+ it "sets healthcheck_path to path" do
128
+ expect(described_class).to receive(:create_http_client) do |options|
129
+ expect(options[:healthcheck_path]).to eq(path)
130
+ end
131
+ described_class.build(logger, hosts, options)
132
+ end
133
+ end
134
+
135
+ context "when not using path" do
136
+ it "sets the healthcheck_path to root" do
137
+ expect(described_class).to receive(:create_http_client) do |options|
138
+ expect(options[:healthcheck_path]).to eq("/")
139
+ end
140
+ described_class.build(logger, hosts, options)
141
+ end
142
+ end
143
+ end
144
+ end
145
+ describe "sniffing_path" do
146
+ context "when setting sniffing_path" do
147
+ let(:sniffing_path) { "/meh" }
148
+ let(:options) { super().merge("sniffing_path" => sniffing_path) }
149
+
150
+ context "when using path" do
151
+ let(:options) { super().merge("path" => "/path") }
152
+ it "ignores the 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
+ context "when not using path" do
160
+
161
+ it "uses the sniffing_path setting" do
162
+ expect(described_class).to receive(:create_http_client) do |options|
163
+ expect(options[:sniffing_path]).to eq(sniffing_path)
164
+ end
165
+ described_class.build(logger, hosts, options)
166
+ end
167
+ end
168
+ end
169
+
170
+ context "when not setting sniffing_path" do
171
+
172
+ context "when using path" do
173
+ let(:path) { "/meh" }
174
+ let(:options) { super().merge("path" => path) }
175
+ it "sets sniffing_path to path+_nodes/http" do
176
+ expect(described_class).to receive(:create_http_client) do |options|
177
+ expect(options[:sniffing_path]).to eq("#{path}/_nodes/http")
178
+ end
179
+ described_class.build(logger, hosts, options)
180
+ end
181
+ end
182
+
183
+ context "when not using path" do
184
+ it "sets the sniffing_path to _nodes/http" do
185
+ expect(described_class).to receive(:create_http_client) do |options|
186
+ expect(options[:sniffing_path]).to eq("/_nodes/http")
187
+ end
188
+ described_class.build(logger, hosts, options)
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,62 @@
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
+ require "logstash/outputs/opensearch"
11
+ require_relative "../../../spec/opensearch_spec_helper"
12
+
13
+ describe "whitelisting error types in expected behavior" do
14
+ let(:template) { '{"template" : "not important, will be updated by :index"}' }
15
+ let(:event1) { LogStash::Event.new("somevalue" => 100, "@timestamp" => "2014-11-17T20:37:17.223Z") }
16
+ let(:action1) { ["index", {:_id=>1, :routing=>nil, :_index=>"logstash-2014.11.17", :_type=> doc_type }, event1] }
17
+ let(:settings) { {"manage_template" => true, "index" => "logstash-2014.11.17", "template_overwrite" => true, "hosts" => get_host_port() } }
18
+
19
+ subject { LogStash::Outputs::OpenSearch.new(settings) }
20
+
21
+ before :each do
22
+ allow(subject.logger).to receive(:warn)
23
+ allow(subject).to receive(:maximum_seen_major_version).and_return(0)
24
+ allow(subject).to receive(:finish_register)
25
+
26
+ subject.register
27
+ allow(subject.client).to receive(:bulk).and_return(
28
+ {
29
+ "errors" => true,
30
+ "items" => [{
31
+ "create" => {
32
+ "status" => 409,
33
+ "error" => {
34
+ "type" => "document_already_exists_exception",
35
+ "reason" => "[shard] document already exists"
36
+ }
37
+ }
38
+ }]
39
+ })
40
+
41
+ subject.multi_receive([event1])
42
+ end
43
+
44
+ after :each do
45
+ subject.close
46
+ end
47
+
48
+ describe "when failure logging is enabled for everything" do
49
+ it "should log a failure on the action" do
50
+ expect(subject.logger).to have_received(:warn).with("Failed action", anything)
51
+ end
52
+ end
53
+
54
+ describe "when failure logging is disabled for docuemnt exists error" do
55
+ let(:settings) { super().merge("failure_type_logging_whitelist" => ["document_already_exists_exception"]) }
56
+
57
+ it "should log a failure on the action" do
58
+ expect(subject.logger).not_to have_received(:warn).with("Failed action", anything)
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,159 @@
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
+ require "logstash/devutils/rspec/spec_helper"
11
+ require "logstash/outputs/opensearch/http_client"
12
+ require 'cabin'
13
+
14
+ describe LogStash::Outputs::OpenSearch::HttpClient::ManticoreAdapter do
15
+ let(:logger) { Cabin::Channel.get }
16
+ let(:options) { {} }
17
+
18
+ subject { described_class.new(logger, options) }
19
+
20
+ it "should raise an exception if requests are issued after close" do
21
+ subject.close
22
+ expect { subject.perform_request(::LogStash::Util::SafeURI.new("http://localhost:9200"), :get, '/') }.to raise_error(::Manticore::ClientStoppedException)
23
+ end
24
+
25
+ it "should implement host unreachable exceptions" do
26
+ expect(subject.host_unreachable_exceptions).to be_a(Array)
27
+ end
28
+
29
+ describe "auth" do
30
+ let(:user) { "myuser" }
31
+ let(:password) { "mypassword" }
32
+ let(:noauth_uri) { clone = uri.clone; clone.user=nil; clone.password=nil; clone }
33
+ let(:uri) { ::LogStash::Util::SafeURI.new("http://#{user}:#{password}@localhost:9200") }
34
+
35
+ it "should convert the auth to params" do
36
+ resp = double("response")
37
+ allow(resp).to receive(:call)
38
+ allow(resp).to receive(:code).and_return(200)
39
+
40
+ expected_uri = noauth_uri.clone
41
+ expected_uri.path = "/"
42
+
43
+ expect(subject.manticore).to receive(:get).
44
+ with(expected_uri.to_s, {
45
+ :headers => {"Content-Type" => "application/json"},
46
+ :auth => {
47
+ :user => user,
48
+ :password => password,
49
+ :eager => true
50
+ }
51
+ }).and_return resp
52
+
53
+ subject.perform_request(uri, :get, "/")
54
+ end
55
+ end
56
+
57
+ describe "bad response codes" do
58
+ let(:uri) { ::LogStash::Util::SafeURI.new("http://localhost:9200") }
59
+
60
+ it "should raise a bad response code error" do
61
+ resp = double("response")
62
+ allow(resp).to receive(:call)
63
+ allow(resp).to receive(:code).and_return(500)
64
+ allow(resp).to receive(:body).and_return("a body")
65
+
66
+ expect(subject.manticore).to receive(:get).
67
+ with(uri.to_s + "/", anything).
68
+ and_return(resp)
69
+
70
+ uri_with_path = uri.clone
71
+ uri_with_path.path = "/"
72
+
73
+ expect(::LogStash::Outputs::OpenSearch::HttpClient::Pool::BadResponseCodeError).to receive(:new).
74
+ with(resp.code, uri_with_path, nil, resp.body).and_call_original
75
+
76
+ expect do
77
+ subject.perform_request(uri, :get, "/")
78
+ end.to raise_error(::LogStash::Outputs::OpenSearch::HttpClient::Pool::BadResponseCodeError)
79
+ end
80
+ end
81
+
82
+ describe "format_url" do
83
+ let(:url) { ::LogStash::Util::SafeURI.new("http://localhost:9200/path/") }
84
+ let(:path) { "_bulk" }
85
+ subject { described_class.new(double("logger"), {}) }
86
+
87
+ it "should add the path argument to the uri's path" do
88
+ expect(subject.format_url(url, path).path).to eq("/path/_bulk")
89
+ end
90
+
91
+ context "when uri contains query parameters" do
92
+ let(:query_params) { "query=value&key=value2" }
93
+ let(:url) { ::LogStash::Util::SafeURI.new("http://localhost:9200/path/?#{query_params}") }
94
+ let(:formatted) { subject.format_url(url, path)}
95
+
96
+ it "should retain query_params after format" do
97
+ expect(formatted.query).to eq(query_params)
98
+ end
99
+
100
+ context "and the path contains query parameters" do
101
+ let(:path) { "/special_path?specialParam=123" }
102
+
103
+ it "should join the query correctly" do
104
+ expect(formatted.query).to eq(query_params + "&specialParam=123")
105
+ end
106
+ end
107
+ end
108
+
109
+ context "when the path contains query parameters" do
110
+ let(:path) { "/special_bulk?pathParam=1"}
111
+ let(:formatted) { subject.format_url(url, path) }
112
+
113
+ it "should add the path correctly" do
114
+ expect(formatted.path).to eq("#{url.path}special_bulk")
115
+ expect(subject.remove_double_escaping(formatted.path)).to eq("#{url.path}special_bulk")
116
+ end
117
+
118
+ it "should add the query parameters correctly" do
119
+ expect(formatted.query).to eq("pathParam=1")
120
+ end
121
+ end
122
+
123
+ context "when uri contains credentials" do
124
+ let(:url) { ::LogStash::Util::SafeURI.new("http://myuser:mypass@localhost:9200") }
125
+ let(:formatted) { subject.format_url(url, path) }
126
+
127
+ it "should remove credentials after format" do
128
+ expect(formatted.userinfo).to be_nil
129
+ end
130
+ end
131
+
132
+ context 'when uri contains date math' do
133
+ let(:url) { ::LogStash::Util::SafeURI.new("http://localhost:9200") }
134
+ let(:path) { CGI.escape("<logstash-{now/d}-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("/%3Clogstash-%7Bnow%2Fd%7D-0001%3E")
139
+ end
140
+ end
141
+
142
+ context 'when uri does not contain date math' do
143
+ let(:url) { ::LogStash::Util::SafeURI.new("http://localhost:9200") }
144
+ let(:path) { CGI.escape("logstash-0001") }
145
+ let(:formatted) { subject.format_url(url, path) }
146
+
147
+ it 'should escape the uri correctly' do
148
+ expect(subject.remove_double_escaping(formatted.path)).to eq("/logstash-0001")
149
+ end
150
+ end
151
+ end
152
+
153
+ describe "integration specs", :integration => true do
154
+ it "should perform correct tests without error" do
155
+ resp = subject.perform_request(::LogStash::Util::SafeURI.new("http://localhost:9200"), :get, "/")
156
+ expect(resp.code).to eql(200)
157
+ end
158
+ end
159
+ end