embulk-input-marketo 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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},