fluent-plugin-splunk-hec 1.1.2 → 1.2.4

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.
@@ -0,0 +1,244 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ describe Fluent::Plugin::SplunkIngestApiOutput do
6
+ include Fluent::Test::Helpers
7
+ include PluginTestHelper
8
+
9
+ INGEST_API_ENDPOINT = 'https://api.scp.splunk.com/tenant_name/ingest/v1beta2/events'
10
+ AUTH_TOKEN_ENDPOINT = 'https://auth.scp.splunk.com/token'
11
+
12
+ before { Fluent::Test.setup } # setup router and others
13
+
14
+ it { expect(::Fluent::Plugin::SplunkIngestApiOutput::VERSION).wont_be_nil }
15
+
16
+ describe 'Required configs validation' do
17
+ it 'should have required fields' do
18
+ expect { create_api_output_driver }.must_raise Fluent::ConfigError
19
+ end
20
+
21
+ describe 'good_config' do
22
+ it {
23
+ instance = create_api_output_driver('service_client_identifier service_client_id',
24
+ 'service_client_secret_key secret_key',
25
+ 'ingest_api_tenant tenant_name').instance
26
+ expect(instance.service_client_identifier).must_equal 'service_client_id'
27
+ expect(instance.service_client_secret_key).must_equal 'secret_key'
28
+ expect(instance.ingest_api_tenant).must_equal 'tenant_name'
29
+ }
30
+ end
31
+ describe 'invalid host' do
32
+ it {
33
+ expect do
34
+ create_api_output_driver('ingest_api_host %bad-host%',
35
+ 'service_client_identifier service_client_id',
36
+ 'service_client_secret_key secret_key',
37
+ 'ingest_api_tenant tenant_name')
38
+ end.must_raise Fluent::ConfigError
39
+ }
40
+ end
41
+ describe 'missing tenant name' do
42
+ it {
43
+ expect do
44
+ create_api_output_driver('ingest_api_host %bad-host%',
45
+ 'service_client_identifier service_client_id',
46
+ 'service_client_secret_key secret_key',
47
+ 'ingest_api_tenant tenant_name')
48
+ end.must_raise Fluent::ConfigError
49
+ }
50
+ end
51
+ describe 'missing client identifier' do
52
+ it {
53
+ expect do
54
+ create_api_output_driver('ingest_api_host %bad-host%',
55
+ 'service_client_secret_key secret_key',
56
+ 'ingest_api_tenant tenant_name')
57
+ end.must_raise Fluent::ConfigError
58
+ }
59
+ end
60
+
61
+ describe 'missing secret key' do
62
+ it {
63
+ expect do
64
+ create_api_output_driver('ingest_api_host %bad-host%',
65
+ 'service_client_identifier service_client_id',
66
+ 'ingest_api_tenant tenant_name')
67
+ end.must_raise Fluent::ConfigError
68
+ }
69
+ end
70
+ end
71
+
72
+ it 'should not fail to start when provided bad auth' do
73
+ stub_failed_auth
74
+ driver = create_api_output_driver('service_client_identifier service_client_id',
75
+ 'service_client_secret_key secret_key',
76
+ 'ingest_api_tenant tenant_name')
77
+ driver.run
78
+ end
79
+
80
+ it 'should send request to Splunk' do
81
+ req = verify_sent_events do |batch|
82
+ expect(batch.size).must_equal 2
83
+ end
84
+ expect(req).must_be_requested times: 1
85
+ end
86
+
87
+ it 'should have an index in the attributes slot' do
88
+ verify_sent_events(conf: %(
89
+ index my_index
90
+ )) do |batch|
91
+ batch.each do |item|
92
+ expect(item['attributes']['index']).must_equal 'my_index'
93
+ end
94
+ end
95
+ end
96
+
97
+ it 'should have attrbutes not fields' do
98
+ verify_sent_events do |batch|
99
+ batch.each do |item|
100
+ expect(item).wont_include :fields
101
+ expect(item).includes :attributes
102
+ end
103
+ end
104
+ end
105
+
106
+ it 'should have body not event' do
107
+ verify_sent_events do |batch|
108
+ batch.each do |item|
109
+ expect(item).wont_include :event
110
+ expect(item).includes :body
111
+ end
112
+ end
113
+ end
114
+
115
+ it 'should have a timestamp and nanos' do
116
+ verify_sent_events do |batch|
117
+ batch.each do |item|
118
+ expect(item).wont_include :time
119
+ expect(item).includes :timestamp
120
+ expect(item).includes :nanos
121
+ end
122
+ end
123
+ end
124
+
125
+ it 'should raise error on 401/429 to force retry' do
126
+ # Try to quiet this down some.
127
+ report_on_exception = Thread.report_on_exception
128
+ Thread.report_on_exception = false
129
+ begin
130
+ expect do
131
+ verify_sent_events status: 429
132
+ end.must_raise RuntimeError
133
+
134
+ expect do
135
+ verify_sent_events status: 401
136
+ end.must_raise RuntimeError
137
+ ensure
138
+ Thread.report_on_exception = report_on_exception
139
+ end
140
+ end
141
+
142
+ it 'should not send an empty log message' do
143
+ verify_sent_events conf: %(
144
+ <format>
145
+ @type single_value
146
+ message_key log
147
+ add_newline false
148
+ </format>), event: { 'log' => "\n" } do |batch|
149
+ batch.each do |_item|
150
+ raise 'No message should be sent'
151
+ end
152
+ end
153
+ end
154
+
155
+ # it 'should send index from filters' do
156
+ # verify_sent_events conf: %[
157
+ # <filter>
158
+ # @type record_transformer
159
+ # enable_ruby
160
+ # <record>
161
+ # index ${ENV['SPLUNK_INDEX']}
162
+ # </record>
163
+ # </filter>
164
+ # ], event: {"log" => "This is the log", "index" => "indexname"} do |batch|
165
+ # batch.each do |item|
166
+ # item[:attrbutes][:index].
167
+ # fail "No message should be sent"
168
+ # end
169
+ # end
170
+ # end
171
+
172
+ def create_api_output_driver(*configs)
173
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::SplunkIngestApiOutput).tap do |d|
174
+ d.configure(configs.join("\n"))
175
+ end
176
+ end
177
+
178
+ DEFAULT_EVENT = {
179
+ log: 'everything is good',
180
+ level: 'info',
181
+ from: 'my_machine',
182
+ file: 'cool.log',
183
+ value: 100,
184
+ agent: {
185
+ name: 'test',
186
+ version: '1.0.0'
187
+ }
188
+ }.freeze
189
+
190
+ def verify_sent_events(args = {})
191
+ conf = args[:conf] || ''
192
+ event = args[:event] || DEFAULT_EVENT
193
+ status = args[:status] || 200
194
+
195
+ events = [
196
+ ['tag.event1', event_time, { id: '1st' }.merge(Marshal.load(Marshal.dump(event)))],
197
+ ['tag.event2', event_time, { id: '2nd' }.merge(Marshal.load(Marshal.dump(event)))]
198
+ ]
199
+
200
+ @driver = create_api_output_driver('service_client_identifier service_client_id',
201
+ 'service_client_secret_key secret_key',
202
+ 'ingest_api_tenant tenant_name',
203
+ conf)
204
+
205
+ api_req = if status == 200
206
+ stub_successful_api_request.with do |r|
207
+ yield r.body.split(/(?={)\s*(?<=})/).map { |item| JSON.load item }.first
208
+ end
209
+ else
210
+ stub_failed_api_request status
211
+ end
212
+
213
+ @driver.run do
214
+ events.each { |evt| @driver.feed *evt }
215
+ end
216
+
217
+ api_req
218
+ end
219
+
220
+ def stub_successful_auth
221
+ stub_request(:post, AUTH_TOKEN_ENDPOINT)
222
+ .to_return(body: '{"access_token":"bearer token","token_type":"Bearer","expires_in":432000,"scope":"client_credentials"}')
223
+ end
224
+
225
+ def stub_failed_auth
226
+ stub_request(:post, AUTH_TOKEN_ENDPOINT)
227
+ .to_return(status: 401,
228
+ body: '{"error":"invalid_client","error_description":"The client secret supplied for a confidential client is invalid."}')
229
+ end
230
+
231
+ def stub_successful_api_request
232
+ stub_successful_auth
233
+
234
+ stub_request(:post, INGEST_API_ENDPOINT)
235
+ .to_return(body: '{"message":"Success","code":"SUCCESS"}')
236
+ end
237
+
238
+ def stub_failed_api_request(status)
239
+ stub_successful_auth
240
+
241
+ stub_request(:post, INGEST_API_ENDPOINT)
242
+ .to_return(body: '', status: status)
243
+ end
244
+ end
@@ -1,9 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'simplecov'
2
4
  SimpleCov.start
