embulk-input-marketo 0.4.0 → 0.5.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +16 -62
  3. data/.travis.yml.erb +9 -14
  4. data/CHANGELOG.md +8 -0
  5. data/README.md +2 -4
  6. data/embulk-input-marketo.gemspec +2 -1
  7. data/gemfiles/embulk-latest +1 -1
  8. data/lib/embulk/input/marketo/activity_log.rb +13 -12
  9. data/lib/embulk/input/marketo/lead.rb +19 -17
  10. data/lib/embulk/input/marketo_api/soap/activity_log.rb +25 -23
  11. data/lib/embulk/input/marketo_api/soap/base.rb +14 -19
  12. data/lib/embulk/input/marketo_api/soap/lead.rb +22 -17
  13. data/test/activity_log_fixtures.rb +181 -150
  14. data/test/embulk/input/marketo/test_activity_log.rb +13 -15
  15. data/test/embulk/input/marketo/test_lead.rb +19 -22
  16. data/test/embulk/input/marketo_api/soap/test_activity_log.rb +33 -8
  17. data/test/embulk/input/marketo_api/soap/test_base.rb +2 -14
  18. data/test/embulk/input/marketo_api/soap/test_lead.rb +2 -2
  19. data/test/lead_fixtures.rb +11 -19
  20. data/test/savon_helper.rb +17 -0
  21. metadata +18 -25
  22. data/gemfiles/embulk-0.6.0-latest +0 -4
  23. data/gemfiles/embulk-0.6.13 +0 -4
  24. data/gemfiles/embulk-0.6.14 +0 -4
  25. data/gemfiles/embulk-0.6.15 +0 -4
  26. data/gemfiles/embulk-0.6.16 +0 -4
  27. data/gemfiles/embulk-0.6.17 +0 -4
  28. data/gemfiles/embulk-0.6.18 +0 -4
  29. data/gemfiles/embulk-0.6.19 +0 -4
  30. data/gemfiles/embulk-0.6.20 +0 -4
  31. data/gemfiles/embulk-0.6.21 +0 -4
  32. data/gemfiles/embulk-0.6.22 +0 -4
  33. data/gemfiles/embulk-0.6.23 +0 -4
  34. data/gemfiles/embulk-0.6.24 +0 -4
  35. data/gemfiles/embulk-0.6.25 +0 -4
  36. data/gemfiles/embulk-0.6.26 +0 -4
  37. data/gemfiles/embulk-0.6.27 +0 -4
  38. data/gemfiles/embulk-0.7.0 +0 -4
  39. data/gemfiles/embulk-0.7.0-latest +0 -4
  40. data/gemfiles/embulk-0.7.1 +0 -4
  41. data/gemfiles/embulk-0.7.2 +0 -4
  42. data/gemfiles/embulk-0.7.3 +0 -4
  43. data/gemfiles/embulk-0.7.4 +0 -4
  44. data/gemfiles/embulk-0.7.5 +0 -4
@@ -53,24 +53,9 @@ module Embulk
53
53
  remaining = response.xpath('//remainingCount').text.to_i
54
54
  Embulk.logger.info "Fetched records in the range: #{records.size}"
55
55
  Embulk.logger.info "Remaining records in the range: #{remaining}"
56
- records.each do |lead|
57
- record = {
58
- "id" => {type: :integer, value: lead.xpath('Id').text.to_i},
59
- "email" => {type: :string, value: lead.xpath('Email').text}
60
- }
61
- lead.xpath('leadAttributeList/attribute').each do |attr|
62
- name = attr.xpath('attrName').text
63
- type = attr.xpath('attrType').text
64
- value = attr.xpath('attrValue').text
65
- record = record.merge(
66
- name => {
67
- type: type,
68
- value: value
69
- }
70
- )
71
- end
72
56
 
73
- block.call(record)
57
+ records.each do |lead|
58
+ process_record(lead, &block)
74
59
  end
75
60
 
76
61
  if remaining > 0
@@ -79,6 +64,26 @@ module Embulk
79
64
  nil
80
65
  end
81
66
  end
