embulk-input-google_analytics 0.1.17 → 0.1.18.alpha

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
  SHA1:
3
- metadata.gz: 8c0c86f1ec128421575f09495f1650bc36b9003e
4
- data.tar.gz: 356d14ca378502fa5a3c7d8781162f318ac62797
3
+ metadata.gz: 840c722b01ba3cf337f7b5e405e8b6b07676810b
4
+ data.tar.gz: 9416098303f34773cf3df1329a8eaf84fe4594b2
5
5
  SHA512:
6
- metadata.gz: 2030bd41d01b4d67e5a694512af6d5cfd4e153570f705e9584fc9d31cb5d7bb439d82726143e6929ffcdc3fb15a1acd2d302d9411a9f3434bf347019b05fc8c7
7
- data.tar.gz: d98bf69f0cefa62bb1058104300bba29a1ff527277d562921529f9ce7108bffc4b25fc1a1b8a6920d5f7edbd0f1c1571793c970f862105c91e14c391a0123a01
6
+ metadata.gz: 736e069eb795ba331c2125df44cb5cc48525f8bb4a44f43e62bb1b0b27c2b1affbd9e8e76fd76dfeeaeb8eaa64b5b9e91cde98254d4a3c90600fb30c7534ac64
7
+ data.tar.gz: 61a3515ba0cd0c28832d39d215b5619e3e62799164155c28ace126f773c8c4c08398e040b5424d38fb775fd08414d0af20833e8c6d5d4ab038ee5cf1373d459e
@@ -1,7 +1,7 @@
1
1
 
2
2
  Gem::Specification.new do |spec|
3
3
  spec.name = "embulk-input-google_analytics"
4
- spec.version = "0.1.17"
4
+ spec.version = "0.1.18.alpha"
5
5
  spec.authors = ["uu59"]
6
6
  spec.summary = "Google Analytics input plugin for Embulk"
7
7
  spec.description = "Loads records from Google Analytics."
@@ -27,5 +27,6 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency 'simplecov'
28
28
  spec.add_development_dependency "codeclimate-test-reporter"
29
29
  spec.add_development_dependency "pry"
30
+ spec.add_development_dependency "pry-debugger-jruby"
30
31
  spec.add_development_dependency "gem_release_helper", "~> 1.0"
31
32
  end
@@ -208,10 +208,22 @@ module Embulk
208
208
 
209
209
  def auth
210
210
  retryer.with_retry do
211
- Google::Auth::ServiceAccountCredentials.make_creds(
212
- json_key_io: StringIO.new(task["json_key_content"]),
213
- scope: "https://www.googleapis.com/auth/analytics.readonly"
214
- )
211
+ case task['auth_method']
212
+ when Plugin::AUTH_TYPE_JSON_KEY
213
+ Google::Auth::ServiceAccountCredentials.make_creds(
214
+ json_key_io: StringIO.new(task["json_key_content"]),
215
+ scope: "https://www.googleapis.com/auth/analytics.readonly"
216
+ )
217
+ when Plugin::AUTH_TYPE_REFRESH_TOKEN
218
+ Google::Auth::UserRefreshCredentials.new(
219
+ 'token_credential_uri': Google::Auth::UserRefreshCredentials::TOKEN_CRED_URI,
220
+ 'client_id': task['client_id'],
221
+ 'client_secret': task['client_secret'],
222
+ 'refresh_token': task['refresh_token']
223
+ )
224
+ else
225
+ raise Embulk::ConfigError.new("Unknown Authentication method: '#{task['auth_method']}'.")
226
+ end
215
227
  end
216
228
  rescue Google::Apis::AuthorizationError => e
217
229
  raise ConfigError.new(e.message)
@@ -3,6 +3,8 @@ module Embulk
3
3
  module GoogleAnalytics
4
4
  class Plugin < InputPlugin
5
5
  ::Embulk::Plugin.register_input("google_analytics", self)
6
+ AUTH_TYPE_JSON_KEY = 'json_key'.freeze
7
+ AUTH_TYPE_REFRESH_TOKEN = 'refresh_token'.freeze
6
8
 
7
9
  # https://developers.google.com/analytics/devguides/reporting/core/dimsmets
8
10
 
