embulk-input-google_spreadsheets 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +12 -0
- data/CHANGELOG.md +67 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +94 -0
- data/Rakefile +13 -0
- data/embulk-input-google_spreadsheets.gemspec +24 -0
- data/example/config_authorized_user.yml +19 -0
- data/example/config_authorized_user.yml.liquid +25 -0
- data/example/config_authorized_user_emoji_worksheet.yml +19 -0
- data/example/config_authorized_user_empty_rows_appears_at_the_same_as_max_fetch_rows.yml +20 -0
- data/example/config_authorized_user_large_data.yml +19 -0
- data/example/config_authorized_user_no_data.yml +18 -0
- data/example/config_service_account.yml +19 -0
- data/example/config_service_account_emoji_worksheet.yml +19 -0
- data/example/config_service_account_empty_rows_appears_at_the_same_as_max_fetch_rows.yml +20 -0
- data/example/config_service_account_large_data.yml +19 -0
- data/example/config_service_account_no_data.yml +18 -0
- data/example/setup_authorized_user_credentials.rb +34 -0
- data/lib/embulk/input/google_spreadsheets.rb +182 -0
- data/lib/embulk/input/google_spreadsheets/auth.rb +63 -0
- data/lib/embulk/input/google_spreadsheets/error.rb +36 -0
- data/lib/embulk/input/google_spreadsheets/pager.rb +107 -0
- data/lib/embulk/input/google_spreadsheets/pager_util.rb +28 -0
- data/lib/embulk/input/google_spreadsheets/record_typecaster.rb +73 -0
- data/lib/embulk/input/google_spreadsheets/spreadsheets_client.rb +75 -0
- data/lib/embulk/input/google_spreadsheets/spreadsheets_url_util.rb +23 -0
- data/lib/embulk/input/google_spreadsheets/typecast/base.rb +62 -0
- data/lib/embulk/input/google_spreadsheets/typecast/loose_typecast.rb +84 -0
- data/lib/embulk/input/google_spreadsheets/typecast/minimal_typecast.rb +109 -0
- data/lib/embulk/input/google_spreadsheets/typecast/strict_typecast.rb +236 -0
- data/lib/embulk/input/google_spreadsheets/typecast/timestamp_format_util.rb +29 -0
- data/lib/embulk/input/google_spreadsheets/typecast_factory.rb +34 -0
- data/test/assert_embulk_nothing_raised.rb +11 -0
- data/test/assert_embulk_raise.rb +11 -0
- data/test/dummy.key +27 -0
- data/test/helper.rb +21 -0
- data/test/test_auth.rb +82 -0
- data/test/test_configure.rb +155 -0
- data/test/test_loose_typecast.rb +194 -0
- data/test/test_minimal_typecast.rb +616 -0
- data/test/test_pager_util.rb +24 -0
- data/test/test_run_examples.rb +125 -0
- data/test/test_spreadsheets_client.rb +87 -0
- data/test/test_spreadsheets_url_util.rb +23 -0
- data/test/test_strict_typecast.rb +666 -0
- data/test/test_typecast_factory.rb +36 -0
- metadata +220 -0
@@ -0,0 +1,236 @@
|
|
1
|
+
require 'time_with_zone'
|
2
|
+
require_relative 'base'
|
3
|
+
require_relative 'timestamp_format_util'
|
4
|
+
|
5
|
+
module Embulk
|
6
|
+
module Input
|
7
|
+
class GoogleSpreadsheets < InputPlugin
|
8
|
+
module Typecast
|
9
|
+
class StrictTypecast < Base
|
10
|
+
# It has assumed that argument `value` is an instance of any of the below classes.
|
11
|
+
# NilClass
|
12
|
+
# String
|
13
|
+
# TrueClass
|
14
|
+
# FalseClass
|
15
|
+
# Integer
|
16
|
+
# Float
|
17
|
+
# Array
|
18
|
+
# Hash
|
19
|
+
# Time
|
20
|
+
|
21
|
+
def as_string(value)
|
22
|
+
return nil if null_string?(value)
|
23
|
+
|
24
|
+
case value
|
25
|
+
when nil
|
26
|
+
nil
|
27
|
+
when String
|
28
|
+
value
|
29
|
+
when TrueClass
|
30
|
+
value.to_s
|
31
|
+
when FalseClass
|
32
|
+
value.to_s
|
33
|
+
when Integer
|
34
|
+
value.to_s
|
35
|
+
when Float
|
36
|
+
value.to_s
|
37
|
+
when Array
|
38
|
+
value.to_json
|
39
|
+
when Hash
|
40
|
+
value.to_json
|
41
|
+
when Time
|
42
|
+
# TODO: support Time class
|
43
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast Time to String: \"#{value}\""
|
44
|
+
else
|
45
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast #{value.class} to String: \"#{value}\""
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def as_long(value)
|
50
|
+
return nil if null_string?(value)
|
51
|
+
|
52
|
+
# `to_i` issue incorrect typecast, so use Integer()
|
53
|
+
# example
|
54
|
+
# [1] pry(main)> '111:222:333'.to_i
|
55
|
+
# => 111
|
56
|
+
# [2] pry(main)> Integer('111:222:333')
|
57
|
+
# ArgumentError: invalid value for Integer(): "111:222:333"
|
58
|
+
# from (pry):2:in `Integer'
|
59
|
+
case value
|
60
|
+
when nil
|
61
|
+
nil
|
62
|
+
when String
|
63
|
+
return nil if value.is_a?(String) and value.empty?
|
64
|
+
begin
|
65
|
+
Integer(value)
|
66
|
+
rescue ArgumentError => e
|
67
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: #{e}"
|
68
|
+
end
|
69
|
+
when TrueClass
|
70
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast true to Integer: \"#{value}\""
|
71
|
+
when FalseClass
|
72
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast false to Integer: \"#{value}\""
|
73
|
+
when Integer
|
74
|
+
value
|
75
|
+
when Float
|
76
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast Float to Integer: \"#{value}\""
|
77
|
+
when Array
|
78
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast Array to Integer: \"#{value}\""
|
79
|
+
when Hash
|
80
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast Hash to Integer: \"#{value}\""
|
81
|
+
when Time
|
82
|
+
value.to_i
|
83
|
+
else
|
84
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast #{value.class} to Integer: \"#{value}\""
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def as_double(value)
|
89
|
+
return nil if null_string?(value)
|
90
|
+
|
91
|
+
# `to_f` issue incorrect typecast, so use Float()
|
92
|
+
# example
|
93
|
+
# [1] pry(main)> '111:222:333'.to_f
|
94
|
+
# => 111.0
|
95
|
+
# [2] pry(main)> Float('111:222:333')
|
96
|
+
# ArgumentError: invalid value for Float(): "111:222:333"
|
97
|
+
# from (pry):2:in `Float'
|
98
|
+
case value
|
99
|
+
when nil
|
100
|
+
nil
|
101
|
+
when String, Integer
|
102
|
+
return nil if value.is_a?(String) and value.empty?
|
103
|
+
begin
|
104
|
+
Float(value)
|
105
|
+
rescue ArgumentError => e
|
106
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: #{e}"
|
107
|
+
end
|
108
|
+
when TrueClass
|
109
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast true to Float: \"#{value}\""
|
110
|
+
when FalseClass
|
111
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast false to Float: \"#{value}\""
|
112
|
+
# when Integer then ...
|
113
|
+
# => merge with String case
|
114
|
+
when Float
|
115
|
+
value
|
116
|
+
when Array
|
117
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast Array to Float: \"#{value}\""
|
118
|
+
when Hash
|
119
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast Hash to Float: \"#{value}\""
|
120
|
+
when Time
|
121
|
+
value.to_f
|
122
|
+
else
|
123
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast #{value.class} to Float: \"#{value}\""
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
BOOLEAN_TRUE_VALUES = %w(yes y true t 1)
|
128
|
+
BOOLEAN_FALSE_VALUES = %w(no n false f 0)
|
129
|
+
|
130
|
+
def as_boolean(value)
|
131
|
+
return nil if null_string?(value)
|
132
|
+
|
133
|
+
case value
|
134
|
+
when nil
|
135
|
+
nil
|
136
|
+
when String, Integer
|
137
|
+
return nil if value.is_a?(String) and value.empty?
|
138
|
+
value = value.to_s unless value.is_a?(String)
|
139
|
+
return true if BOOLEAN_TRUE_VALUES.include?(value.downcase)
|
140
|
+
return false if BOOLEAN_FALSE_VALUES.include?(value.downcase)
|
141
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast '#{value}' to a boolean value." \
|
142
|
+
" A boolean value must be one of #{BOOLEAN_TRUE_VALUES + BOOLEAN_FALSE_VALUES}: \"#{value}\""
|
143
|
+
when TrueClass
|
144
|
+
true
|
145
|
+
when FalseClass
|
146
|
+
false
|
147
|
+
# when Integer then ... => merge with String case
|
148
|
+
when Float
|
149
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast Float to a boolean value: \"#{value}\""
|
150
|
+
when Array
|
151
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast Array to a boolean value: \"#{value}\""
|
152
|
+
when Hash
|
153
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast Hash to a boolean value: \"#{value}\""
|
154
|
+
when Time
|
155
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast Time to String: \"#{value}\""
|
156
|
+
else
|
157
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast #{value.class} to a boolean value: \"#{value}\""
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def as_timestamp(value, timestamp_format = nil, timezone = nil)
|
162
|
+
return nil if null_string?(value)
|
163
|
+
|
164
|
+
case value
|
165
|
+
when nil
|
166
|
+
nil
|
167
|
+
when String, Integer, Float
|
168
|
+
return nil if value.is_a?(String) and value.empty?
|
169
|
+
value = value.to_s unless value.is_a?(String)
|
170
|
+
begin
|
171
|
+
if timestamp_format and TimestampFormatUtil.timezone_format?(timestamp_format)
|
172
|
+
Time.strptime(value, timestamp_format)
|
173
|
+
elsif timestamp_format and timezone
|
174
|
+
TimeWithZone.strptime_with_zone(value, timestamp_format, timezone)
|
175
|
+
elsif timezone
|
176
|
+
TimeWithZone.parse_with_zone(value, timezone)
|
177
|
+
elsif timestamp_format
|
178
|
+
Time.strptime(value, timestamp_format)
|
179
|
+
else
|
180
|
+
Time.parse(value)
|
181
|
+
end
|
182
|
+
rescue ArgumentError => e
|
183
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast #{value.class} to Time: \"#{value}\" because of '#{e}'"
|
184
|
+
end
|
185
|
+
when TrueClass
|
186
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast true to Time: \"#{value}\""
|
187
|
+
when FalseClass
|
188
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast false to Time: \"#{value}\""
|
189
|
+
# when Integer
|
190
|
+
# ... => merge with String case
|
191
|
+
# when Float
|
192
|
+
# ... => merge with String case
|
193
|
+
when Array
|
194
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast Array to Time: \"#{value}\""
|
195
|
+
when Hash
|
196
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast Hash to Time: \"#{value}\""
|
197
|
+
when Time
|
198
|
+
value
|
199
|
+
else
|
200
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast #{value.class} to Time: \"#{value}\""
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def as_json(value)
|
205
|
+
return nil if null_string?(value)
|
206
|
+
|
207
|
+
# NOTE: This method must do `JSON.parse` if `value` is String. ref. https://github.com/embulk/embulk/issues/499
|
208
|
+
case value
|
209
|
+
when nil, Array, Hash
|
210
|
+
value
|
211
|
+
when String
|
212
|
+
begin
|
213
|
+
JSON.parse(value)
|
214
|
+
rescue JSON::ParserError => e
|
215
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast #{value.class} to JSON: \"#{value}\" because of '#{e}'"
|
216
|
+
end
|
217
|
+
# when TrueClass then ... => merge with Time case
|
218
|
+
# when FalseClass then ... => merge with Time case
|
219
|
+
# when Integer then ... => merge with Time case
|
220
|
+
# when Float then ... => merge with Time case
|
221
|
+
# when Array then ... => merge with nil case
|
222
|
+
# when Hash then ... => merge with nil case
|
223
|
+
when TrueClass, FalseClass, Integer, Float, Array, Hash, Time
|
224
|
+
# TODO: support Time class. Now call Exception to avoid format/timezone trouble.
|
225
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast Time to JSON: \"#{value}\""
|
226
|
+
|
227
|
+
else
|
228
|
+
raise TypecastError.new "`embulk-input-google_spreadsheets`: cannot typecast #{value.class} to JSON: \"#{value}\""
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Embulk
|
2
|
+
module Input
|
3
|
+
class GoogleSpreadsheets < InputPlugin
|
4
|
+
module Typecast
|
5
|
+
module TimestampFormatUtil
|
6
|
+
|
7
|
+
def self.timezone_format?(format)
|
8
|
+
@cache ||= {}
|
9
|
+
return @cache[format.dup] if @cache.has_key?(format)
|
10
|
+
@cache[format] = tz_regexp === format
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def self.tz_regexp
|
16
|
+
# Time zone:
|
17
|
+
# %z - Time zone as hour and minute offset from UTC (e.g. +0900)
|
18
|
+
# %:z - hour and minute offset from UTC with a colon (e.g. +09:00)
|
19
|
+
# %::z - hour, minute and second offset from UTC (e.g. +09:00:00)
|
20
|
+
# %Z - Abbreviated time zone name or similar information. (OS dependent)
|
21
|
+
#
|
22
|
+
# ref. https://docs.ruby-lang.org/en/2.3.0/Time.html#method-i-strftime
|
23
|
+
@tz_regexp ||= %r{(?:\A|[^%]|(?:%%)+)%(?::?:?z|Z)}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'error'
|
2
|
+
|
3
|
+
module Embulk
|
4
|
+
module Input
|
5
|
+
class GoogleSpreadsheets < InputPlugin
|
6
|
+
module TypecastFactory
|
7
|
+
def self.create(type, task)
|
8
|
+
raise GoogleSpreadsheets::ConfigError.new("`embulk-input-google_spreadsheets`: unknown typecast '#{type}'") if type.nil? or !type.is_a?(String)
|
9
|
+
|
10
|
+
type = type.downcase
|
11
|
+
path = build_typecast_class_path(type)
|
12
|
+
raise GoogleSpreadsheets::ConfigError.new("`embulk-input-google_spreadsheets`: Typecast class path does not exist '#{path}'") unless File.exist?(path)
|
13
|
+
|
14
|
+
require path
|
15
|
+
typecast_class(type).new(task)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.typecast_class(type)
|
21
|
+
Object.const_get("Embulk::Input::GoogleSpreadsheets::Typecast::#{camelize(type)}Typecast")
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.build_typecast_class_path(type)
|
25
|
+
File.expand_path("typecast/#{type}_typecast.rb", __dir__)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.camelize(snake)
|
29
|
+
snake.split('_').map{|w| w[0] = w[0].upcase; w}.join
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module AssertEmbulkRaise
|
2
|
+
# NOTE: assert_raise(TypecastError) do ... end can't detect correctly
|
3
|
+
def assert_embulk_raise(klass, &block)
|
4
|
+
begin
|
5
|
+
yield
|
6
|
+
assert false
|
7
|
+
rescue => e
|
8
|
+
assert e.is_a?(klass), "expect: #{klass.name}, actual: #{e.class.name}, message: #{e}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/test/dummy.key
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIIEpgIBAAKCAQEApmXpbr2WNslz+T881vt8uljjBtcJR8eu0UVcGfLjdZ+sn86z
|
3
|
+
HMJgzKUlV5Y8GFT2ktgcznAM/Tn83XsKbOLKfdutdnRHQK/bG4Qj7QxI1TiEbJ8y
|
4
|
+
c8EWdO8GvFQXkKSlL26U/t8tPgnFrYKt5C/XNvVL3vPEWS9MtJk903llWhRueXJ8
|
5
|
+
iOFMKWq50fIr28gzDnzXqwErhzdDuxI2FWHcjXI20eWMg/uHG8m0OfHDZhcsOlri
|
6
|
+
+SXX+TkCwEeyUak2WqPCA+HzlNJRGyphgQIMixI8ZAnZ6vmz4coD5yXNRGOzAhq1
|
7
|
+
86s/ajOAFnSOVN98SutvkrgY9UlywPv+5UVxnwIDAQABAoIBAQCeVt3xlhDJ45sr
|
8
|
+
M8TWIguHW6v1R0y6dEZjNyg0PQ+7Tw06KLwCAumP8xp8pSZcVQUpqOKIgtGpabO4
|
9
|
+
oivCf3EGoLMIxA9Fe9H49h4lpQntc9F3d2nQAo43CXkUXsTpy/KwFv9LJN3taekk
|
10
|
+
efS07d1Sm8rtxnMyFrNcK3JMuPj75GmdSHPGnBth/EUMoNzE4FiTUJaDg/DrXHg/
|
11
|
+
zxIW7H+vVKEnlhExp8vX4VXgXJJ1J4woXAD1h2RneV2zHu/OsXI5prBbSUdR2jSw
|
12
|
+
obZqF2XFpBvZOOuYWQ53kJB1vqLWODb14Bp7okfpqA9QSM52tzTJjXYGpgd0lhGq
|
13
|
+
vHfulyCJAoGBAN0Uw9slMitG3TlabKdCbzKHhw8izuyFpfPU+NU+PeKZo4yN5iRG
|
14
|
+
jr5S+VlmavqzNyhgG6bh1f2e95Tygcu7CKMTDG6m4s71iZ+yr+yN/bX07DwSERor
|
15
|
+
q3NtYxLtvAdEUkpAxLTDZXzYDYWXKOkslV8hNZJXZiQX98KdkEkljnbdAoGBAMCu
|
16
|
+
FVZVVm186yQLE3myfHemyiGoyLNivEXDL0/L5P/FFTlS7CwMq3+ZBdPWuPKi8pjb
|
17
|
+
K4NUxDOAWMgTJzKcQRCNLez470l9GGp+tIvlo7gtt8BVkIL0jIZ92xV7nGskDV1z
|
18
|
+
HnqdkJ/v8Y2/CIZ9q7Q+iLcM+Xf/BNuccIwInXyrAoGBAL/r797FmpjhKtlIO3yz
|
19
|
+
+o5WAxRLtnCz0Q4su1t7bgPSNp2k7b5eFjr5EwfeFk7O17pQPJESCk/i+bEvGSiA
|
20
|
+
lI3k0m0YqVra4v9lAr4Lwc188rtvP7OFZ5CLzG85PHref8WAFoOKAQdxE8P+JoDN
|
21
|
+
uFpeHQCOqNf6ipZDbGdjmBptAoGBAL3H+b5CadGH0/d5bWJV2mDkCH3kyGJgIv83
|
22
|
+
xBb9xn3ieggvU+4DQLx6VZIVEa/zra2/WnmN+X6csVXH/7jKzQ9nb0/U1aP1siHa
|
23
|
+
0SxmML8NUMsBvEgwZWVm+26KhUPGi996rw+ouLW/2ZV7DwOhLolnerOJ9QIrTnac
|
24
|
+
/QIAzlXnAoGBAMq/PA22fsGGyJwtKoxJiFwm6myb9q4dx7CsRUW8FivXXa8IBV6K
|
25
|
+
8TvzytIGA9SjIRHQR9wDOlxyO7JE5ndEwBIsPesARvcRdrukN7UWorT5y33KRe8m
|
26
|
+
bd54ICAxK+uNVWBv2xaM6V9hFdzeYZ8McZvlht4AqDmkHu/nsTYMeLci
|
27
|
+
-----END RSA PRIVATE KEY-----
|
data/test/helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'test/unit/rr'
|
5
|
+
|
6
|
+
ENV['TZ'] = 'JST-9'
|
7
|
+
|
8
|
+
require 'embulk'
|
9
|
+
Embulk.setup
|
10
|
+
Embulk.logger = Embulk::Logger.new('/dev/null')
|
11
|
+
|
12
|
+
APP_ROOT = File.expand_path('../', __dir__)
|
13
|
+
EXAMPLE_ROOT = File.join(APP_ROOT, 'example')
|
14
|
+
TEST_ROOT = File.join(APP_ROOT, 'test')
|
15
|
+
JSON_KEYFILE_SERVICE_ACCOUNT = File.join(EXAMPLE_ROOT, 'service_account_credentials.json')
|
16
|
+
JSON_KEYFILE_AUTHORIZED_USER = File.join(EXAMPLE_ROOT, 'authorized_user_credentials.json')
|
17
|
+
TEST_SPREADSHEETS_URL = 'https://docs.google.com/spreadsheets/d/1Cxz-LudQuhRAGZL8mBoHs6mRnpjODpyF4Rwc5UYoV1E/edit#gid=0'
|
18
|
+
TEST_SPREADSHEETS_ID = '1Cxz-LudQuhRAGZL8mBoHs6mRnpjODpyF4Rwc5UYoV1E'
|
19
|
+
TEST_WORKSHEET_TITLE = 'sheet1'
|
20
|
+
TEST_WORKSHEET_TITLE_MULTI_BYTE = '日本語(japanese)'
|
21
|
+
DUMMY_RSA_KEY = File.expand_path('dummy.key', __dir__) # openssl genrsa 2048 > dummy.key
|
data/test/test_auth.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
require 'embulk/input/google_spreadsheets'
|
3
|
+
require_relative 'assert_embulk_raise'
|
4
|
+
require_relative 'assert_embulk_nothing_raised'
|
5
|
+
|
6
|
+
module Embulk
|
7
|
+
class Input::GoogleSpreadsheets < InputPlugin
|
8
|
+
|
9
|
+
class TestAuth < Test::Unit::TestCase
|
10
|
+
|
11
|
+
include AssertEmbulkRaise
|
12
|
+
include AssertEmbulkNothingRaised
|
13
|
+
|
14
|
+
sub_test_case 'authorized_user' do
|
15
|
+
unless File.exist?(JSON_KEYFILE_AUTHORIZED_USER)
|
16
|
+
puts "#{JSON_KEYFILE_AUTHORIZED_USER} is not found. Skip correct cases authorized_user"
|
17
|
+
else
|
18
|
+
test 'correct json_keyfile' do
|
19
|
+
task = {
|
20
|
+
'auth_method' => 'authorized_user',
|
21
|
+
'json_keyfile' => File.read(JSON_KEYFILE_AUTHORIZED_USER)
|
22
|
+
}
|
23
|
+
assert_embulk_nothing_raised do
|
24
|
+
Auth.new(task).authenticate.fetch_access_token!
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
test 'incorrect json_keyfile' do
|
30
|
+
task = {
|
31
|
+
'auth_method' => 'authorized_user',
|
32
|
+
'json_keyfile' => '{"client_id":"hoge", "client_secret":"fuga","refresh_token":"hogo"}'
|
33
|
+
}
|
34
|
+
assert_embulk_raise Signet::AuthorizationError do
|
35
|
+
Auth.new(task).authenticate.fetch_access_token!
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
sub_test_case 'service_account' do
|
41
|
+
unless File.exist?(JSON_KEYFILE_SERVICE_ACCOUNT)
|
42
|
+
puts "#{JSON_KEYFILE_SERVICE_ACCOUNT} is not found. Skip correct cases service_account"
|
43
|
+
else
|
44
|
+
test 'correct json_keyfile' do
|
45
|
+
task = {
|
46
|
+
'auth_method' => 'service_account',
|
47
|
+
'json_keyfile' => File.read(JSON_KEYFILE_SERVICE_ACCOUNT)
|
48
|
+
}
|
49
|
+
assert_embulk_nothing_raised do
|
50
|
+
Auth.new(task).authenticate.fetch_access_token!
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
test 'incorrect json_keyfile' do
|
56
|
+
dummy_rsa_key = File.read(DUMMY_RSA_KEY).gsub("\n", '\n')
|
57
|
+
task = {
|
58
|
+
'auth_method' => 'service_account',
|
59
|
+
'json_keyfile' => '{"client_id":"hoge", "client_secret":"fuga","client_email":"hogo","private_key":"' + dummy_rsa_key + '"}'
|
60
|
+
}
|
61
|
+
assert_embulk_raise Signet::AuthorizationError do
|
62
|
+
Auth.new(task).authenticate.fetch_access_token!
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# TODO: compute_engine cases
|
68
|
+
# TODO: application_default cases
|
69
|
+
|
70
|
+
sub_test_case 'ConfigError' do
|
71
|
+
test 'invalid auth_method' do
|
72
|
+
task = {
|
73
|
+
'auth_methqd' => 'hoge'
|
74
|
+
}
|
75
|
+
assert_embulk_raise ConfigError do
|
76
|
+
Auth.new(task).authenticate
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|