fluent-plugin-splunk-hec 1.1.2 → 1.2.0

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.splunkbeta.com/tenant_name/ingest/v1beta2/events'
10
+ AUTH_TOKEN_ENDPOINT = 'https://api.splunkbeta.com/system/identity/v1/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,41 @@
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.0
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: 2019-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: fluent-plugin-kubernetes_metadata_filter
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 2.1.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 2.1.2
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: fluentd
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
- - - "~>"
31
+ - - '='
18
32
  - !ruby/object:Gem::Version
19
33
  version: '1.4'
20
34
  type: :runtime
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
- - - "~>"
38
+ - - '='
25
39
  - !ruby/object:Gem::Version
26
40
  version: '1.4'
27
41
  - !ruby/object:Gem::Dependency
@@ -52,6 +66,34 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: openid_connect
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.1.6
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.1.6
83
+ - !ruby/object:Gem::Dependency
84
+ name: prometheus-client
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.9.0
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.9.0
55
97
  - !ruby/object:Gem::Dependency
56
98
  name: bundler
57
99
  requirement: !ruby/object:Gem::Requirement
@@ -81,61 +123,75 @@ dependencies:
81
123
  - !ruby/object:Gem::Version
82
124
  version: '12.0'
83
125
  - !ruby/object:Gem::Dependency
84
- name: test-unit
126
+ name: minitest
85
127
  requirement: !ruby/object:Gem::Requirement
86
128
  requirements:
87
129
  - - "~>"
88
130
  - !ruby/object:Gem::Version
89
- version: '3.0'
131
+ version: '5.0'
90
132
  type: :development
91
133
  prerelease: false
92
134
  version_requirements: !ruby/object:Gem::Requirement
93
135
  requirements:
94
136
  - - "~>"
95
137
  - !ruby/object:Gem::Version
96
- version: '3.0'
138
+ version: '5.0'
97
139
  - !ruby/object:Gem::Dependency
98
- name: minitest
140
+ name: rubocop
99
141
  requirement: !ruby/object:Gem::Requirement
100
142
  requirements:
101
143
  - - "~>"
102
144
  - !ruby/object:Gem::Version
103
- version: '5.0'
145
+ version: 0.63.1
104
146
  type: :development
105
147
  prerelease: false
106
148
  version_requirements: !ruby/object:Gem::Requirement
107
149
  requirements:
108
150
  - - "~>"
109
151
  - !ruby/object:Gem::Version
110
- version: '5.0'
152
+ version: 0.63.1
111
153
  - !ruby/object:Gem::Dependency
112
- name: webmock
154
+ name: simplecov
113
155
  requirement: !ruby/object:Gem::Requirement
114
156
  requirements:
115
157
  - - "~>"
116
158
  - !ruby/object:Gem::Version
117
- version: 3.5.0
159
+ version: 0.16.1
118
160
  type: :development
119
161
  prerelease: false
120
162
  version_requirements: !ruby/object:Gem::Requirement
121
163
  requirements:
122
164
  - - "~>"
123
165
  - !ruby/object:Gem::Version
124
- version: 3.5.0
166
+ version: 0.16.1
125
167
  - !ruby/object:Gem::Dependency
126
- name: simplecov
168
+ name: test-unit
127
169
  requirement: !ruby/object:Gem::Requirement
128
170
  requirements:
129
171
  - - "~>"
130
172
  - !ruby/object:Gem::Version
131
- version: 0.16.1
173
+ version: '3.0'
132
174
  type: :development
133
175
  prerelease: false
134
176
  version_requirements: !ruby/object:Gem::Requirement
135
177
  requirements:
136
178
  - - "~>"
137
179
  - !ruby/object:Gem::Version
138
- version: 0.16.1
180
+ version: '3.0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: webmock
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: 3.5.0
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: 3.5.0
139
195
  description: |-
140
196
  A fluentd output plugin created by Splunk
141
197
  that writes events to splunk indexers over HTTP Event Collector API.
@@ -153,15 +209,18 @@ files:
153
209
  - Rakefile
154
210
  - VERSION
155
211
  - fluent-plugin-splunk-hec.gemspec
212
+ - lib/fluent/plugin/out_splunk.rb
213
+ - lib/fluent/plugin/out_splunk/match_formatter.rb
214
+ - lib/fluent/plugin/out_splunk/version.rb
156
215
  - lib/fluent/plugin/out_splunk_hec.rb
157
- - lib/fluent/plugin/out_splunk_hec/match_formatter.rb
158
216
  - lib/fluent/plugin/out_splunk_hec/version.rb
217
+ - lib/fluent/plugin/out_splunk_ingest_api.rb
159
218
  - test/fluent/plugin/out_splunk_hec_test.rb
219
+ - test/fluent/plugin/out_splunk_ingest_api_test.rb
160
220
  - test/lib/webmock/http_lib_adapters/curb_adapter.rb
161
221
  - test/lib/webmock/http_lib_adapters/em_http_request_adapter.rb
162
222
  - test/lib/webmock/http_lib_adapters/excon_adapter.rb
163
223
  - test/lib/webmock/http_lib_adapters/http_rb_adapter.rb
164
- - test/lib/webmock/http_lib_adapters/httpclient_adapter.rb
165
224
  - test/lib/webmock/http_lib_adapters/manticore_adapter.rb
166
225
  - test/lib/webmock/http_lib_adapters/patron_adapter.rb
167
226
  - test/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb
@@ -185,18 +244,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
185
244
  - !ruby/object:Gem::Version
186
245
  version: '0'
187
246
  requirements: []
188
- rubygems_version: 3.0.1
247
+ rubygems_version: 3.0.6
189
248
  signing_key:
190
249
  specification_version: 4
191
250
  summary: Fluentd plugin for Splunk HEC.
192
251
  test_files:
193
- - test/fluent/plugin/out_splunk_hec_test.rb
194
- - test/lib/webmock/http_lib_adapters/patron_adapter.rb
195
- - test/lib/webmock/http_lib_adapters/manticore_adapter.rb
196
252
  - test/lib/webmock/http_lib_adapters/em_http_request_adapter.rb
197
253
  - test/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb
254
+ - test/lib/webmock/http_lib_adapters/patron_adapter.rb
198
255
  - test/lib/webmock/http_lib_adapters/curb_adapter.rb
199
- - test/lib/webmock/http_lib_adapters/httpclient_adapter.rb
256
+ - test/lib/webmock/http_lib_adapters/manticore_adapter.rb
200
257
  - test/lib/webmock/http_lib_adapters/http_rb_adapter.rb
201
258
  - test/lib/webmock/http_lib_adapters/excon_adapter.rb
259
+ - test/fluent/plugin/out_splunk_ingest_api_test.rb
260
+ - test/fluent/plugin/out_splunk_hec_test.rb
202
261
  - test/test_helper.rb