embulk-input-google_spreadsheets 1.0.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.
- 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
|