67
+
68
+ def process_record(lead, &block)
69
+ record = {
70
+ "id" => {type: :integer, value: lead.xpath('Id').text.to_i},
71
+ "email" => {type: :string, value: lead.xpath('Email').text}
72
+ }
73
+ lead.xpath('leadAttributeList/attribute').each do |attr|
74
+ name = attr.xpath('attrName').text
75
+ type = attr.xpath('attrType').text
76
+ value = attr.xpath('attrValue').text
77
+ record = record.merge(
78
+ name => {
79
+ type: type,
80
+ value: value
81
+ }
82
+ )
83
+ end
84
+
85
+ block.call(record)
86
+ end
82
87
  end
83
88
  end
84
89
  end
@@ -1,171 +1,202 @@
1
+ require "savon_helper"
2
+
1
3
  module ActivityLogFixtures
2
- private
4
+ include SavonHelper
3
5
 
4
- def activity_logs_response
5
- activity_logs(response)
6
- end
6
+ private
7
7
 
8
- def next_stream_activity_logs_response
9
- activity_logs(next_stream_response)
8
+ def activity_log_xml(body)
9
+ <<XML
10
+ <?xml version="1.0" encoding="UTF-8"?>
11
+ <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="http://www.marketo.com/mktows/">
12
+ <SOAP-ENV:Body>
13
+ <ns1:successGetLeadChanges>
14
+ <result>
15
+ #{body}
16
+ </result>
17
+ </ns1:successGetLeadChanges>
18
+ </SOAP-ENV:Body>
19
+ </SOAP-ENV:Envelope>
20
+ XML
10
21
  end
11
22
 
12
- def preview_activity_logs_response
13
- activity_logs(preview_response)
23
+ def xml_ac_response_no_attributes
24
+ activity_log_xml <<XML
25
+ <returnCount>2</returnCount>
26
+ <remainingCount>0</remainingCount>
27
+ <newStartPosition>
28
+ <latestCreatedAt>2015-07-14T09:13:10+09:00</latestCreatedAt>
29
+ <oldestCreatedAt>2015-07-14T09:13:13+09:00</oldestCreatedAt>
30
+ <activityCreatedAt xsi:nil="true"/>
31
+ <offset>offset</offset>
32
+ </newStartPosition>
33
+ <leadChangeRecordList>
34
+ <leadChangeRecord>
35
+ <id>1</id>
36
+ <activityDateTime>2015-07-14T09:00:09+09:00</activityDateTime>
37
+ <activityType>at1</activityType>
38
+ <mktgAssetName>score1</mktgAssetName>
39
+ <activityAttributes>
40
+ <attribute>
41
+ <attrName>Attribute Name</attrName>
42
+ <attrType xsi:nil="true"/>
43
+ <attrValue>Attribute1</attrValue>
44
+ </attribute>
45
+ <attribute>
46
+ <attrName>Old Value</attrName>
47
+ <attrType xsi:nil="true"/>
48
+ <attrValue>402</attrValue>
49
+ </attribute>
50
+ </activityAttributes>
51
+ <mktPersonId>100</mktPersonId>
52
+ </leadChangeRecord>
53
+ <leadChangeRecord>
54
+ <id>2</id>
55
+ <activityDateTime>2015-07-14T09:00:10+09:00</activityDateTime>
56
+ <activityType>at2</activityType>
57
+ <mktgAssetName>score2</mktgAssetName>
58
+ <mktPersonId>90</mktPersonId>
59
+ </leadChangeRecord>
60
+ </leadChangeRecordList>
61
+ XML
14
62
  end
15
63
 
16
- def none_activity_log_response
17
- activity_logs(none_response)
18
- end
19
64
 