@@ -11,6 +13,15 @@ module Embulk
11
13
  unless %w(ga:date ga:dateHour).include?(task["time_series"])
12
14
  raise ConfigError.new("Unknown time_series '#{task["time_series"]}'. Use 'ga:dateHour' or 'ga:date'")
13
15
  end
16
+
17
+ raise ConfigError.new("Unknown Authentication method '#{task['auth_method']}'.") unless task['auth_method']
18
+
19
+ if task['auth_method'] == Plugin::AUTH_TYPE_REFRESH_TOKEN
20
+ unless task['client_id'] && task['client_secret'] && task['refresh_token']
21
+ raise ConfigError.new("client_id, client_secret and refresh_token are required when using Oauth authentication")
22
+ end
23
+ end
24
+
14
25
  columns_list = Client.new(task).get_columns_list
15
26
 
16
27
  columns = columns_from_task(task).map do |col_name|
@@ -53,8 +64,16 @@ module Embulk
53
64
  end
54
65
 
55
66
  def self.task_from_config(config)
56
- json_key_content = config.param("json_key_content", :string)
57
- {
67
+ refresh_token = config.param('refresh_token', :string, default: nil)
68
+ json_key_content = config.param("json_key_content", :string, default: nil)
69
+
70
+ auth_method = Plugin::AUTH_TYPE_REFRESH_TOKEN if refresh_token
71
+ auth_method = Plugin::AUTH_TYPE_JSON_KEY if json_key_content && auth_method == nil
72
+ {
73
+ "auth_method" => auth_method,
74
+ "client_id" => config.param("client_id", :string, default: nil),
75
+ "client_secret" => config.param("client_secret", :string, default: nil),
76
+ "refresh_token" => refresh_token,
58
77
  "json_key_content" => json_key_content,
59
78
  "view_id" => config.param("view_id", :string),
60
79
  "dimensions" => config.param("dimensions", :array, default: []),
@@ -98,7 +117,7 @@ module Embulk
98
117
  client = Client.new(task, preview?)
99
118
  columns = self.class.columns_from_task(task) + ["view_id"]
100
119
 
101
- last_record_time = task["last_record_time"] ? Time.parse(task["last_record_time"]) : nil
120
+ last_record_time = task['incremental'] && task["last_record_time"] ? Time.parse(task["last_record_time"]) : nil
102
121
 
103
122
  latest_time_series = nil
104
123
  skip_counter, total_counter = 0, 0
@@ -283,6 +283,60 @@ module Embulk
283
283
  end
284
284
  end
285
285
 
286
+ sub_test_case "oauth_refresh_token" do
287
+ setup do
288
+ conf = valid_config_oauth["in"]
289
+ mute_logger
290
+ @client = Client.new(task(embulk_config(conf)))
291
+ end
292
+
293
+ sub_test_case "retry refresh token" do
294
+ def should_retry
295
+ mock(Google::Auth::UserRefreshCredentials).new(anything).times(retryer.config.limit + 1) { raise error }
296
+ assert_raise do
297
+ @client.auth
298
+ end
299
+ end
300
+
301
+ def should_not_retry
302
+ mock(Google::Auth::UserRefreshCredentials).new(anything).times(1) { raise error }
303
+ assert_raise do
304
+ @client.auth
305
+ end
306
+ end
307
+
308
+ sub_test_case "Server respones error (5xx)" do
309
+ def error
310
+ Google::Apis::ServerError.new("error")
311
+ end
312
+
313
+ test "should retry refresh token" do
314
+ should_retry
315
+ end
316
+ end
317
+
318
+ sub_test_case "Refresh token reach Rate Limit" do
319
+ def error
320
+ Google::Apis::RateLimitError.new("error")
321
+ end
322
+
323
+ test "should retry refresh token" do
324
+ should_retry
325
+ end
326
+ end
327
+
328
+ sub_test_case "Refresh token Error" do
329
+ def error
330
+ Google::Apis::AuthorizationError.new("error")
331
+ end
332
+
333
+ test "should not retry" do
334
+ should_not_retry
335
+ end
336
+ end
337
+ end
338
+ end
339
+
286
340
  sub_test_case "too_early_data?" do
287
341
  def stub_timezone(client)
288
342
  stub(client).get_profile { {timezone: "America/Los_Angeles" } }
@@ -412,6 +466,10 @@ module Embulk
412
466
  fixture_load("valid.yml")
413
467
  end
414
468
 
469
+ def valid_config_oauth
470
+ fixture_load("valid_refresh_token.yml")
471
+ end
472
+
415
473
  def embulk_config(hash)
416
474
  Embulk::DataSource.new(hash)
417
475
  end
@@ -75,6 +75,46 @@ module Embulk
75
75
  end
76
76
  end
77
77
 
78
+ test "missing client_id params for oauth" do
79
+ conf = valid_config_oauth["in"]
80
+ conf.delete("client_id")
81
+ assert_raise(Embulk::ConfigError.new(oauth_expect_message)) do
82
+ Plugin.transaction(embulk_config(conf))
83
+ end
84
+ end
85
+
86
+ test "missing client_secret params for oauth" do
87
+ conf = valid_config_oauth["in"]
88
+ conf.delete('client_secret')
89
+ assert_raise(Embulk::ConfigError.new(oauth_expect_message)) do
90
+ Plugin.transaction(embulk_config(conf))
91
+ end
92
+ end
93
+
94
+ test "missing refresh_token params for oauth" do
95
+ conf = valid_config_oauth["in"]
96
+ conf.delete("refresh_token")
97
+ assert_raise(Embulk::ConfigError.new(unknown_auth_method_message)) do
98
+ Plugin.transaction(embulk_config(conf))
99
+ end
100
+ end
101
+
102
+ test "missing json_key_content params for oauth" do
103
+ conf = valid_config["in"]
104
+ conf.delete("json_key_content")
105
+ assert_raise(Embulk::ConfigError.new(unknown_auth_method_message)) do
106
+ Plugin.transaction(embulk_config(conf))
107
+ end
108
+ end
109
+
110
+ def unknown_auth_method_message
111
+ "Unknown Authentication method ''."
112
+ end
113
+
114
+ def oauth_expect_message
115
+ "client_id, client_secret and refresh_token are required when using Oauth authentication"
116
+ end
117
+
78
118
  def unknown_col_name
79
119
  "ga:foooooo"
80
120
  end
@@ -162,12 +202,14 @@ module Embulk
162
202
 
163
203
  sub_test_case "last_record_time option" do
164
204
  setup do
205
+ stub(Plugin).calculate_next_times { {} }
165
206
  Time.zone = "America/Los_Angeles"
166
207
  @last_record_time = Time.zone.parse("2016-06-01 12:00:00").to_time
167
208
 
168
209
  conf = valid_config["in"]
169
210
  conf["time_series"] = time_series
170
211
  conf["last_record_time"] = @last_record_time.strftime("%Y-%m-%d %H:%M:%S %z")
212
+ conf['incremental'] = true
171
213
  @plugin = Plugin.new(embulk_config(conf), nil, nil, @page_builder)
172
214
  end
173
215
 
@@ -182,6 +224,7 @@ module Embulk
182
224
  }
183
225
  block.call row
184
226
  end
227
+ stub(klass).get_profile { {timezone: "America/Los_Angeles" } }
185
228
  end
186
229
 
187
230
  mock(@page_builder).add.never
@@ -219,12 +262,15 @@ module Embulk
219
262
 
220
263
  sub_test_case "last_record_time option" do
221
264
  setup do
265
+ stub(Plugin).calculate_next_times { {} }
222
266
  Time.zone = "America/Los_Angeles"
223
267
  @last_record_time = Time.zone.parse("2016-06-01 12:00:00").to_time
224
268
 
225
269
  conf = valid_config["in"]
226
270
  conf["time_series"] = time_series
227
271
  conf["last_record_time"] = @last_record_time.strftime("%Y-%m-%d %H:%M:%S %z")
272
+ conf['incremental'] = true
273
+
228
274
  @plugin = Plugin.new(embulk_config(conf), nil, nil, @page_builder)
229
275
  end
230
276
 
@@ -239,6 +285,7 @@ module Embulk
239
285
  }