3
5
 
4
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
5
- $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
6
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
7
+ $LOAD_PATH.unshift File.expand_path('lib', __dir__)
6
8
  require 'fluent/plugin/out_splunk_hec'
9
+ require 'fluent/plugin/out_splunk_ingest_api'
7
10
 
8
11
  require 'fluent/test'
9
12
  require 'fluent/test/driver/output'
@@ -17,7 +20,7 @@ module Minitest::Expectations
17
20
  infect_an_assertion :assert_not_requested, :wont_be_requested, :reverse
18
21
  end
19
22
 
20
- TEST_HEC_TOKEN = 'some-token'.freeze
23
+ TEST_HEC_TOKEN = 'some-token'
21
24
 
22
25
  module PluginTestHelper
23
26
  def fluentd_conf_for(*lines)
@@ -27,16 +30,16 @@ module PluginTestHelper
27
30
  (basic_config + lines).join("\n")
28
31
  end
29
32
 
30
- def create_output_driver(*configs)
31
- Fluent::Test::Driver::Output.new(Fluent::Plugin::SplunkHecOutput).tap { |d|
33
+ def create_hec_output_driver(*configs)
34
+ Fluent::Test::Driver::Output.new(Fluent::Plugin::SplunkHecOutput).tap do |d|
32
35
  d.configure(fluentd_conf_for(*configs))
33
- }
36
+ end
34
37
  end