20
- def activity_logs(body)
21
- Struct.new(:body).new({
22
- success_get_lead_changes: {
23
- result: body
24
- }
25
- })
65
+ def xml_ac_response
66
+ activity_log_xml <<XML
67
+ <returnCount>2</returnCount>
68
+ <remainingCount>1</remainingCount>
69
+ <newStartPosition>
70
+ <latestCreatedAt>2015-07-14T09:13:10+09:00</latestCreatedAt>
71
+ <oldestCreatedAt>2015-07-14T09:13:13+09:00</oldestCreatedAt>
72
+ <activityCreatedAt xsi:nil="true"/>
73
+ <offset>offset</offset>
74
+ </newStartPosition>
75
+ <leadChangeRecordList>
76
+ <leadChangeRecord>
77
+ <id>1</id>
78
+ <activityDateTime>2015-07-14T09:00:09+09:00</activityDateTime>
79
+ <activityType>at1</activityType>
80
+ <mktgAssetName>score1</mktgAssetName>
81
+ <activityAttributes>
82
+ <attribute>
83
+ <attrName>Attribute Name</attrName>
84
+ <attrType xsi:nil="true"/>
85
+ <attrValue>Attribute1</attrValue>
86
+ </attribute>
87
+ <attribute>
88
+ <attrName>Old Value</attrName>
89
+ <attrType xsi:nil="true"/>
90
+ <attrValue>402</attrValue>
91
+ </attribute>
92
+ </activityAttributes>
93
+ <mktPersonId>100</mktPersonId>
94
+ </leadChangeRecord>
95
+ <leadChangeRecord>
96
+ <id>2</id>
97
+ <activityDateTime>2015-07-14T09:00:10+09:00</activityDateTime>
98
+ <activityType>at2</activityType>
99
+ <mktgAssetName>score2</mktgAssetName>
100
+ <activityAttributes>
101
+ <attribute>
102
+ <attrName>Attribute Name</attrName>
103
+ <attrType xsi:nil="true"/>
104
+ <attrValue>Attribute2</attrValue>
105
+ </attribute>
106
+ <attribute>
107
+ <attrName>Old Value</attrName>
108
+ <attrType xsi:nil="true"/>
109
+ <attrValue>403</attrValue>
110
+ </attribute>
111
+ </activityAttributes>
112
+ <mktPersonId>90</mktPersonId>
113
+ </leadChangeRecord>
114
+ </leadChangeRecordList>
115
+ XML
26
116
  end
27
117
 
28
- def response
29
- {
30
- return_count: "2",
31
- remaining_count: "1",
32
- new_start_position: {
33
- latest_created_at: true,
34
- oldest_created_at: "2015-07-14T00:13:13+0000",
35
- activity_created_at: true,
36
- offset: offset,
37
- },
38
- lead_change_record_list: {
39
- lead_change_record: [
40
- {
41
- id: "1",
42
- activity_date_time: "2015-07-14T00:00:09+0000",
43
- activity_type: "at1",
44
- mktg_asset_name: "score1",
45
- activity_attributes: {
46
- attribute: [
47
- {
48
- attr_name: "Attribute Name",
49
- attr_type: nil,
50
- attr_value: "Attribute1",
51
- },
52
- {
53
- attr_name: "Old Value",
54
- attr_type: nil,
55
- attr_value: "402",
56
- },
57
- ],
58
- },
59
- mkt_person_id: "100",
60
- },
61
- {
62
- id: "2",
63
- activity_date_time: "2015-07-14T00:00:10+0000",
64
- activity_type: "at2",
65
- mktg_asset_name: "score2",
66
- activity_attributes: {
67
- attribute: [
68
- {
69
- attr_name: "Attribute Name",
70
- attr_type: nil,
71
- attr_value: "Attribute2",
72
- },
73
- {
74
- attr_name: "Old Value",
75
- attr_type: nil,
76
- attr_value: "403",
77
- },
78
- ],
79
- },
80
- mkt_person_id: "90",
81
- },
82
- ]
83
- }
84
- }
118
+ def xml_ac_next_response
119
+ activity_log_xml <<XML
120
+ <returnCount>1</returnCount>
121
+ <remainingCount>0</remainingCount>
122
+ <newStartPosition>
123
+ </newStartPosition>
124
+ <leadChangeRecordList>
125
+ <leadChangeRecord>
126
+ <id>3</id>
127
+ <activityDateTime>2015-07-14T09:00:11+09:00</activityDateTime>
128
+ <activityType>at3</activityType>
129
+ <mktgAssetName>score3</mktgAssetName>
130
+ <activityAttributes>
131
+ <attribute>
132
+ <attrName>Attribute Name</attrName>
133
+ <attrType xsi:nil="true"/>
134
+ <attrValue>Attribute3</attrValue>
135
+ </attribute>
136
+ <attribute>
137
+ <attrName>Old Value</attrName>
138
+ <attrType xsi:nil="true"/>
139
+ <attrValue>404</attrValue>
140
+ </attribute>
141
+ </activityAttributes>
142
+ <mktPersonId>100</mktPersonId>
143
+ </leadChangeRecord>
144
+ </leadChangeRecordList>
145
+ XML
85
146
  end
86
147
 
