fluent-plugin-ipinfo 1.0.2 → 1.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b7f4f8cb5ce41b6e9406b3dd3f88b737f4c25e7b727f9ad05027f83dceebab3
4
- data.tar.gz: aad770ddea261401fb88e81eeecbf411e894ecfb6e8d5b1174dfdd0092f07c3a
3
+ metadata.gz: 2e715ffb9f1f67768b47a75a2909da48be93f43c882d78e135d69c70a3dc9678
4
+ data.tar.gz: 3c002e087f57d526771d43408f2692a0c459b4b266a14623f655d19e83fc79d8
5
5
  SHA512:
6
- metadata.gz: 3476241da4cb77bf3b9a444f0f68041694685b7b2be85b27a2e663f6c113df2156385784f748771baaf9a084bd4a2580d561d9d97de273cc75f9560e10947bce
7
- data.tar.gz: 6833261bdfe609470cd168556ee5075b3e307b53dbd4f5d7c186617e0c50cc09d2466dc54466b7e0d60739b4c01b40d4f64fecb1be17196127825a4fe0199b5e
6
+ metadata.gz: f9269e76e2018277b28e2572b540612fa968d7ebb71ea2e60580f762f3bdfbed5c5aa83d799a4b9ac085c6ffca07a451be4cf01988ce5c5e6409ee421e9031e2
7
+ data.tar.gz: 07210a8a3082bfe1ce5dfb47d0433deb9157d7aaeff4e03b7e3bdb90233e4535547ade6c9d4ad229f11ce0506c1cd926ffcf7f1540aea98b4cfa1ab08d73ae6b
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fluent-plugin-ipinfo (1.0.2)
4
+ fluent-plugin-ipinfo (1.1.0)
5
5
  IPinfo (~> 1.0, >= 1.0.1)
6
6
  fluentd (>= 0.14.2, < 2)
7
7
 
data/README.md CHANGED
@@ -39,7 +39,7 @@ In this example, the following event:
39
39
  }
40
40
  ```
41
41
 
42
- Would be enriched and returned as following:
42
+ would be enriched and returned as following:
43
43
 
44
44
  ```json
