logstash-input-salesforce 3.2.0 → 3.3.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,123 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: https://login.salesforce.com/services/oauth2/token
6
+ body:
7
+ encoding: US-ASCII
8
+ string: grant_type=password&client_id=xxxx&client_secret=xxxx&username=xxxx&password=xxxx
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.9.1
12
+ Content-Type:
13
+ - application/x-www-form-urlencoded
14
+ Accept:
15
+ - '*/*'
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Date:
22
+ - Thu, 27 Aug 2015 23:57:42 GMT
23
+ Set-Cookie:
24
+ - BrowserId=xxxx;Path=/;Domain=.salesforce.com;Expires=Mon, 26-Oct-2015 23:57:42 GMT
25
+ Expires:
26
+ - Thu, 01 Jan 1970 00:00:00 GMT
27
+ Pragma:
28
+ - no-cache
29
+ Cache-Control:
30
+ - no-cache, no-store
31
+ Content-Type:
32
+ - application/json;charset=UTF-8
33
+ Transfer-Encoding:
34
+ - chunked
35
+ body:
36
+ encoding: US-ASCII
37
+ string: '{"id":"https://login.salesforce.com/id/xxxx/xxxx","issued_at":"1440719862904","token_type":"Bearer","instance_url":"https://eu2.salesforce.com","signature":"xxxx","access_token":"xxxx"}'
38
+ http_version:
39
+ recorded_at: Thu, 27 Aug 2015 23:57:43 GMT
40
+ - request:
41
+ method: get
42
+ uri: https://eu2.salesforce.com/services/data/v26.0/sobjects/Lead/describe
43
+ body:
44
+ encoding: US-ASCII
45
+ string: ''
46
+ headers:
47
+ User-Agent:
48
+ - Faraday v0.9.1
49
+ Authorization:
50
+ - OAuth xxxx
51
+ Accept-Encoding:
52
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
53
+ Accept:
54
+ - '*/*'
55
+ response:
56
+ status:
57
+ code: 200
58
+ message: OK
59
+ headers:
60
+ Date:
61
+ - Thu, 27 Aug 2015 23:57:44 GMT
62
+ Set-Cookie:
63
+ - BrowserId=xxxx;Path=/;Domain=.salesforce.com;Expires=Mon, 26-Oct-2015 23:57:44 GMT
64
+ Expires:
65
+ - Thu, 01 Jan 1970 00:00:00 GMT
66
+ Sforce-Limit-Info:
67
+ - api-usage=211068/451000
68
+ Org.eclipse.jetty.server.include.etag:
69
+ - 5fb54cb6
70
+ Last-Modified:
71
+ - Thu, 27 Aug 2015 22:36:55 GMT
72
+ Content-Type:
73
+ - application/json;charset=UTF-8
74
+ Etag:
75
+ - 5fb54cb-gzip"
76
+ Transfer-Encoding:
77
+ - chunked
78
+ body:
79
+ encoding: UTF-8
80
+ string: '{"activateable":false,"childRelationships":[],"createable":true,"custom":false,"customSetting":false,"deletable":true,"deprecatedAndHidden":false,"feedEnabled":true,"fields":[{"autoNumber":false,"byteLength":18,"calculated":false,"calculatedFormula":null,"cascadeDelete":false,"caseSensitive":false,"controllerName":null,"createable":false,"custom":false,"defaultValue":null,"defaultValueFormula":null,"defaultedOnCreate":true,"dependentPicklist":false,"deprecatedAndHidden":false,"digits":0,"displayLocationInDecimal":false,"externalId":false,"filterable":true,"groupable":true,"htmlFormatted":false,"idLookup":true,"inlineHelpText":null,"label":"Lead
81
+ ID","length":18,"name":"Id","nameField":false,"namePointing":false,"nillable":false,"permissionable":false,"picklistValues":[],"precision":0,"referenceTo":[],"relationshipName":null,"relationshipOrder":null,"restrictedDelete":false,"restrictedPicklist":false,"scale":0,"soapType":"tns:ID","sortable":true,"type":"id","unique":false,"updateable":false,"writeRequiresMasterRead":false},{"autoNumber":false,"byteLength":0,"calculated":false,"calculatedFormula":null,"cascadeDelete":false,"caseSensitive":false,"controllerName":null,"createable":false,"custom":false,"defaultValue":null,"defaultValueFormula":null,"defaultedOnCreate":true,"dependentPicklist":false,"deprecatedAndHidden":false,"digits":0,"displayLocationInDecimal":false,"externalId":false,"filterable":true,"groupable":true,"htmlFormatted":false,"idLookup":false,"inlineHelpText":null,"label":"Deleted","length":0,"name":"IsDeleted","nameField":false,"namePointing":false,"nillable":false,"permissionable":false,"picklistValues":[],"precision":0,"referenceTo":[],"relationshipName":null,"relationshipOrder":null,"restrictedDelete":false,"restrictedPicklist":false,"scale":0,"soapType":"xsd:boolean","sortable":true,"type":"boolean","unique":false,"updateable":false,"writeRequiresMasterRead":false},{"autoNumber":false,"byteLength":240,"calculated":false,"calculatedFormula":null,"cascadeDelete":false,"caseSensitive":false,"controllerName":null,"createable":true,"custom":false,"defaultValue":null,"defaultValueFormula":null,"defaultedOnCreate":false,"dependentPicklist":false,"deprecatedAndHidden":false,"digits":0,"displayLocationInDecimal":false,"externalId":false,"filterable":true,"groupable":true,"htmlFormatted":false,"idLookup":false,"inlineHelpText":null,"label":"Last
82
+ Name","length":80,"name":"LastName","nameField":false,"namePointing":false,"nillable":false,"permissionable":false,"picklistValues":[],"precision":0,"referenceTo":[],"relationshipName":null,"relationshipOrder":null,"restrictedDelete":false,"restrictedPicklist":false,"scale":0,"soapType":"xsd:string","sortable":true,"type":"string","unique":false,"updateable":true,"writeRequiresMasterRead":false},{"autoNumber":false,"byteLength":120,"calculated":false,"calculatedFormula":null,"cascadeDelete":false,"caseSensitive":false,"controllerName":null,"createable":true,"custom":false,"defaultValue":null,"defaultValueFormula":null,"defaultedOnCreate":false,"dependentPicklist":false,"deprecatedAndHidden":false,"digits":0,"displayLocationInDecimal":false,"externalId":false,"filterable":true,"groupable":true,"htmlFormatted":false,"idLookup":false,"inlineHelpText":null,"label":"First
83
+ Name","length":40,"name":"FirstName","nameField":false,"namePointing":false,"nillable":true,"permissionable":false,"picklistValues":[],"precision":0,"referenceTo":[],"relationshipName":null,"relationshipOrder":null,"restrictedDelete":false,"restrictedPicklist":false,"scale":0,"soapType":"xsd:string","sortable":true,"type":"string","unique":false,"updateable":true,"writeRequiresMasterRead":false},{"autoNumber":false,"byteLength":120,"calculated":false,"calculatedFormula":null,"cascadeDelete":false,"caseSensitive":false,"controllerName":null,"createable":true,"custom":false,"defaultValue":null,"defaultValueFormula":null,"defaultedOnCreate":false,"dependentPicklist":false,"deprecatedAndHidden":false,"digits":0,"displayLocationInDecimal":false,"externalId":false,"filterable":true,"groupable":true,"htmlFormatted":false,"idLookup":false,"inlineHelpText":null,"label":"Salutation","length":40,"name":"Salutation","nameField":false,"namePointing":false,"nillable":true,"permissionable":false,"picklistValues":[{"active":true,"defaultValue":false,"label":"Mr.","validFor":null,"value":"Mr."},{"active":true,"defaultValue":false,"label":"Ms.","validFor":null,"value":"Ms."},{"active":true,"defaultValue":false,"label":"Mrs.","validFor":null,"value":"Mrs."},{"active":true,"defaultValue":false,"label":"Dr.","validFor":null,"value":"Dr."},{"active":true,"defaultValue":false,"label":"Prof.","validFor":null,"value":"Prof."}],"precision":0,"referenceTo":[],"relationshipName":null,"relationshipOrder":null,"restrictedDelete":false,"restrictedPicklist":false,"scale":0,"soapType":"xsd:string","sortable":true,"type":"picklist","unique":false,"updateable":true,"writeRequiresMasterRead":false}],"keyPrefix":"00Q","label":"Lead","labelPlural":"Leads","layoutable":true,"listviewable":null,"lookupLayoutable":null,"mergeable":true,"name":"Lead","queryable":true,"recordTypeInfos":[{"available":true,"defaultRecordTypeMapping":true,"name":"Marketing","recordTypeId":"xxxx"},{"available":true,"defaultRecordTypeMapping":false,"name":"Partner
84
+ Deal","recordTypeId":"xxxx"},{"available":true,"defaultRecordTypeMapping":false,"name":"Sales","recordTypeId":"xxxx"},{"available":true,"defaultRecordTypeMapping":false,"name":"Master","recordTypeId":"xxxx"}],"replicateable":true,"retrieveable":true,"searchLayoutable":null,"searchable":true,"triggerable":true,"undeletable":true,"updateable":true,"urls":{"uiEditTemplate":"https://xxx.salesforce.com/{ID}/e","sobject":"/services/data/v26.0/sobjects/Lead","uiDetailTemplate":"https://xxx.salesforce.com/{ID}","describe":"/services/data/v26.0/sobjects/Lead/describe","rowTemplate":"/services/data/v26.0/sobjects/Lead/{ID}","uiNewRecord":"https://xxx.salesforce.com/00Q/e"}}'
85
+ http_version:
86
+ recorded_at: Thu, 27 Aug 2015 23:57:44 GMT
87
+ - request:
88
+ method: get
89
+ uri: https://eu2.salesforce.com/services/data/v26.0/query?q=SELECT%20Id,IsDeleted,LastName,FirstName,Salutation,LastModifiedDate%20FROM%20Lead%20WHERE%20LastModifiedDate%20%3E%202025-05-07T14:32:17Z%20ORDER%20BY%20LastModifiedDate%20ASC
90
+ body:
91
+ encoding: US-ASCII
92
+ string: ''
93
+ headers:
94
+ User-Agent:
95
+ - Faraday v0.9.1
96
+ Authorization:
97
+ - OAuth xxx
98
+ Accept-Encoding:
99
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
100
+ Accept:
101
+ - '*/*'
102
+ response:
103
+ status:
104
+ code: 200
105
+ message: OK
106
+ headers:
107
+ Date:
108
+ - Thu, 27 Aug 2015 23:57:45 GMT
109
+ Set-Cookie:
110
+ - BrowserId=xxxx;Path=/;Domain=.salesforce.com;Expires=Mon, 26-Oct-2015 23:57:45 GMT
111
+ Expires:
112
+ - Thu, 01 Jan 1970 00:00:00 GMT
113
+ Sforce-Limit-Info:
114
+ - api-usage=211063/451000
115
+ Content-Type:
116
+ - application/json;charset=UTF-8
117
+ Transfer-Encoding:
118
+ - chunked
119
+ body:
120
+ encoding: UTF-8
121
+ string: '{"totalSize":3,"done":true,"records":[{"attributes":{"type":"Lead","url":"/services/data/v26.0/sobjects/Lead/xxxx"},"Id":"xxxx","IsDeleted":false,"LastName":"Katz","FirstName":"Aaron","Salutation":"Mr."},{"attributes":{"type":"Lead","url":"/services/data/v26.0/sobjects/Lead/xxxx"},"Id":"xxxx","IsDeleted":false,"LastName":"Grand","FirstName":"Adrien","Salutation":"Dr."},{"attributes":{"type":"Lead","url":"/services/data/v26.0/sobjects/Lead/xxxx"},"Id":"xxxx","IsDeleted":false,"LastName":"Hardy","FirstName":"Alan","Salutation":"Overlord"}]}'
122
+ http_version:
123
+ recorded_at: Thu, 27 Aug 2015 23:57:45 GMT
@@ -8,10 +8,10 @@ RSpec.describe LogStash::Inputs::Salesforce do
8
8
  let(:options) do
