logstash-output-elasticsearch-test 11.16.0-x86_64-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +649 -0
  3. data/CONTRIBUTORS +34 -0
  4. data/Gemfile +16 -0
  5. data/LICENSE +202 -0
  6. data/NOTICE.TXT +5 -0
  7. data/README.md +106 -0
  8. data/docs/index.asciidoc +1369 -0
  9. data/lib/logstash/outputs/elasticsearch/data_stream_support.rb +282 -0
  10. data/lib/logstash/outputs/elasticsearch/default-ilm-policy.json +14 -0
  11. data/lib/logstash/outputs/elasticsearch/http_client/manticore_adapter.rb +155 -0
  12. data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +534 -0
  13. data/lib/logstash/outputs/elasticsearch/http_client.rb +497 -0
  14. data/lib/logstash/outputs/elasticsearch/http_client_builder.rb +201 -0
  15. data/lib/logstash/outputs/elasticsearch/ilm.rb +92 -0
  16. data/lib/logstash/outputs/elasticsearch/license_checker.rb +52 -0
  17. data/lib/logstash/outputs/elasticsearch/template_manager.rb +131 -0
  18. data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-6x.json +45 -0
  19. data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-7x.json +44 -0
  20. data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-8x.json +50 -0
  21. data/lib/logstash/outputs/elasticsearch.rb +699 -0
  22. data/lib/logstash/plugin_mixins/elasticsearch/api_configs.rb +237 -0
  23. data/lib/logstash/plugin_mixins/elasticsearch/common.rb +409 -0
  24. data/lib/logstash/plugin_mixins/elasticsearch/noop_license_checker.rb +9 -0
  25. data/logstash-output-elasticsearch.gemspec +40 -0
  26. data/spec/es_spec_helper.rb +225 -0
  27. data/spec/fixtures/_nodes/6x.json +81 -0
  28. data/spec/fixtures/_nodes/7x.json +92 -0
  29. data/spec/fixtures/htpasswd +2 -0
  30. data/spec/fixtures/license_check/active.json +16 -0
  31. data/spec/fixtures/license_check/inactive.json +5 -0
  32. data/spec/fixtures/nginx_reverse_proxy.conf +22 -0
  33. data/spec/fixtures/scripts/painless/scripted_update.painless +2 -0
  34. data/spec/fixtures/scripts/painless/scripted_update_nested.painless +1 -0
  35. data/spec/fixtures/scripts/painless/scripted_upsert.painless +1 -0
  36. data/spec/fixtures/template-with-policy-es6x.json +48 -0
  37. data/spec/fixtures/template-with-policy-es7x.json +45 -0
  38. data/spec/fixtures/template-with-policy-es8x.json +50 -0
  39. data/spec/fixtures/test_certs/ca.crt +29 -0
  40. data/spec/fixtures/test_certs/ca.der.sha256 +1 -0
  41. data/spec/fixtures/test_certs/ca.key +51 -0
  42. data/spec/fixtures/test_certs/renew.sh +13 -0
  43. data/spec/fixtures/test_certs/test.crt +30 -0
  44. data/spec/fixtures/test_certs/test.der.sha256 +1 -0
  45. data/spec/fixtures/test_certs/test.key +51 -0
  46. data/spec/fixtures/test_certs/test.p12 +0 -0
  47. data/spec/fixtures/test_certs/test_invalid.crt +36 -0
  48. data/spec/fixtures/test_certs/test_invalid.key +51 -0
  49. data/spec/fixtures/test_certs/test_invalid.p12 +0 -0
  50. data/spec/fixtures/test_certs/test_self_signed.crt +32 -0
  51. data/spec/fixtures/test_certs/test_self_signed.key +54 -0
  52. data/spec/fixtures/test_certs/test_self_signed.p12 +0 -0
  53. data/spec/integration/outputs/compressed_indexing_spec.rb +70 -0
  54. data/spec/integration/outputs/create_spec.rb +67 -0
  55. data/spec/integration/outputs/data_stream_spec.rb +68 -0
  56. data/spec/integration/outputs/delete_spec.rb +63 -0
  57. data/spec/integration/outputs/ilm_spec.rb +534 -0
  58. data/spec/integration/outputs/index_spec.rb +421 -0
  59. data/spec/integration/outputs/index_version_spec.rb +98 -0
  60. data/spec/integration/outputs/ingest_pipeline_spec.rb +75 -0
  61. data/spec/integration/outputs/metrics_spec.rb +66 -0
  62. data/spec/integration/outputs/no_es_on_startup_spec.rb +78 -0
  63. data/spec/integration/outputs/painless_update_spec.rb +99 -0
  64. data/spec/integration/outputs/parent_spec.rb +94 -0
  65. data/spec/integration/outputs/retry_spec.rb +182 -0
  66. data/spec/integration/outputs/routing_spec.rb +61 -0
  67. data/spec/integration/outputs/sniffer_spec.rb +94 -0
  68. data/spec/integration/outputs/templates_spec.rb +133 -0
  69. data/spec/integration/outputs/unsupported_actions_spec.rb +75 -0
  70. data/spec/integration/outputs/update_spec.rb +114 -0
  71. data/spec/spec_helper.rb +10 -0
  72. data/spec/support/elasticsearch/api/actions/delete_ilm_policy.rb +19 -0
  73. data/spec/support/elasticsearch/api/actions/get_alias.rb +18 -0
  74. data/spec/support/elasticsearch/api/actions/get_ilm_policy.rb +18 -0
  75. data/spec/support/elasticsearch/api/actions/put_alias.rb +24 -0
  76. data/spec/support/elasticsearch/api/actions/put_ilm_policy.rb +25 -0
  77. data/spec/unit/http_client_builder_spec.rb +185 -0
  78. data/spec/unit/outputs/elasticsearch/data_stream_support_spec.rb +612 -0
  79. data/spec/unit/outputs/elasticsearch/http_client/manticore_adapter_spec.rb +151 -0
  80. data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +501 -0
  81. data/spec/unit/outputs/elasticsearch/http_client_spec.rb +339 -0
  82. data/spec/unit/outputs/elasticsearch/template_manager_spec.rb +189 -0
  83. data/spec/unit/outputs/elasticsearch_proxy_spec.rb +103 -0
  84. data/spec/unit/outputs/elasticsearch_spec.rb +1573 -0
  85. data/spec/unit/outputs/elasticsearch_ssl_spec.rb +197 -0
  86. data/spec/unit/outputs/error_whitelist_spec.rb +56 -0
  87. data/spec/unit/outputs/license_check_spec.rb +57 -0
  88. metadata +423 -0