240
286
  block.call row
241
287
  end
288
+ stub(klass).get_profile { {timezone: "America/Los_Angeles" } }
242
289
  end
243
290
 
244
291
  mock(@page_builder).add.never
@@ -250,6 +297,39 @@ module Embulk
250
297
  end
251
298
  end
252
299
 
300
+ sub_test_case "run non-incremental" do
301
+ sub_test_case " should be added to page_builder" do
302
+ setup do
303
+ Time.zone = "America/Los_Angeles"
304
+ @last_record_time = Time.zone.parse("2016-06-01 12:00:00").to_time
305
+
306
+ conf = valid_config["in"]
307
+ conf["time_series"] = "ga:date"
308
+ conf["last_record_time"] = @last_record_time.strftime("%Y-%m-%d %H:%M:%S %z")
309
+ conf['incremental'] = false
310
+ @plugin = Plugin.new(embulk_config(conf), nil, nil, @page_builder)
311
+ end
312
+
313
+ test "should allow record to be added to page_builder" do
314
+ any_instance_of(Client) do |klass|
315
+ stub(klass).each_report_row do |block|
316
+ row = {
317
+ "ga:date" => @last_record_time,
318
+ "ga:browser" => "wget",
319
+ "ga:visits" => 3,
320
+ "ga:pageviews" => 4,
321
+ }
322
+ block.call row
323
+ end
324
+ end
325
+
326
+ mock(@page_builder).add(anything).at_least(1)
327
+ mock(@page_builder).finish
328
+ @plugin.run
329
+ end
330
+ end
331
+ end
332
+
253
333
  sub_test_case "canonicalize_column_name" do