9
9
  {
10
10
  "client_id" => "",
11
- "client_secret" => "",
11
+ "client_secret" => ::LogStash::Util::Password.new("secret-key"),
12
12
  "username" => "",
13
- "password" => "",
14
- "security_token" => "",
13
+ "password" => ::LogStash::Util::Password.new("secret-password"),
14
+ "security_token" => ::LogStash::Util::Password.new("secret-token"),
15
15
  "sfdc_object_name" => ""
16
16
  }
17
17
  end
@@ -35,10 +35,10 @@ RSpec.describe LogStash::Inputs::Salesforce do
35
35
  let(:options) do
36
36
  {
37
37
  "client_id" => "",
38
- "client_secret" => "",
38
+ "client_secret" => ::LogStash::Util::Password.new("secret-key"),
39
39
  "username" => "",
40
- "password" => "",
41
- "security_token" => "",
40
+ "password" => ::LogStash::Util::Password.new("secret-password"),
41
+ "security_token" => ::LogStash::Util::Password.new("secret-token"),
42
42
  "sfdc_object_name" => "Lead",
43
43
  "sfdc_fields" => ["Something"]
44
44
  }
@@ -67,10 +67,10 @@ RSpec.describe LogStash::Inputs::Salesforce do
67
67
  let(:options) do