35
38
 
36
39
  def stub_hec_request(endpoint)
37
40
  stub_request(:post, "#{endpoint}/services/collector")
38
41
  .with(headers: { 'Authorization' => "Splunk #{TEST_HEC_TOKEN}",
39
- 'User-Agent' => "fluent-plugin-splunk_hec_out/#{Fluent::Plugin::SplunkHecOutput::VERSION}" })
42
+ 'User-Agent' => "fluent-plugin-splunk_hec_out/#{Fluent::Plugin::SplunkHecOutput::VERSION}" })
40
43
  .to_return(body: '{"text":"Success","code":0}')
41
44
  end
42
45
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-splunk-hec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Splunk Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-12 00:00:00.000000000 Z
11
+ date: 2020-08-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.4'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.4'
27
27
  - !ruby/object:Gem::Dependency
@@ -44,14 +44,42 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.0'
47
+ version: '3.1'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.0'
54
+ version: '3.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: openid_connect
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.1.8
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.1.8
69
+ - !ruby/object:Gem::Dependency
70
+ name: prometheus-client
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "<"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.10.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "<"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.10.0
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: bundler
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -70,72 +98,86 @@ dependencies:
70
98
  name: rake
71
99
  requirement: !ruby/object:Gem::Requirement
72
100
  requirements:
73
- - - "~>"
101
+ - - ">="
74
102
  - !ruby/object:Gem::Version
75
103
  version: '12.0'
76
104
  type: :development
77
105
  prerelease: false
78
106
  version_requirements: !ruby/object:Gem::Requirement
79
107
  requirements:
80
- - - "~>"
108
+ - - ">="
81
109
  - !ruby/object:Gem::Version
82
110
  version: '12.0'
83
111
  - !ruby/object:Gem::Dependency
84
- name: test-unit
112
+ name: minitest
85
113
  requirement: !ruby/object:Gem::Requirement
86
114
  requirements:
87
115
  - - "~>"
88
116
  - !ruby/object:Gem::Version
89
- version: '3.0'
117
+ version: '5.0'
90
118
  type: :development
91
119
  prerelease: false
92
120
  version_requirements: !ruby/object:Gem::Requirement
93
121
  requirements:
94
122
  - - "~>"
95
123
  - !ruby/object:Gem::Version
96
- version: '3.0'
124
+ version: '5.0'
97
125
  - !ruby/object:Gem::Dependency
98
- name: minitest
126
+ name: rubocop
99
127
  requirement: !ruby/object:Gem::Requirement
100
128
  requirements:
101
129
  - - "~>"
102
130
  - !ruby/object:Gem::Version
103
- version: '5.0'
131
+ version: 0.63.1
104
132
  type: :development
105
133
  prerelease: false
106
134
  version_requirements: !ruby/object:Gem::Requirement