45
45
  {
@@ -68,6 +68,8 @@ Would be enriched and returned as following:
68
68
  The token to be used with the IPInfo API for paid plans.
69
69
  To use the free plan (limited to 50k requests per month), do not use the `access_token` parameter.
70
70
 
71
+ If the value provided for `access_token` is an empty string (`""` or `" "`), the default value (`nil`) is used instead.
72
+
71
73
  ### `key_name`
72
74
 
73
75
  | type | required | default |
@@ -76,6 +78,8 @@ To use the free plan (limited to 50k requests per month), do not use the `access
76
78
 
77
79
  The name of the key containing the IP address.
78
80
 
81
+ If the value provided for `key_name` is an empty string (`""` or `" "`) or `nil`, the default value (`ip_address`) is used instead.
82
+
79
83
  ### `out_key`
80
84
 
81
85
  | type | required | default |
@@ -84,6 +88,46 @@ The name of the key containing the IP address.
84
88
 
85
89
  The name of the key to store the geographical location data in.
86
90
 
91
+ If the value provided for `out_key` is an empty string (`""` or `" "`) or `nil`, the default value (`ipinfo`) is used instead.
92
+
93
+ If the record has already a key with the same name as the value of `out_key`, its value will be overwritten with the geographical location data as shown in the example below:
94
+
95
+ ```xml
96
+ <filter foo.bar>
97
+ @type ipinfo
98
+ access_token 1a2b3c4d5e
99
+ key_name ip_address
100
+ out_key data
101
+ fields ["country_name", "region", "city", "latitude", "longitude"]
102
+ </filter>
103
+ ```
104
+
105
+ The following event:
106
+
107
+ ```json
108
+ {
109
+ "message":"Can you get me the geographical location for this IP addresse ?",
110
+ "ip_address":"8.8.8.8",
111
+ "data": "This value is going to be overwritten."
112
+ }
113
+ ```
114
+
115
+ would be enriched and returned as following:
116
+
117
+ ```json
118
+ {
119
+ "message": "Can you get me the geographical location for this IP addresse ?",
120
+ "ip_address": "8.8.8.8",
121
+ "data": {
122
+ "country_name": "United States",
123
+ "region": "California",
124
+ "city": "Mountain View",
125
+ "latitude": "37.4056",
126
+ "longitude": "-122.0775"
127
+ }
128
+ }
129
+ ```
130
+
87
131
  ### `fields`
88
132
 
89
133
  | type | required | default |
@@ -2,7 +2,7 @@ $:.push File.expand_path("../lib", __FILE__)
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "fluent-plugin-ipinfo"
5
- s.version = "1.0.2"
5
+ s.version = "1.1.0"
6
6
  s.license = "Apache-2.0"
7
7
  s.authors = ["Ahmed Abdelkafi"]
8
8
  s.email = ["abdelkafiahmed@gmail.com"]
@@ -35,41 +35,76 @@ module Fluent::Plugin
35
35
 
36
36
  def initialize
37
37
  super
38
- # "maxsize": 4096 # Number of entries to keep in cache
39
- # "ttl": 60 * 60 * 24 * 7 # Keep the data in cache for one week
40
- @ipinfo_settings = {:ttl => 604800, :maxsize => 4096}
38
+ # Keep the data in cache for one week
39
+ # Number of entries to keep in cache
40
+ @ipinfo_cache_settings = {:ttl => 60 * 60 * 24 * 7, :maxsize => 4096}
41
41
  end
42
42
 
43
43
  def configure(conf)
44
44
  super
45
+
46
+ if !@access_token.nil? and @access_token.strip.empty?
47
+ log.warn "access_token value is an empty string. Falling back to default value."
48
+ @access_token = nil
49
+ end
50
+
51
+ if @key_name.nil? or @key_name.strip.empty?
52
+ log.warn "key_name value is '#{@key_name}'. Falling back to default value."
53
+ @key_name = 'ip_address'
54
+ end
55
+
56
+ if @out_key.nil? or @out_key.strip.empty?
57
+ log.warn "out_key value is '#{@out_key}'. Falling back to default value."
58
+ @out_key = 'ipinfo'
59
+ end
60
+
61
+ # Delete duplicates and empty fields (nil values included)
62
+ @fields = @fields.uniq.delete_if {|f| f.strip.empty? or f.nil?}
63
+
64
+ unless @fields.length() > 0
65
+ raise Fluent::ConfigError, "Fields array is empty. You need to specify at least one field."
66
+ end
67
+
68
+ # Create the IPInfo client handler
45
69
  unless @access_token.nil?
46
- @ipinfo_handler = IPinfo::create(@access_token, @ipinfo_settings)
70
+ @ipinfo_handler = IPinfo::create(@access_token, @ipinfo_cache_settings)
47
71
  else
48
- @ipinfo_handler = IPinfo::create(nil, @ipinfo_settings)
72
+ @ipinfo_handler = IPinfo::create(nil, @ipinfo_cache_settings)
49
73
  end
50
74
  end
51
75
 
52
76
  def filter(tag, time, record)
53
- ip_address = record[@key_name]
54
- unless ip_address.nil?
55
- # Fetch geolocation details using IPInfo API
56
- ipinfo_details = @ipinfo_handler.details(ip_address)
57
- # IPInfo ruby wrapper returns a dict based on symbols, we need to stringify the symbols
58
- # to be able to use them easily
59
- all_details = ipinfo_details.all
60
- geodata = all_details.stringify_keys
61
- # Get the final list of fields by running a join operation on the fields provided by the user and the ones
62
- # returned by IPInfo API
63
- ipinfo_returned_fields = geodata.keys
64
- final_fields = ipinfo_returned_fields & @fields
65
- if final_fields.length() != @fields.length()
66
- ignored_fields = @fields - final_fields
67
- ignored_fields.each{|field|
68
- log.warn "Field \"" + field + "\" not present in IPInfo payload. Ignoring it."
69
- }
77
+ # Check that the record has a key whose name is the value of @key_name
78
+ unless record.key?(@key_name)
79
+ log.error "key '#{@key_name}' is not present in the record. Ignoring the record."
80
+ else
81
+ ip_address = record[@key_name]
82
+ # Check that the ip_address is not 'nil'
83
+ unless ip_address.nil?
84
+ begin
85
+ # Fetch geolocation details using IPInfo API
86
+ ipinfo_details = @ipinfo_handler.details(ip_address)
87
+ # IPInfo ruby wrapper returns a dict based on symbols, we need to stringify the symbols
88
+ # to be able to use them easily
89
+ all_details = ipinfo_details.all
90
+ geodata = all_details.stringify_keys
91
+ # Get the final list of fields by running a join operation on the fields provided by the user and the ones
92
+ # returned by IPInfo API
93
+ ipinfo_returned_fields = geodata.keys
94
+ final_fields = ipinfo_returned_fields & @fields
95
+ if final_fields.length() != @fields.length()
96
+ ignored_fields = @fields - final_fields
97
+ ignored_fields.each{|field|
98
+ log.warn "Field '#{@field}' not present in IPInfo payload. Ignoring it."
99
+ }
100
+ end
101
+ # Extract a subhash from the geolocation data returned by IPInfo API using the final_fields list as keys.
102
+ record[@out_key] = extract_subhash(geodata, final_fields)
103
+ rescue Exception => e
104
+ log.error 'An error occured while fetching geographical location data.', error: e
105
+ log.warn_backtrace e.backtrace
106
+ end
70
107
  end
71
- # Extract a subhash from the geolocation data returned by IPInfo API using the final_fields list as keys.
72
- record[@out_key] = extract_subhash(geodata, final_fields)
73
108
  end
74
109
  record
75
110
  end
@@ -51,14 +51,105 @@ class IPinfoFilterTest < Test::Unit::TestCase
51
51
  d.filtered_records
52
52
  end
53
53
 
54
+ sub_test_case 'plugin will use default values' do
55
+ test 'access_token nil' do
56
+ config = %[
57
+ @type ipinfo
58
+ access_token
59
+ ]
60
+ d = create_driver(config)
61
+ assert_equal d.instance.access_token, nil
62
+ end
63
+
64
+ test 'access_token empty string' do
65
+ config = %[
66
+ @type ipinfo
67
+ access_token ""
68
+ ]
69
+ d = create_driver(config)
70
+ assert_equal d.instance.access_token, nil
71
+ end
72
+
73
+ test 'key_name nil' do
74
+ config = %[
75
+ @type ipinfo
76
+ key_name
77
+ ]
78
+ d = create_driver(config)
79
+ assert_equal d.instance.key_name, 'ip_address'
80
+ end
81
+
82
+ test 'key_name empty string' do
83
+ config = %[
84
+ @type ipinfo
85
+ key_name
86
+ ]
87
+ d = create_driver(config)
88
+ assert_equal d.instance.key_name, 'ip_address'
89
+ end
90
+
91
+ test 'out_key nil' do
92
+ config = %[
93
+ @type ipinfo
94
+ out_key
95
+ ]
96
+ d = create_driver(config)
97
+ assert_equal d.instance.out_key, 'ipinfo'
98
+ end
99
+
100
+ test 'out_key empty string' do
101
+ config = %[
102
+ @type ipinfo
103
+ out_key
104
+ ]
105
+ d = create_driver(config)
106
+ assert_equal d.instance.out_key, 'ipinfo'
107
+ end
108
+ end
109
+
110
+ sub_test_case 'plugin will raise Fluent::ConfigError' do
111
+ test 'empty fields' do
112
+ config = %[
113
+ @type ipinfo
114
+ fields []
115
+ ]
116
+ assert_raise Fluent::ConfigError do
117
+ create_driver(config)
118
+ end
119
+ end
120
+
121
+ test 'fields with one empty string' do
122
+ config = %[
123
+ @type ipinfo
124
+ fields [""]
125
+ ]
126
+ assert_raise Fluent::ConfigError do
127
+ create_driver(config)
128
+ end
129
+ end
130
+
131
+ test 'fields with multiple empty string' do
132
+ config = %[
133
+ @type ipinfo
134
+ fields [""]
135
+ ]
136
+ assert_raise Fluent::ConfigError do
137
+ create_driver(config)
138
+ end
139
+ end
140
+ end
141
+
54
142
  sub_test_case 'plugin will fetch geolocation data' do
55
143
  test 'add ipinfo to record with default fields' do
56
- conf = CONFIG
144
+ config = CONFIG
57
145
  messages = [
58
- { 'ip_address' => '8.8.8.8' }
146
+ {
147
+ 'ip_address' => '8.8.8.8'
148
+ }
59
149
  ]
60
150
  expected = [
61
- { 'ip_address' => '8.8.8.8',
151
+ {
152
+ 'ip_address' => '8.8.8.8',
62
153
  'ipinfo' => {
63
154
  'country_name' => 'United States',
64
155
  'region' => 'California',
@@ -68,20 +159,23 @@ class IPinfoFilterTest < Test::Unit::TestCase
68
159
  }
69
160
  }
70
161
  ]
71
- filtered_records = filter(conf, messages)
162
+ filtered_records = filter(config, messages)
72
163
  assert_equal(expected, filtered_records)
73
164
  end
74
165
 
75
166
  test 'add ipinfo to record with custom key_name' do
76
- conf = %[
167
+ config = %[
77
168
  @type ipinfo
78
169
  key_name ip
79
170
  ]
80
171
  messages = [
81
- { 'ip' => '8.8.8.8' }
172
+ {
173
+ 'ip' => '8.8.8.8'
174
+ }
82
175
  ]
83
176
  expected = [
84
- { 'ip' => '8.8.8.8',
177
+ {
178
+ 'ip' => '8.8.8.8',
85
179
  'ipinfo' => {
86
180
  'country_name' => 'United States',
87
181
  'region' => 'California',
@@ -91,20 +185,23 @@ class IPinfoFilterTest < Test::Unit::TestCase
91
185
  }
92
186
  }
93
187
  ]
94
- filtered_records = filter(conf, messages)
188
+ filtered_records = filter(config, messages)
95
189
  assert_equal(expected, filtered_records)
96
190
  end
97
191
 
98
192
  test 'add ipinfo to record with custom out_key' do
99
- conf = %[
193
+ config = %[
100
194
  @type ipinfo
101
195
  out_key geodata
102
196
  ]
103
197
  messages = [
104
- { 'ip_address' => '8.8.8.8' }
198
+ {
199
+ 'ip_address' => '8.8.8.8'
200
+ }
105
201
  ]
106
202
  expected = [
107
- { 'ip_address' => '8.8.8.8',
203
+ {
204
+ 'ip_address' => '8.8.8.8',
108
205
  'geodata' => {
109
206
  'country_name' => 'United States',
110
207
  'region' => 'California',
@@ -114,62 +211,98 @@ class IPinfoFilterTest < Test::Unit::TestCase
114
211
  }
115
212
  }
116
213
  ]
117
- filtered_records = filter(conf, messages)
214
+ filtered_records = filter(config, messages)
215
+ assert_equal(expected, filtered_records)
216
+ end
217
+
218
+ test 'add ipinfo to record with custom out_key that is already defined' do
219
+ config = %[
220
+ @type ipinfo
221
+ out_key geodata
222
+ ]
223
+ messages = [
224
+ {
225
+ 'ip_address' => '8.8.8.8',
226
+ 'geodata' => 'bye!'
227
+ }
228
+ ]
229
+ expected = [
230
+ {
231
+ 'ip_address' => '8.8.8.8',
232
+ 'geodata' => {
233
+ 'country_name' => 'United States',
234
+ 'region' => 'California',
235
+ 'city' => 'Mountain View',
236
+ 'latitude' => '37.4056',
237
+ 'longitude' => '-122.0775'
238
+ }
239
+ }
240
+ ]
241
+ filtered_records = filter(config, messages)
118
242
  assert_equal(expected, filtered_records)
119
243
  end
120
244
 
121
245
  test 'add ipinfo to record with custom fields' do
122
- conf = %[
246
+ config = %[
123
247
  @type ipinfo
124
248
  fields ["country_name", "city"]
125
249
  ]
126
250
  messages = [
127
- { 'ip_address' => '8.8.8.8' }
251
+ {
252
+ 'ip_address' => '8.8.8.8'
253
+ }
128
254
  ]
129
255
  expected = [
130
- { 'ip_address' => '8.8.8.8',
256
+ {
257
+ 'ip_address' => '8.8.8.8',
131
258
  'ipinfo' => {
132
259
  'country_name' => 'United States',
133
260
  'city' => 'Mountain View'
134
261
  }
135
262
  }
136
263
  ]
137
- filtered_records = filter(conf, messages)
264
+ filtered_records = filter(config, messages)
138
265
  assert_equal(expected, filtered_records)
139
266
  end
140
267
 
141
268
  test 'add ipinfo to record with custom key_name and custom fields' do
142
- conf = %[
269
+ config = %[
143
270
  @type ipinfo
144
271
  key_name ip
145
272
  fields ["country_name", "city"]
146
273
  ]
147
274
  messages = [
148
- { 'ip' => '8.8.8.8' }
275
+ {
276
+ 'ip' => '8.8.8.8'
277
+ }
149
278
  ]
150
279
  expected = [
151
- { 'ip' => '8.8.8.8',
280
+ {
281
+ 'ip' => '8.8.8.8',
152
282
  'ipinfo' => {
153
283
  'country_name' => 'United States',
154
284
  'city' => 'Mountain View'
155
285
  }
156
286
  }
157
287
  ]
158
- filtered_records = filter(conf, messages)
288
+ filtered_records = filter(config, messages)
159
289
  assert_equal(expected, filtered_records)
160
290
  end
161
291
 
162
292
  test 'add ipinfo to record with custom key_name and custom out_key' do
163
- conf = %[
293
+ config = %[
164
294
  @type ipinfo
165
295
  key_name ip
166
296
  out_key geodata
167
297
  ]
168
298
  messages = [
169
- { 'ip' => '8.8.8.8' }
299
+ {
300
+ 'ip' => '8.8.8.8'
301
+ }
170
302
  ]
171
303
  expected = [
172
- { 'ip' => '8.8.8.8',
304
+ {
305
+ 'ip' => '8.8.8.8',
173
306
  'geodata' => {
174
307
  'country_name' => 'United States',
175
308
  'region' => 'California',
@@ -179,29 +312,32 @@ class IPinfoFilterTest < Test::Unit::TestCase
179
312
  }
180
313
  }
181
314
  ]
182
- filtered_records = filter(conf, messages)
315
+ filtered_records = filter(config, messages)
183
316
  assert_equal(expected, filtered_records)
184
317
  end
185
318
 
186
319
  test 'add ipinfo to record with custom key_name, custom out_name and custom fields' do
187
- conf = %[
320
+ config = %[
188
321
  @type ipinfo
189
322
  key_name ip
190
323
  out_key geodata
191
324
  fields ["country_name", "city"]
192
325
  ]
193
326
  messages = [
194
- { 'ip' => '8.8.8.8' }
327
+ {
328
+ 'ip' => '8.8.8.8'
329
+ }
195
330
  ]
196
331
  expected = [
197
- { 'ip' => '8.8.8.8',
332
+ {
333
+ 'ip' => '8.8.8.8',
198
334
  'geodata' => {
199
335
  'country_name' => 'United States',
200
336
  'city' => 'Mountain View'
201
337
  }
202
338
  }
203
339
  ]
204
- filtered_records = filter(conf, messages)
340
+ filtered_records = filter(config, messages)
205
341
  assert_equal(expected, filtered_records)
206
342
  end
207
343
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-ipinfo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ahmed Abdelkafi