@@ -0,0 +1,133 @@
1
+ require_relative "../../../spec/es_spec_helper"
2
+
3
+ describe "index template expected behavior", :integration => true do
4
+ let(:ecs_compatibility) { fail('spec group does not define `ecs_compatibility`!') }
5
+
6
+ subject! do
7
+ require "logstash/outputs/elasticsearch"
8
+ allow_any_instance_of(LogStash::Outputs::ElasticSearch).to receive(:ecs_compatibility).and_return(ecs_compatibility)
9
+
10
+ settings = {
11
+ "manage_template" => true,
12
+ "template_overwrite" => true,
13
+ "hosts" => "#{get_host_port()}"
14
+ }
15
+ next LogStash::Outputs::ElasticSearch.new(settings)
16
+ end
17
+
18
+ let(:elasticsearch_client) { get_client }
19
+
20
+ before(:each) do
21
+ # delete indices and templates
22
+ require "elasticsearch"
23
+
24
+ elasticsearch_client.indices.delete_template(:name => '*')
25
+ # This can fail if there are no indexes, ignore failure.
26
+ elasticsearch_client.indices.delete(:index => '*') rescue puts("DELETE INDICES ERROR: #{$!}")
27
+ # Since we are pinned to ES client 7.x, we need to delete data streams the hard way...
28
+ elasticsearch_client.perform_request("DELETE", "/_data_stream/*") rescue puts("DELETE DATA STREAMS ERROR: #{$!}")
29
+ end
30
+
31
+ context 'with ecs_compatibility => disabled' do
32
+ let(:ecs_compatibility) { :disabled }
33
+ before :each do
34
+ @es = elasticsearch_client # cache as ivar for tests...
35
+
36
+ subject.register
37
+
38
+ subject.multi_receive([
39
+ LogStash::Event.new("message" => "sample message here"),
40
+ LogStash::Event.new("somemessage" => { "message" => "sample nested message here" }),
41
+ LogStash::Event.new("somevalue" => 100),
42
+ LogStash::Event.new("somevalue" => 10),
43
+ LogStash::Event.new("somevalue" => 1),
44
+ LogStash::Event.new("country" => "us"),
45
+ LogStash::Event.new("country" => "at"),
46
+ LogStash::Event.new("geoip" => { "location" => [ 0.0, 0.0 ] })
47
+ ])
48
+
49
+ @es.indices.refresh
50
+
51
+ # Wait or fail until everything's indexed.
52
+ Stud::try(20.times) do
53
+ r = @es.search(index: 'logstash*')
54
+ expect(r).to have_hits(8)
55
+ end
56
+ end
57
+
58
+ it "permits phrase searching on string fields" do
59
+ results = @es.search(index: 'logstash*', q: "message:\"sample message\"")
60
+ expect(results).to have_hits(1)
61
+ expect(results["hits"]["hits"][0]["_source"]["message"]).to eq("sample message here")
62
+ end
63
+
64
+ it "numbers dynamically map to a numeric type and permit range queries" do
65
+ results = @es.search(index: 'logstash*', q: "somevalue:[5 TO 105]")
66
+ expect(results).to have_hits(2)
67
+
68
+ values = results["hits"]["hits"].collect { |r| r["_source"]["somevalue"] }
69
+ expect(values).to include(10)
70
+ expect(values).to include(100)
71
+ expect(values).to_not include(1)
72
+ end
73
+
74
+ it "does not create .keyword field for top-level message field" do
75
+ results = @es.search(index: 'logstash*', q: "message.keyword:\"sample message here\"")
76
+ expect(results).to have_hits(0)
77
+ end
78
+
79
+ it "creates .keyword field for nested message fields" do
80
+ results = @es.search(index: 'logstash*', q: "somemessage.message.keyword:\"sample nested message here\"")
81
+ expect(results).to have_hits(1)
82
+ end
83
+
84
+ it "creates .keyword field from any string field which is not_analyzed" do
85
+ results = @es.search(index: 'logstash*', q: "country.keyword:\"us\"")
86
+ expect(results).to have_hits(1)
87
+ expect(results["hits"]["hits"][0]["_source"]["country"]).to eq("us")
88
+
89
+ # partial or terms should not work.
90
+ results = @es.search(index: 'logstash*', q: "country.keyword:\"u\"")
91
+ expect(results).to have_hits(0)
92
+ end
93
+
94
+ it "make [geoip][location] a geo_point" do
95
+ expect(field_properties_from_template("logstash", "geoip")["location"]["type"]).to eq("geo_point")
96
+ end
97
+
98
+ it "aggregate .keyword results correctly " do
99
+ results = @es.search(index: 'logstash*', body: { "aggregations" => { "my_agg" => { "terms" => { "field" => "country.keyword" } } } })["aggregations"]["my_agg"]
100
+ terms = results["buckets"].collect { |b| b["key"] }
101
+
102
+ expect(terms).to include("us")
103
+
104
+ # 'at' is a stopword, make sure stopwords are not ignored.
105
+ expect(terms).to include("at")
106
+ end
107
+ end
108
+
109
+ context 'with ECS enabled' do
110
+ let(:ecs_compatibility) { :v1 }
111
+
112
+ before(:each) do
113
+ subject.register # should load template?
114
+ subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
115
+ end
116
+
117
+ let(:elasticsearch_cluster_major_version) do
118
+ elasticsearch_client.info&.dig("version", "number" )&.split('.')&.map(&:to_i)&.first
119
+ end
120
+
121
+ it 'loads the templates' do
122
+ aggregate_failures do
123
+ if elasticsearch_cluster_major_version >= 8
124
+ # In ES 8+ we use the _index_template API
125
+ expect(elasticsearch_client.indices.exists_index_template(name: 'ecs-logstash')).to be_truthy
126
+ else
127
+ # Otherwise, we used the legacy _template API
128
+ expect(elasticsearch_client.indices.exists_template(name: 'ecs-logstash')).to be_truthy
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,75 @@
1
+ require_relative "../../../spec/es_spec_helper"
2
+
3
+ describe "Unsupported actions testing...", :integration => true do
4
+ require "logstash/outputs/elasticsearch"
5
+
6
+ INDEX = "logstash-unsupported-actions-rejected"
7
+
8
+ def get_es_output( options={} )
9
+ settings = {
10
+ "manage_template" => true,
11
+ "index" => INDEX,
12
+ "template_overwrite" => true,
13
+ "hosts" => get_host_port(),
14
+ "action" => "%{action_field}",
15
+ "document_id" => "%{doc_id}",
16
+ "ecs_compatibility" => "disabled"
17
+ }
18
+ LogStash::Outputs::ElasticSearch.new(settings.merge!(options))
19
+ end
20
+
21
+ before :each do
22
+ @es = get_client
23
+ # Delete all templates first.
24
+ # Clean ES of data before we start.
25
+ @es.indices.delete_template(:name => "*")
26
+ # This can fail if there are no indexes, ignore failure.
27
+ @es.indices.delete(:index => "*") rescue nil
28
+ # index single doc for update purpose
29
+ @es.index(
30
+ :index => INDEX,
31
+ :type => doc_type,
32
+ :id => "2",
33
+ :body => { :message => 'Test to doc indexing', :counter => 1 }
34
+ )
35
+ @es.index(
36
+ :index => INDEX,
37
+ :type => doc_type,
38
+ :id => "3",
39
+ :body => { :message => 'Test to doc deletion', :counter => 2 }
40
+ )
41
+ @es.indices.refresh
42
+ end
43
+
44
+ context "multiple actions include unsupported action" do
45
+ let(:events) {[
46
+ LogStash::Event.new("action_field" => "index", "doc_id" => 1, "message"=> "hello"),
47
+ LogStash::Event.new("action_field" => "update", "doc_id" => 2, "message"=> "hi"),
48
+ LogStash::Event.new("action_field" => "delete", "doc_id" => 3),
49
+ LogStash::Event.new("action_field" => "unsupported_action", "doc_id" => 4, "message"=> "world!")
50
+ ]}
51
+
52
+ it "should reject unsupported doc" do
53
+ subject = get_es_output
54
+ subject.register
55
+ subject.multi_receive(events)
56
+
57
+ index_or_update = proc do |event|
58
+ action = event.get("action_field")
59
+ action.eql?("index") || action.eql?("update")
60
+ end
61
+
62
+ indexed_events = events.select { |event| index_or_update.call(event) }
63
+ rejected_events = events.select { |event| !index_or_update.call(event) }
64
+
65
+ indexed_events.each do |event|
66
+ response = @es.get(:index => INDEX, :type => doc_type, :id => event.get("doc_id"), :refresh => true)
67
+ expect(response['_source']['message']).to eq(event.get("message"))
68
+ end
69
+
70
+ rejected_events.each do |event|
71
+ expect {@es.get(:index => INDEX, :type => doc_type, :id => event.get("doc_id"), :refresh => true)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,114 @@
1
+ require_relative "../../../spec/es_spec_helper"
2
+
3
+ describe "Update actions without scripts", :integration => true do
4
+ require "logstash/outputs/elasticsearch"
5
+
6
+ def get_es_output( options={} )
7
+ settings = {
8
+ "manage_template" => true,
9
+ "index" => "logstash-update",
10
+ "template_overwrite" => true,
11
+ "hosts" => get_host_port(),
12
+ "action" => "update"
13
+ }
14
+ LogStash::Outputs::ElasticSearch.new(settings.merge!(options))
15
+ end
16
+
17
+ before :each do
18
+ @es = get_client
19
+ # Delete all templates first.
20
+ # Clean ES of data before we start.
21
+ @es.indices.delete_template(:name => "*")
22
+ # This can fail if there are no indexes, ignore failure.
23
+ @es.indices.delete(:index => "*") rescue nil
24
+ @es.index(
25
+ :index => 'logstash-update',
26
+ :type => doc_type,
27
+ :id => "123",
28
+ :body => { :message => 'Test', :counter => 1 }
29
+ )
30
+ @es.indices.refresh
31
+ end
32
+
33
+ it "should fail without a document_id" do
34
+ subject = get_es_output
35
+ expect { subject.register }.to raise_error(LogStash::ConfigurationError)
36
+ end
37
+
38
+ context "when update only" do
39
+ it "should not create new document" do
40
+ subject = get_es_output({ 'document_id' => "456" } )
41
+ subject.register
42
+ subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
43
+ expect {@es.get(:index => 'logstash-update', :type => doc_type, :id => "456", :refresh => true)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
44
+ end
45
+
46
+ it "should update existing document" do
47
+ subject = get_es_output({ 'document_id' => "123" })
48
+ subject.register
49
+ subject.multi_receive([LogStash::Event.new("message" => "updated message here")])
50
+ r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "123", :refresh => true)
51
+ expect(r["_source"]["message"]).to eq('updated message here')
52
+ end
53
+
54
+ # The es ruby client treats the data field differently. Make sure this doesn't
55
+ # raise an exception
56
+ it "should update an existing document that has a 'data' field" do
57
+ subject = get_es_output({ 'document_id' => "123" })
58
+ subject.register
59
+ subject.multi_receive([LogStash::Event.new("data" => "updated message here", "message" => "foo")])
60
+ r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "123", :refresh => true)
61
+ expect(r["_source"]["data"]).to eq('updated message here')
62
+ expect(r["_source"]["message"]).to eq('foo')
63
+ end
64
+
65
+ it "should allow default (internal) version" do
66
+ subject = get_es_output({ 'document_id' => "123", "version" => "99" })
67
+ subject.register
68
+ end
69
+
70
+ it "should allow internal version" do
71
+ subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "internal" })
72
+ subject.register
73
+ end
74
+
75
+ it "should not allow external version" do
76
+ subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "external" })
77
+ expect { subject.register }.to raise_error(LogStash::ConfigurationError)
78
+ end
79
+
80
+ it "should not allow external_gt version" do
81
+ subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "external_gt" })
82
+ expect { subject.register }.to raise_error(LogStash::ConfigurationError)
83
+ end
84
+
85
+ it "should not allow external_gte version" do
86
+ subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "external_gte" })
87
+ expect { subject.register }.to raise_error(LogStash::ConfigurationError)
88
+ end
89
+
90
+ end
91
+
92
+ context "when update with upsert" do
93
+ it "should create new documents with provided upsert" do
94
+ subject = get_es_output({ 'document_id' => "456", 'upsert' => '{"message": "upsert message"}' })
95
+ subject.register
96
+ subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
97
+ r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "456", :refresh => true)
98
+ expect(r["_source"]["message"]).to eq('upsert message')
99
+ end
100
+
101
+ it "should create new documents with event/doc as upsert" do
102
+ subject = get_es_output({ 'document_id' => "456", 'doc_as_upsert' => true })
103
+ subject.register
104
+ subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
105
+ r = @es.get(:index => 'logstash-update', :type => doc_type, :id => "456", :refresh => true)
106
+ expect(r["_source"]["message"]).to eq('sample message here')
107
+ end
108
+
109
+ it "should fail on documents with event/doc as upsert at external version" do
110
+ subject = get_es_output({ 'document_id' => "456", 'doc_as_upsert' => true, 'version' => 999, "version_type" => "external" })
111
+ expect { subject.register }.to raise_error(LogStash::ConfigurationError)
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,10 @@
1
+ require "logstash/devutils/rspec/spec_helper"
2
+
3
+ require "logstash/outputs/elasticsearch"
4
+
5
+ module LogStash::Outputs::ElasticSearch::SpecHelper
6
+ end
7
+
8
+ RSpec.configure do |config|
9
+ config.include LogStash::Outputs::ElasticSearch::SpecHelper
10
+ 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