87
- def offset
88
- "offset"
148
+ def xml_ac_none_response
149
+ activity_log_xml <<XML
150
+ <returnCount>0</returnCount>
151
+ <remainingCount>0</remainingCount>
152
+ <newStartPosition>
153
+ </newStartPosition>
154
+ <leadChangeRecordList>
155
+ </leadChangeRecordList>
156
+ XML
89
157
  end
90
158
 
91
- def next_stream_response
92
- {
93
- return_count: 1,
94
- remaining_count: 0,
95
- new_start_position: {
96
- },
97
- lead_change_record_list: {
98
- lead_change_record: [
99
- {
100
- id: "3",
101
- activity_date_time: "2015-07-14T00:00:11+0000",
102
- activity_type: "at3",
103
- mktg_asset_name: "score3",
104
- activity_attributes: {
105
- attribute: [
106
- {
107
- attr_name: "Attribute Name",
108
- attr_type: nil,
109
- attr_value: "Attribute3",
110
- },
111
- {
112
- attr_name: "Old Value",
113
- attr_type: nil,
114
- attr_value: "404",
115
- },
116
- ],
117
- },
118
- mkt_person_id: "100",
119
- },
120
- ]
121
- }
122
- }
159
+ def xml_ac_preview_response
160
+ activity_log_xml <<XML
161
+ <returnCount>15</returnCount>
162
+ <remainingCount>0</remainingCount>
163
+ <newStartPosition>
164
+ </newStartPosition>
165
+ <leadChangeRecordList>
166
+ #{xml_ac_attr(15)}
167
+ </leadChangeRecordList>
168
+ XML
123
169
  end
124
170
 
125
- def preview_response
126
- records = (1..15).map do |i|
127
- {
128
- id: i,
129
- activity_date_time: "2015-07-14T00:00:11+0000",
130
- activity_type: "at#{i}",
131
- mktg_asset_name: "score#{i}",
132
- activity_attributes: {
133
- attribute: [
134
- {
135
- attr_name: "Attribute Name",
136
- attr_type: nil,
137
- attr_value: "Attribute#{i}",
138
- },
139
- {
140
- attr_name: "Old Value",
141
- attr_type: nil,
142
- attr_value: "404",
143
- },
144
- ],
145
- },
146
- mkt_person_id: "100",
147
- }
171
+ def xml_ac_attr(times = 15)
172
+ response = ""
173
+ (1..times).each do |n|
174
+ response << <<-XML
175
+ <leadChangeRecord>
176
+ <id>#{n}</id>
177
+ <activityDateTime>2015-07-14T00:00:11+00:00</activityDateTime>
178
+ <activityType>at#{n}</activityType>
179
+ <mktgAssetName>score#{n}</mktgAssetName>
180
+ <activityAttributes>
181
+ <attribute>
182
+ <attrName>Attribute Name</attrName>
183
+ <attrType xsi:nil="true"/>
184
+ <attrValue>Attribute#{n}</attrValue>
185
+ </attribute>
186
+ <attribute>
187
+ <attrName>Old Value</attrName>
188
+ <attrType xsi:nil="true"/>
189
+ <attrValue>404</attrValue>
190
+ </attribute>
191
+ </activityAttributes>
192
+ <mktPersonId>100</mktPersonId>
193
+ </leadChangeRecord>
194
+ XML
148
195
  end
149
-
150
- {
151
- return_count: 15,
152
- remaining_count: 0,
153
- new_start_position: {},
154
- lead_change_record_list: {
155
- lead_change_record: records
156
- }
157
- }
196
+ response
158
197
  end
159
198
 
160
- def none_response
161
- {
162
- result: {
163
- return_count: 0,
164
- remaining_count: 0,
165
- new_start_position: {
166
- },
167
- lead_change_record_list: nil
168
- }
169
- }
199
+ def offset
200
+ "offset"
170
201
  end
171
202
  end
@@ -130,7 +130,7 @@ module Embulk
130
130
  def expected_guessed_columns