107
135
  requirements:
108
136
  - - "~>"
109
137
  - !ruby/object:Gem::Version
110
- version: '5.0'
138
+ version: 0.63.1
111
139
  - !ruby/object:Gem::Dependency
112
- name: webmock
140
+ name: simplecov
113
141
  requirement: !ruby/object:Gem::Requirement
114
142
  requirements:
115
143
  - - "~>"
116
144
  - !ruby/object:Gem::Version
117
- version: 3.5.0
145
+ version: 0.16.1
118
146
  type: :development
119
147
  prerelease: false
120
148
  version_requirements: !ruby/object:Gem::Requirement
121
149
  requirements:
122
150
  - - "~>"
123
151
  - !ruby/object:Gem::Version
124
- version: 3.5.0
152
+ version: 0.16.1
125
153
  - !ruby/object:Gem::Dependency
126
- name: simplecov
154
+ name: test-unit
127
155
  requirement: !ruby/object:Gem::Requirement
128
156
  requirements:
129
157
  - - "~>"
130
158
  - !ruby/object:Gem::Version
131
- version: 0.16.1
159
+ version: '3.0'
132
160
  type: :development
133
161
  prerelease: false
134
162
  version_requirements: !ruby/object:Gem::Requirement
135
163
  requirements:
136
164
  - - "~>"
137
165
  - !ruby/object:Gem::Version
138
- version: 0.16.1
166
+ version: '3.0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: webmock
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: 3.5.0
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: 3.5.0
139
181
  description: |-
140
182
  A fluentd output plugin created by Splunk
141
183
  that writes events to splunk indexers over HTTP Event Collector API.
@@ -153,15 +195,18 @@ files:
153
195
  - Rakefile
154
196
  - VERSION
155
197
  - fluent-plugin-splunk-hec.gemspec
198
+ - lib/fluent/plugin/out_splunk.rb
199
+ - lib/fluent/plugin/out_splunk/match_formatter.rb
200
+ - lib/fluent/plugin/out_splunk/version.rb
156
201
  - lib/fluent/plugin/out_splunk_hec.rb
157
- - lib/fluent/plugin/out_splunk_hec/match_formatter.rb
158
202
  - lib/fluent/plugin/out_splunk_hec/version.rb
203
+ - lib/fluent/plugin/out_splunk_ingest_api.rb
159
204
  - test/fluent/plugin/out_splunk_hec_test.rb
205
+ - test/fluent/plugin/out_splunk_ingest_api_test.rb
160
206
  - test/lib/webmock/http_lib_adapters/curb_adapter.rb
161
207
  - test/lib/webmock/http_lib_adapters/em_http_request_adapter.rb
162
208
  - test/lib/webmock/http_lib_adapters/excon_adapter.rb
163
209
  - test/lib/webmock/http_lib_adapters/http_rb_adapter.rb
164
- - test/lib/webmock/http_lib_adapters/httpclient_adapter.rb
165
210
  - test/lib/webmock/http_lib_adapters/manticore_adapter.rb
166
211
  - test/lib/webmock/http_lib_adapters/patron_adapter.rb
167
212
  - test/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb
@@ -185,18 +230,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
185
230
  - !ruby/object:Gem::Version
186
231
  version: '0'
187
232
  requirements: []
188
- rubygems_version: 3.0.1
233
+ rubygems_version: 3.0.6
189
234
  signing_key:
190
235
  specification_version: 4
191
236
  summary: Fluentd plugin for Splunk HEC.
192
237
  test_files:
193
238
  - test/fluent/plugin/out_splunk_hec_test.rb
239
+ - test/fluent/plugin/out_splunk_ingest_api_test.rb
194
240
  - test/lib/webmock/http_lib_adapters/patron_adapter.rb
195
241
  - test/lib/webmock/http_lib_adapters/manticore_adapter.rb
196
242
  - test/lib/webmock/http_lib_adapters/em_http_request_adapter.rb
197
243
  - test/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb
198
244
  - test/lib/webmock/http_lib_adapters/curb_adapter.rb
199
- - test/lib/webmock/http_lib_adapters/httpclient_adapter.rb
200
245
  - test/lib/webmock/http_lib_adapters/http_rb_adapter.rb
201
246
  - test/lib/webmock/http_lib_adapters/excon_adapter.rb
202
247
  - test/test_helper.rb