254
334
  data do
255
335
  [
@@ -457,6 +537,10 @@ module Embulk
457
537
  def embulk_config(hash)
458
538
  Embulk::DataSource.new(hash)
459
539
  end
540
+
541
+ def valid_config_oauth
542
+ fixture_load("valid_refresh_token.yml")
543
+ end
460
544
  end
461
545
  end
462
546
  end
@@ -0,0 +1,18 @@
1
+ in:
2
+ type: google_analytics
3
+ refresh_token: "your_refresh_token"
4
+ client_id: "your_client_id_here"
5
+ client_secret: "your_client_secret_here"
6
+ view_id: 101111111
7
+ time_series: "ga:dateHour"
8
+
9
+ dimensions:
10
+ - "ga:browser"
11
+ metrics:
12
+ - "ga:visits"
13
+ - "ga:pageviews"
14
+ retry_limit: 2
15
+ retry_initial_wait_sec: 0
16
+
17
+ out:
18
+ type: stdout
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-input-google_analytics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.17
4
+ version: 0.1.18.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - uu59
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-16 00:00:00.000000000 Z
11
+ date: 2018-05-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -192,6 +192,20 @@ dependencies:
192
192
  - - ">="
193
193
  - !ruby/object:Gem::Version
194
194
  version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ requirement: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - ">="
199
+ - !ruby/object:Gem::Version
200
+ version: '0'
201
+ name: pry-debugger-jruby
202
+ prerelease: false
203
+ type: :development
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
195
209
  - !ruby/object:Gem::Dependency
196
210
  requirement: !ruby/object:Gem::Requirement
197
211
  requirements:
@@ -231,6 +245,7 @@ files:
231
245
  - test/fixture_helper.rb
232
246
  - test/fixtures/reports.json
233
247
  - test/fixtures/valid.yml
248
+ - test/fixtures/valid_refresh_token.yml
234
249
  - test/override_assert_raise.rb
235
250
  - test/run-test.rb
236
251
  homepage: https://github.com/treasure-data/embulk-input-google_analytics
@@ -248,9 +263,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
248
263
  version: '0'
249
264
  required_rubygems_version: !ruby/object:Gem::Requirement
250
265
  requirements:
251
- - - ">="
266
+ - - ">"
252
267
  - !ruby/object:Gem::Version
253
- version: '0'
268
+ version: 1.3.1
254
269
  requirements: []
255
270
  rubyforge_project:
256
271
  rubygems_version: 2.6.6
@@ -263,5 +278,6 @@ test_files:
263
278
  - test/fixture_helper.rb
264
279
  - test/fixtures/reports.json
265
280
  - test/fixtures/valid.yml
281
+ - test/fixtures/valid_refresh_token.yml
266
282
  - test/override_assert_raise.rb
267
283
  - test/run-test.rb