131
131
  [
132
132
  {name: :id, type: :long},
133
- {name: :activity_date_time, type: :timestamp, format: "%Y-%m-%dT%H:%M:%S%z"},
133
+ {name: :activity_date_time, type: :timestamp, format: "%Y-%m-%dT%H:%M:%S%:z"},
134
134
  {name: :activity_type, type: :string},
135
135
  {name: :mktg_asset_name, type: :string},
136
136
  {name: :mkt_person_id, type: :long},
@@ -157,17 +157,11 @@ module Embulk
157
157
 
158
158
  def test_retry
159
159
  any_instance_of(Savon::Client) do |klass|
160
- stub(klass).call(:get_multiple_leads, anything) do
160
+ stub(klass).call(:get_lead_changes, anything) do
161
161
  raise "foo"
162
162
  end
163
163
  end
164
164
 
165
- any_instance_of(::Embulk::Input::MarketoApi::Soap::Base) do |klass|
166
- task[:retry_limit].times do |n|
167
- mock(klass).sleep(task[:retry_initial_wait_sec] * (2**n))
168
- end
169
- end
170
-
171
165
  mock(Embulk.logger).warn(/Retrying/).times(task[:retry_limit])
172
166
  stub(Embulk.logger).info {}
173
167
 
@@ -200,11 +194,11 @@ module Embulk
200
194
 
201
195
  any_instance_of(Savon::Client) do |klass|
202
196
  mock(klass).call(:get_lead_changes, message: request) do
203
- activity_logs_response
197
+ savon_response(xml_ac_response)
204
198
  end
205
199
 
206
200
  mock(klass).call(:get_lead_changes, message: offset_request) do
207
- next_stream_activity_logs_response
201
+ savon_response(xml_ac_next_response)
208
202
  end
209
203
  end
210
204
 
@@ -213,6 +207,7 @@ module Embulk
213
207
  mock(@page_builder).add(["3", Time.parse("2015-07-14T00:00:11+0000"), "at3", "score3", "100", "Attribute3", "404"])
214
208
  mock(@page_builder).finish
215
209
 
210
+ @plugin.init
216
211
  @plugin.run
217
212
  end
218
213
 
@@ -221,12 +216,13 @@ module Embulk
221
216
 
222
217
  any_instance_of(Savon::Client) do |klass|
223
218
  mock(klass).call(:get_lead_changes, message: request) do
224
- none_activity_log_response
219
+ savon_response xml_ac_none_response
225
220
  end
226
221
  end
227
222
 
228
223
  mock(@page_builder).finish
229
224
 
225
+ @plugin.init
230
226
  @plugin.run
231
227
  end
232
228
 
@@ -235,22 +231,23 @@ module Embulk
235
231
 
236
232
  any_instance_of(Savon::Client) do |klass|
237
233
  mock(klass).call(:get_lead_changes, message: preview_request) do
238
- preview_activity_logs_response
234
+ savon_response xml_ac_preview_response
239
235
  end
240
236
  end
241
237
 
242
238
  1.upto(ActivityLog::PREVIEW_COUNT) do |count|
243
- mock(@page_builder).add([count, Time.parse("2015-07-14T00:00:11+0000"), "at#{count}", "score#{count}", "100", "Attribute#{count}", "404"])
239
+ mock(@page_builder).add([count.to_s, Time.parse("2015-07-14T00:00:11+0000"), "at#{count}", "score#{count}", "100", "Attribute#{count}", "404"])
244
240
  end
245
241
  mock(@page_builder).finish
246
242
 
243
+ @plugin.init
247
244
  @plugin.run
248
245
  end
249
246
 
250
247
  def test_wrong_type
251
248
  any_instance_of(Savon::Client) do |klass|
252
249
  stub(klass).call(:get_lead_changes, message: request) do
253
- next_stream_activity_logs_response
250
+ savon_response xml_ac_next_response
254
251
  end
255
252
  end
256
253
  stub(@page_builder).add {}
@@ -263,6 +260,7 @@ module Embulk
263
260
  @plugin = ActivityLog.new(task, nil, nil, @page_builder)
264
261
 
265
262
  assert_raise(Embulk::ConfigError) do
263
+ @plugin.init
266
264
  @plugin.run
267
265
  end
268
266
  end
@@ -325,7 +323,7 @@ module Embulk
325
323
  encryption_key: "TOPSECRET",
326
324
  from_datetime: from_datetime,
327
325
  to_datetime: to_datetime,
328
- retry_initial_wait_sec: 3,
326
+ retry_initial_wait_sec: 0,
329
327
  retry_limit: 2,
330
328
  columns: [
331
329
  {"name" => :id, "type" => :long},