68
68
  {
69
69
  "client_id" => "",
70
- "client_secret" => "",
70
+ "client_secret" => ::LogStash::Util::Password.new("secret-key"),
71
71
  "username" => "",
72
- "password" => "",
73
- "security_token" => "",
72
+ "password" => ::LogStash::Util::Password.new("secret-password"),
73
+ "security_token" => ::LogStash::Util::Password.new("secret-token"),
74
74
  "sfdc_object_name" => "Lead"
75
75
  }
76
76
  end
@@ -84,7 +84,7 @@ RSpec.describe LogStash::Inputs::Salesforce do
84
84
  ["Salutation", "picklist"]] }
85
85
  subject { input }
86
86
  it "loads the Lead object fields" do
87
- VCR.use_cassette("describe_lead_object",:decode_compressed_response => true) do
87
+ VCR.use_cassette("describe lead object",:decode_compressed_response => true) do
88
88
  subject.register
89
89
  expect(subject.instance_variable_get(:@sfdc_field_types)).to match_array(expected_types_result)
90
90
  expect(subject.instance_variable_get(:@sfdc_fields)).to match_array(expected_fields_result)
@@ -94,10 +94,10 @@ RSpec.describe LogStash::Inputs::Salesforce do
94
94
  let(:options) do
95
95
  {
96
96
  "client_id" => "",
97
- "client_secret" => "",
97
+ "client_secret" => ::LogStash::Util::Password.new("secret-key"),
98
98
  "username" => "",
99
- "password" => "",
100
- "security_token" => "",
99
+ "password" => ::LogStash::Util::Password.new("secret-password"),
100
+ "security_token" => ::LogStash::Util::Password.new("secret-token"),
101
101
  "sfdc_object_name" => "Lead",
102
102
  "sfdc_fields" => ["Id", "IsDeleted", "LastName", "FirstName", "Salutation"],
103
103
  "sfdc_filters" => "Email LIKE '%@elastic.co'"
@@ -107,7 +107,7 @@ RSpec.describe LogStash::Inputs::Salesforce do
107
107
  subject { input }
108
108
  let(:queue) { [] }
109
109
  it "loads some lead records" do
110
- VCR.use_cassette("load some lead objects",:decode_compressed_response => true) do
110
+ VCR.use_cassette("load some lead objects", :decode_compressed_response => true) do
111
111
  subject.register
112
112
  subject.run(queue)
113
113
  expect(queue.length).to eq(3)
@@ -137,10 +137,10 @@ RSpec.describe LogStash::Inputs::Salesforce do
137
137
  let(:options) do
138
138
  {
139
139
  "client_id" => "",
140
- "client_secret" => "",
140
+ "client_secret" => ::LogStash::Util::Password.new("secret-key"),
141
141
  "username" => "",
142
- "password" => "",
143
- "security_token" => "",
142
+ "password" => ::LogStash::Util::Password.new("secret-password"),
143
+ "security_token" => ::LogStash::Util::Password.new("secret-token"),
144
144
  "sfdc_instance_url" => "my-domain.my.salesforce.com",
145
145
  "sfdc_object_name" => "Lead"
146
146
  }
@@ -155,7 +155,7 @@ RSpec.describe LogStash::Inputs::Salesforce do
155
155
  ["Salutation", "picklist"]] }
156
156
  subject { input }
157
157
  it "logs into sfdc instance url" do
158
- VCR.use_cassette("login_into_mydomain", :decode_compressed_response => true) do
158
+ VCR.use_cassette("login into mydomain", :decode_compressed_response => true) do
159
159
  subject.register
160
160
  expect(subject.instance_variable_get(:@sfdc_field_types)).to match_array(expected_types_result)
161
161
  expect(subject.instance_variable_get(:@sfdc_fields)).to match_array(expected_fields_result)
@@ -165,10 +165,10 @@ RSpec.describe LogStash::Inputs::Salesforce do
165
165
  let(:options) do
166
166
  {
167
167
  "client_id" => "",
168
- "client_secret" => "",
168
+ "client_secret" => ::LogStash::Util::Password.new("secret-key"),
169
169
  "username" => "",
170
- "password" => "",
171
- "security_token" => "",
170
+ "password" => ::LogStash::Util::Password.new("secret-password"),
171
+ "security_token" => ::LogStash::Util::Password.new("secret-token"),
172
172
  "sfdc_instance_url" => "my-domain.my.salesforce.com",
173
173
  "sfdc_object_name" => "Lead",
174
174
  "use_test_sandbox" => true
@@ -200,10 +200,10 @@ RSpec.describe LogStash::Inputs::Salesforce do
200
200
  {
201
201
  "api_version" => "52.0",
202
202
  "client_id" => "",
203
- "client_secret" => "",
203
+ "client_secret" => ::LogStash::Util::Password.new("secret-key"),
204
204
  "username" => "",
205
- "password" => "",
206
- "security_token" => "",
205
+ "password" => ::LogStash::Util::Password.new("secret-password"),
206
+ "security_token" => ::LogStash::Util::Password.new("secret-token"),
207
207
  "use_tooling_api" => true,
208
208
  "sfdc_object_name" => "ApexTestRunResult"
209
209
  }
@@ -211,11 +211,271 @@ RSpec.describe LogStash::Inputs::Salesforce do
211
211
  let(:input) { LogStash::Inputs::Salesforce.new(options) }
212
212
  subject { input }
213
213
  it "should use the Tooling Api Query resource path" do
214
- VCR.use_cassette("describe_apex_test_run_result_object",:decode_compressed_response => true) do
214
+ VCR.use_cassette("describe apex test run result object", :decode_compressed_response => true) do
215
215
  subject.register
216
216
  expect(subject.send(:client).send(:api_path, "query")).to eq('/services/data/v52.0/tooling/query')
217
217
  end
218
218
  end
219
219
  end
220
+
221
+ context "run continuously at interval" do
222
+ VCR.configure do |config|
223
+ config.cassette_library_dir = File.join(File.dirname(__FILE__), '..', 'fixtures', 'vcr_cassettes')
224
+ config.hook_into :webmock
225
+ config.before_record do |i|
226
+ if i.response.body.encoding.to_s == 'ASCII-8BIT'
227
+ # required because sfdc doesn't send back the content encoding and it
228
+ # confuses the yaml parser
229
+ json_body = JSON.load(i.response.body.encode("ASCII-8BIT").force_encoding("utf-8"))
230
+ i.response.body = json_body.to_json
231
+ i.response.update_content_length_header
232
+ end
233
+ end
234
+ end
235
+ let(:options) do
236
+ {
237
+ "client_id" => "",
238
+ "client_secret" => ::LogStash::Util::Password.new("secret-key"),
239
+ "username" => "",
240
+ "password" => ::LogStash::Util::Password.new("secret-password"),
241
+ "security_token" => ::LogStash::Util::Password.new("secret-token"),
242
+ "use_tooling_api" => false,
243
+ "sfdc_object_name" => "Lead",
244
+ "sfdc_fields" => ["Id", "IsDeleted", "LastName", "FirstName", "Salutation"],
245
+ "sfdc_filters" => "Email LIKE '%@elastic.co'",
246
+ "interval" => 3
247
+ }
248
+ end
249
+ let(:input) { LogStash::Inputs::Salesforce.new(options) }
250
+ subject { input }
251
+ let(:queue) { [] }
252
+ it "loads some lead records" do
253
+ VCR.use_cassette("load some lead objects twice", :decode_compressed_response => true) do
254
+ subject.register
255
+ # Run a background thread to set the stop flag after 7 seconds, i.e. after the second run of the plugin
256
+ thr = Thread.new {
257
+ sleep(4) # more than 3, less than 6
258
+ subject.do_stop
259
+ }
260
+ subject.run(queue)
261
+ thr.join
262
+ expect(queue.length).to eq(8) # 3 + 5
263
+ end
264
+ end
265
+ end
266
+
267
+ context "run with last modified time from range field file" do
268
+ VCR.configure do |config|
269
+ config.cassette_library_dir = File.join(File.dirname(__FILE__), '..', 'fixtures', 'vcr_cassettes')
270
+ config.hook_into :webmock
271
+ config.before_record do |i|
272
+ if i.response.body.encoding.to_s == 'ASCII-8BIT'
273
+ # required because sfdc doesn't send back the content encoding and it
274
+ # confuses the yaml parser
275
+ json_body = JSON.load(i.response.body.encode("ASCII-8BIT").force_encoding("utf-8"))
276
+ i.response.body = json_body.to_json
277
+ i.response.update_content_length_header
278
+ end
279
+ end
280
+ end
281
+ let(:options) do
282
+ {
283
+ "client_id" => "",
284
+ "client_secret" => ::LogStash::Util::Password.new("secret-key"),
285
+ "username" => "",
286
+ "password" => ::LogStash::Util::Password.new("secret-password"),
287
+ "security_token" => ::LogStash::Util::Password.new("secret-token"),
288
+ "use_tooling_api" => false,
289
+ "sfdc_object_name" => "Lead",
290
+ "sfdc_fields" => ["Id", "IsDeleted", "LastName", "FirstName", "Salutation"],
291
+ "sfdc_filters" => "Email LIKE '%@elastic.co'",
292
+ "changed_data_filter" => "LastModifiedDate > %{last_tracking_field_value}",
293
+ "tracking_field_value_file" => "last_tracking_field_value.txt"
294
+ }
295
+ end
296
+ let(:input) { LogStash::Inputs::Salesforce.new(options) }
297
+ subject { input }
298
+ let(:queue) { [] }
299
+ it "loads some lead records modified after 2025-05-07 14:32:17 UTC" do
300
+ VCR.use_cassette("load some lead objects with lastmodifieddate filter", :decode_compressed_response => true) do
301
+ subject.register
302
+ File.write("last_tracking_field_value.txt", "2025-05-07T14:32:17Z")
303
+ subject.run(queue)
304
+ expect(queue.length).to eq(3)
305
+ end
306
+ end
307
+ end
308
+
309
+ context "run with last modified time from range field file when file doesn't yet exist" do
310
+ VCR.configure do |config|
311
+ config.cassette_library_dir = File.join(File.dirname(__FILE__), '..', 'fixtures', 'vcr_cassettes')
312
+ config.hook_into :webmock
313
+ config.before_record do |i|
314
+ if i.response.body.encoding.to_s == 'ASCII-8BIT'
315
+ # required because sfdc doesn't send back the content encoding and it
316
+ # confuses the yaml parser
317
+ json_body = JSON.load(i.response.body.encode("ASCII-8BIT").force_encoding("utf-8"))
318
+ i.response.body = json_body.to_json
319
+ i.response.update_content_length_header
320
+ end
321
+ end
322
+ end
323
+ let(:options) do
324
+ {
325
+ "client_id" => "",
326
+ "client_secret" => ::LogStash::Util::Password.new("secret-key"),
327
+ "username" => "",
328
+ "password" => ::LogStash::Util::Password.new("secret-password"),
329
+ "security_token" => ::LogStash::Util::Password.new("secret-token"),
330
+ "use_tooling_api" => false,
331
+ "sfdc_object_name" => "Lead",
332
+ "sfdc_fields" => ["Id", "IsDeleted", "LastName", "FirstName", "Salutation"],
333
+ "sfdc_filters" => "Email LIKE '%@elastic.co'",
334
+ "changed_data_filter" => "LastModifiedDate > %{last_tracking_field_value}",
335
+ "tracking_field_value_file" => "last_tracking_field_value.txt"
336
+ }
337
+ end
338
+ let(:input) { LogStash::Inputs::Salesforce.new(options) }
339
+ subject { input }
340
+ let(:queue) { [] }
341
+ it "loads some lead records" do
342
+ VCR.use_cassette("load some lead objects", :decode_compressed_response => true) do
343
+ subject.register
344
+ File.exist?("last_tracking_field_value.txt") && File.delete("last_tracking_field_value.txt")
345
+ subject.run(queue)
346
+ expect(queue.length).to eq(3)
347
+ end
348
+ end
349
+ end
350
+
351
+ context "run with last modified time from range field file with range field" do
352
+ VCR.configure do |config|
353
+ config.cassette_library_dir = File.join(File.dirname(__FILE__), '..', 'fixtures', 'vcr_cassettes')
354
+ config.hook_into :webmock
355
+ config.before_record do |i|
356
+ if i.response.body.encoding.to_s == 'ASCII-8BIT'
357
+ # required because sfdc doesn't send back the content encoding and it
358
+ # confuses the yaml parser
359
+ json_body = JSON.load(i.response.body.encode("ASCII-8BIT").force_encoding("utf-8"))
360
+ i.response.body = json_body.to_json
361
+ i.response.update_content_length_header
362
+ end
363
+ end
364
+ end
365
+ let(:options) do
366
+ {
367
+ "client_id" => "",
368
+ "client_secret" => ::LogStash::Util::Password.new("secret-key"),
369
+ "username" => "",
370
+ "password" => ::LogStash::Util::Password.new("secret-password"),
371
+ "security_token" => ::LogStash::Util::Password.new("secret-token"),
372
+ "use_tooling_api" => false,
373
+ "sfdc_object_name" => "Lead",
374
+ "sfdc_fields" => ["Id", "IsDeleted", "LastName", "FirstName", "Salutation"],
375
+ "sfdc_filters" => "Email LIKE '%@elastic.co'",
376
+ "tracking_field" => "LastModifiedDate",
377
+ "changed_data_filter" => "LastModifiedDate > %{last_tracking_field_value}",
378
+ "tracking_field_value_file" => "last_tracking_field_value.txt"
379
+ }
380
+ end
381
+ let(:input) { LogStash::Inputs::Salesforce.new(options) }
382
+ subject { input }
383
+ let(:queue) { [] }
384
+ it "loads some lead records modified after 2025-05-07 14:32:17 UTC" do
385
+ VCR.use_cassette("load some lead objects with lastmodifieddate filter order by lastmodifieddate", :decode_compressed_response => true) do
386
+ subject.register
387
+ File.write("last_tracking_field_value.txt", "2025-05-07T14:32:17Z")
388
+ subject.run(queue)
389
+ expect(queue.length).to eq(3)
390
+ end
391
+ end
392
+ end
393
+
394
+ context "run with last modified time from range field file with range field and no other filters" do
395
+ VCR.configure do |config|
396
+ config.cassette_library_dir = File.join(File.dirname(__FILE__), '..', 'fixtures', 'vcr_cassettes')
397
+ config.hook_into :webmock
398
+ config.before_record do |i|
399
+ if i.response.body.encoding.to_s == 'ASCII-8BIT'
400
+ # required because sfdc doesn't send back the content encoding and it
401
+ # confuses the yaml parser
402
+ json_body = JSON.load(i.response.body.encode("ASCII-8BIT").force_encoding("utf-8"))
403
+ i.response.body = json_body.to_json
404
+ i.response.update_content_length_header
405
+ end
406
+ end
407
+ end
408
+ let(:options) do
409
+ {
410
+ "client_id" => "",
411
+ "client_secret" => ::LogStash::Util::Password.new("secret-key"),
412
+ "username" => "",
413
+ "password" => ::LogStash::Util::Password.new("secret-password"),
414
+ "security_token" => ::LogStash::Util::Password.new("secret-token"),
415
+ "use_tooling_api" => false,
416
+ "sfdc_object_name" => "Lead",
417
+ "sfdc_fields" => ["Id", "IsDeleted", "LastName", "FirstName", "Salutation"],
418
+ "tracking_field" => "LastModifiedDate",
419
+ "changed_data_filter" => "LastModifiedDate > %{last_tracking_field_value}",
420
+ "tracking_field_value_file" => "last_tracking_field_value.txt"
421
+ }
422
+ end
423
+ let(:input) { LogStash::Inputs::Salesforce.new(options) }
424
+ subject { input }
425
+ let(:queue) { [] }
426
+ it "loads some lead records modified after 2025-05-07 14:32:17 UTC" do
427
+ VCR.use_cassette("load some lead objects with lastmodifieddate filter order by lastmodifieddate no filters", :decode_compressed_response => true) do
428
+ subject.register
429
+ File.write("last_tracking_field_value.txt", "2025-05-07T14:32:17Z")
430
+ subject.run(queue)
431
+ expect(queue.length).to eq(3)
432
+ end
433
+ end
434
+ end
435
+
436
+ context "run with last modified time from range field file when file doesn't yet exist with range field" do
437
+ VCR.configure do |config|
438
+ config.cassette_library_dir = File.join(File.dirname(__FILE__), '..', 'fixtures', 'vcr_cassettes')
439
+ config.hook_into :webmock
440
+ config.before_record do |i|
441
+ if i.response.body.encoding.to_s == 'ASCII-8BIT'
442
+ # required because sfdc doesn't send back the content encoding and it
443
+ # confuses the yaml parser
444
+ json_body = JSON.load(i.response.body.encode("ASCII-8BIT").force_encoding("utf-8"))
445
+ i.response.body = json_body.to_json
446
+ i.response.update_content_length_header
447
+ end
448
+ end
449
+ end
450
+ let(:options) do
451
+ {
452
+ "client_id" => "",
453
+ "client_secret" => ::LogStash::Util::Password.new("secret-key"),
454
+ "username" => "",
455
+ "password" => ::LogStash::Util::Password.new("secret-password"),
456
+ "security_token" => ::LogStash::Util::Password.new("secret-token"),
457
+ "use_tooling_api" => false,
458
+ "sfdc_object_name" => "Lead",
459
+ "sfdc_fields" => ["Id", "IsDeleted", "LastName", "FirstName", "Salutation"],
460
+ "sfdc_filters" => "Email LIKE '%@elastic.co'",
461
+ "tracking_field" => "LastModifiedDate",
462
+ "changed_data_filter" => "LastModifiedDate > %{last_tracking_field_value}",
463
+ "tracking_field_value_file" => "last_tracking_field_value.txt"
464
+ }
465
+ end
466
+ let(:input) { LogStash::Inputs::Salesforce.new(options) }
467
+ subject { input }
468
+ let(:queue) { [] }
469
+ it "loads some lead records" do
470
+ VCR.use_cassette("load some lead objects order by lastmodifieddate", :decode_compressed_response => true) do
471
+ subject.register
472
+ File.exist?("last_tracking_field_value.txt") && File.delete("last_tracking_field_value.txt")
473
+ subject.run(queue)
474
+ expect(queue.length).to eq(3)
475
+ tracking_field_value = File.read("last_tracking_field_value.txt")
476
+ expect(tracking_field_value).to eq("2025-05-07T14:32:17Z")
477
+ end
478
+ end
479
+ end
220
480
  end
221
481
  end