td 0.11.10 → 0.11.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +1 -0
- data/.travis.yml +18 -0
- data/ChangeLog +10 -0
- data/README.rdoc +3 -1
- data/Rakefile +11 -0
- data/appveyor.yml +17 -0
- data/lib/td/command/connector.rb +68 -46
- data/lib/td/command/import.rb +17 -2
- data/lib/td/command/list.rb +12 -2
- data/lib/td/command/table.rb +7 -46
- data/lib/td/version.rb +1 -1
- data/spec/spec_helper.rb +7 -1
- data/spec/td/command/connector_spec.rb +8 -6
- data/spec/td/command/job_spec.rb +15 -7
- data/spec/td/updater_spec.rb +31 -23
- data/td.gemspec +5 -3
- metadata +56 -50
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e564b64771f7174a938bb3bbc1018c29dde82e23
|
4
|
+
data.tar.gz: 4ef2d5ce846fa9eb2b2e6a250f4a21947d9c86a0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ccd286b00461da0f4880faaee3f82663ea37559fe79e13ff5d606a77012f3fc7df1f0e7b99b1468eb4a0118a51ba00dcbdfa61df5aa4c42b24984592dd172e4d
|
7
|
+
data.tar.gz: d5a9c05c266d1efd0a2c853e2497bcc5f6389a38de0a6d45f76d2535fa20431a077db2eb860cff9369dd96c59a0843117fd15ebeb0a10f8ddf469893b41d3f8e
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/ChangeLog
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
== 2015-07-10 version 0.11.11
|
2
|
+
|
3
|
+
* Updated 'td-client' gem dependency to 0.8.71. The new gem removed to/from
|
4
|
+
parameter from table/tail API.
|
5
|
+
* Version up bundled Ruby for Mac and Windows.
|
6
|
+
* Remove -t (to) and -f (from) from table:tail command.
|
7
|
+
* connector:guess shows help message if no arguments are set.
|
8
|
+
* table:* unsupported 'item' table.
|
9
|
+
* upgrade rubyzip
|
10
|
+
|
1
11
|
== 2015-05-19 version 0.11.10
|
2
12
|
|
3
13
|
* Updated 'td-client' gem dependency to 0.8.70. The new gem removed client
|
data/README.rdoc
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
= Treasure Data command line tool
|
2
|
+
{<img src="https://travis-ci.org/treasure-data/td.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/treasure-data/td]
|
3
|
+
{<img src="https://coveralls.io/repos/treasure-data/td/badge.svg?branch=master&service=github" alt="Coverage Status" />}[https://coveralls.io/github/treasure-data/td?branch=master]
|
2
4
|
|
3
5
|
This CUI utility wraps the {Ruby Client Library td-client-ruby}[https://github.com/treasure-data/td-client-ruby]
|
4
6
|
to interact with the REST API in managing databases and jobs on the Treasure Data Cloud.
|
@@ -146,5 +148,5 @@ These are the available hooks:
|
|
146
148
|
|
147
149
|
= Copyright
|
148
150
|
|
149
|
-
Copyright:: Copyright (c)
|
151
|
+
Copyright:: Copyright (c) 2015 Treasure Data Inc.
|
150
152
|
License:: Apache License, Version 2.0
|
data/Rakefile
CHANGED
@@ -145,3 +145,14 @@ Dir[File.expand_path("../dist/**/*.rake", __FILE__)].each do |rake|
|
|
145
145
|
import rake
|
146
146
|
end
|
147
147
|
|
148
|
+
require 'rspec/core'
|
149
|
+
require 'rspec/core/rake_task'
|
150
|
+
|
151
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
152
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
153
|
+
end
|
154
|
+
|
155
|
+
task :coverage do |t|
|
156
|
+
ENV['SIMPLE_COV'] = '1'
|
157
|
+
Rake::Task["spec"].invoke
|
158
|
+
end
|
data/appveyor.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
---
|
2
|
+
version: "{build}"
|
3
|
+
clone_depth: 10
|
4
|
+
install:
|
5
|
+
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
|
6
|
+
- ruby --version
|
7
|
+
- gem --version
|
8
|
+
- gem install bundler --quiet --no-ri --no-rdoc
|
9
|
+
- bundler --version
|
10
|
+
- bundle install
|
11
|
+
build_script:
|
12
|
+
- bundle exec rake build
|
13
|
+
test_script:
|
14
|
+
- bundle exec rake spec
|
15
|
+
environment:
|
16
|
+
matrix:
|
17
|
+
- ruby_version: "22"
|
data/lib/td/command/connector.rb
CHANGED
@@ -18,21 +18,31 @@ module Command
|
|
18
18
|
id = secret = source = nil
|
19
19
|
out = 'td-bulkload.yml'
|
20
20
|
|
21
|
-
op.on('--type[=TYPE]', "
|
22
|
-
op.on('--access-id ID', "
|
23
|
-
op.on('--access-secret SECRET', "
|
24
|
-
op.on('--source SOURCE', "
|
25
|
-
op.on('--out FILE_NAME', "
|
26
|
-
|
27
|
-
|
28
|
-
if
|
29
|
-
|
30
|
-
out ||=
|
21
|
+
op.on('--type[=TYPE]', "(obsoleted)") { |s| type = s }
|
22
|
+
op.on('--access-id ID', "(obsoleted)") { |s| id = s }
|
23
|
+
op.on('--access-secret SECRET', "(obsoleted)") { |s| secret = s }
|
24
|
+
op.on('--source SOURCE', "(obsoleted)") { |s| source = s }
|
25
|
+
op.on('-o', '--out FILE_NAME', "output file name for connector:preview") { |s| out = s }
|
26
|
+
|
27
|
+
config_file = op.cmd_parse
|
28
|
+
if config_file
|
29
|
+
config = prepare_bulkload_job_config(config_file)
|
30
|
+
out ||= config_file
|
31
31
|
else
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
begin
|
33
|
+
required('--access-id', id)
|
34
|
+
required('--access-secret', secret)
|
35
|
+
required('--source', source)
|
36
|
+
required('--out', out)
|
37
|
+
rescue ParameterConfigurationError
|
38
|
+
if id == nil && secret == nil && source == nil
|
39
|
+
$stdout.puts op.to_s
|
40
|
+
$stdout.puts ""
|
41
|
+
raise ParameterConfigurationError, "path to configuration file is required"
|
42
|
+
else
|
43
|
+
raise
|
44
|
+
end
|
45
|
+
end
|
36
46
|
|
37
47
|
uri = URI.parse(source)
|
38
48
|
endpoint = uri.host
|
@@ -40,26 +50,24 @@ module Command
|
|
40
50
|
bucket = path_components.shift.sub(/\//, '')
|
41
51
|
path_prefix = path_components.join.sub(/\//, '')
|
42
52
|
|
43
|
-
|
44
|
-
:
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
:path_prefix => path_prefix,
|
51
|
-
}
|
53
|
+
config = {
|
54
|
+
:type => type,
|
55
|
+
:access_key_id => id,
|
56
|
+
:secret_access_key => secret,
|
57
|
+
:endpoint => endpoint,
|
58
|
+
:bucket => bucket,
|
59
|
+
:path_prefix => path_prefix,
|
52
60
|
}
|
53
61
|
end
|
54
62
|
|
55
63
|
client = get_client
|
56
|
-
job = client.bulk_load_guess(
|
64
|
+
job = client.bulk_load_guess(config: config)
|
57
65
|
|
58
66
|
create_bulkload_job_file_backup(out)
|
59
67
|
if /\.json\z/ =~ out
|
60
|
-
config_str = JSON.pretty_generate(job)
|
68
|
+
config_str = JSON.pretty_generate(job['config'])
|
61
69
|
else
|
62
|
-
config_str = YAML.dump(job)
|
70
|
+
config_str = YAML.dump(job['config'])
|
63
71
|
end
|
64
72
|
File.open(out, 'w') do |f|
|
65
73
|
f << config_str
|
@@ -76,9 +84,9 @@ module Command
|
|
76
84
|
def connector_preview(op)
|
77
85
|
set_render_format_option(op)
|
78
86
|
config_file = op.cmd_parse
|
79
|
-
|
87
|
+
config = prepare_bulkload_job_config(config_file)
|
80
88
|
client = get_client()
|
81
|
-
preview = client.bulk_load_preview(
|
89
|
+
preview = client.bulk_load_preview(config: config)
|
82
90
|
|
83
91
|
cols = preview['schema'].sort_by { |col|
|
84
92
|
col['index']
|
@@ -105,7 +113,7 @@ module Command
|
|
105
113
|
wait = exclude = false
|
106
114
|
op.on('--database DB_NAME', "destination database") { |s| database = s }
|
107
115
|
op.on('--table TABLE_NAME', "destination table") { |s| table = s }
|
108
|
-
op.on('--time-column COLUMN_NAME', "data partitioning key") { |s| time_column = s }
|
116
|
+
op.on('--time-column COLUMN_NAME', "data partitioning key") { |s| time_column = s } # unnecessary but for backward compatibility
|
109
117
|
op.on('-w', '--wait', 'wait for finishing the job', TrueClass) { |b| wait = b }
|
110
118
|
op.on('-x', '--exclude', 'do not automatically retrieve the job result', TrueClass) { |b| exclude = b }
|
111
119
|
|
@@ -114,11 +122,11 @@ module Command
|
|
114
122
|
required('--database', database)
|
115
123
|
required('--table', table)
|
116
124
|
|
117
|
-
|
118
|
-
|
125
|
+
config = prepare_bulkload_job_config(config_file)
|
126
|
+
(config['out'] ||= {})['time_column'] = time_column if time_column # TODO will not work once embulk implements multi-job
|
119
127
|
|
120
128
|
client = get_client()
|
121
|
-
job_id = client.bulk_load_issue(database, table, job)
|
129
|
+
job_id = client.bulk_load_issue(database, table, config: job)
|
122
130
|
|
123
131
|
$stdout.puts "Job #{job_id} is queued."
|
124
132
|
$stdout.puts "Use '#{$prog} " + Config.cl_options_string + "job:show #{job_id}' to show the status."
|
@@ -166,13 +174,13 @@ module Command
|
|
166
174
|
|
167
175
|
name, cron, database, table, config_file = op.cmd_parse
|
168
176
|
|
169
|
-
|
177
|
+
config = prepare_bulkload_job_config(config_file)
|
170
178
|
opts[:cron] = cron
|
171
179
|
|
172
180
|
client = get_client()
|
173
181
|
get_table(client, database, table)
|
174
182
|
|
175
|
-
session = client.bulk_load_create(name, database, table,
|
183
|
+
session = client.bulk_load_create(name, database, table, opts.merge(config: config))
|
176
184
|
dump_connector_session(session)
|
177
185
|
end
|
178
186
|
|
@@ -187,10 +195,10 @@ module Command
|
|
187
195
|
def connector_update(op)
|
188
196
|
name, config_file = op.cmd_parse
|
189
197
|
|
190
|
-
|
198
|
+
config = prepare_bulkload_job_config(config_file)
|
191
199
|
|
192
200
|
client = get_client()
|
193
|
-
session = client.bulk_load_update(name,
|
201
|
+
session = client.bulk_load_update(name, config: config)
|
194
202
|
dump_connector_session(session)
|
195
203
|
end
|
196
204
|
|
@@ -264,10 +272,24 @@ private
|
|
264
272
|
raise ParameterConfigurationError, "configuration file: #{config_file} not found"
|
265
273
|
end
|
266
274
|
config_str = File.read(config_file)
|
267
|
-
|
268
|
-
|
275
|
+
|
276
|
+
config = nil
|
277
|
+
begin
|
278
|
+
if file_type(config_str) == :yaml
|
279
|
+
config_str = JSON.pretty_generate(YAML.load(config_str))
|
280
|
+
end
|
281
|
+
config = JSON.load(config_str)
|
282
|
+
rescue => e
|
283
|
+
raise ParameterConfigurationError, "configuration file: #{config_file} #{e.message}"
|
284
|
+
end
|
285
|
+
|
286
|
+
if config['config']
|
287
|
+
if config.size != 1
|
288
|
+
raise "Setting #{(config.keys - ['config']).inspect} keys in a configuration file is not supported. Please set options to the command line argument."
|
289
|
+
end
|
290
|
+
config = config['config']
|
269
291
|
end
|
270
|
-
|
292
|
+
config
|
271
293
|
end
|
272
294
|
|
273
295
|
def create_bulkload_job_file_backup(out)
|
@@ -283,14 +305,14 @@ private
|
|
283
305
|
end
|
284
306
|
|
285
307
|
def dump_connector_session(session)
|
286
|
-
$stdout.puts "Name : #{session
|
287
|
-
$stdout.puts "Cron : #{session
|
288
|
-
$stdout.puts "Timezone : #{session
|
289
|
-
$stdout.puts "Delay : #{session
|
290
|
-
$stdout.puts "Database : #{session
|
291
|
-
$stdout.puts "Table : #{session
|
308
|
+
$stdout.puts "Name : #{session["name"]}"
|
309
|
+
$stdout.puts "Cron : #{session["cron"]}"
|
310
|
+
$stdout.puts "Timezone : #{session["timezone"]}"
|
311
|
+
$stdout.puts "Delay : #{session["delay"]}"
|
312
|
+
$stdout.puts "Database : #{session["database"]}"
|
313
|
+
$stdout.puts "Table : #{session["table"]}"
|
292
314
|
$stdout.puts "Config"
|
293
|
-
$stdout.puts YAML.dump(session
|
315
|
+
$stdout.puts YAML.dump(session["config"])
|
294
316
|
end
|
295
317
|
|
296
318
|
def wait_connector_job(client, job_id, exclude)
|
data/lib/td/command/import.rb
CHANGED
@@ -150,11 +150,15 @@ module Command
|
|
150
150
|
begin
|
151
151
|
Timeout.timeout(@timeout) do
|
152
152
|
pid = Process.spawn(*@cmd)
|
153
|
-
|
154
|
-
return $?
|
153
|
+
waitpid(pid)
|
155
154
|
end
|
156
155
|
rescue Timeout::Error
|
157
156
|
if pid
|
157
|
+
# NOTE last check has not been completed the process during sleep
|
158
|
+
if Process.waitpid(pid, Process::WNOHANG)
|
159
|
+
return $?
|
160
|
+
end
|
161
|
+
|
158
162
|
require 'rbconfig'
|
159
163
|
# win32 ruby does not support QUIT and TERM
|
160
164
|
if RbConfig::CONFIG['host_os'] !~ /mswin|mingw|cygwin/
|
@@ -172,6 +176,17 @@ module Command
|
|
172
176
|
return $?
|
173
177
|
end
|
174
178
|
end
|
179
|
+
|
180
|
+
def waitpid(pid)
|
181
|
+
# NOTE Use nonblocking mode, because Process.waitpid is block other thread at Windows.
|
182
|
+
loop do
|
183
|
+
if Process.waitpid(pid, Process::WNOHANG)
|
184
|
+
return $?
|
185
|
+
end
|
186
|
+
|
187
|
+
sleep 1
|
188
|
+
end
|
189
|
+
end
|
175
190
|
end
|
176
191
|
|
177
192
|
def check_java
|
data/lib/td/command/list.rb
CHANGED
@@ -236,7 +236,7 @@ module List
|
|
236
236
|
add_list 'table:import', %w[db table files_], 'Parse and import files to a table', ['table:import example_db table1 --apache access.log', 'table:import example_db table1 --json -t time - < test.json']
|
237
237
|
add_list 'table:export', %w[db table], 'Dump logs in a table to the specified storage', ['table:export example_db table1 --s3-bucket mybucket -k KEY_ID -s SECRET_KEY']
|
238
238
|
add_list 'table:swap', %w[db table1 table2], 'Swap names of two tables', ['table:swap example_db table1 table2']
|
239
|
-
add_list 'table:tail', %w[db table], 'Get recently imported logs', ['table:tail example_db table1', 'table:tail example_db table1 -
|
239
|
+
add_list 'table:tail', %w[db table], 'Get recently imported logs', ['table:tail example_db table1', 'table:tail example_db table1 -n 30']
|
240
240
|
add_list 'table:partial_delete', %w[db table], 'Delete logs from the table within the specified time range', ['table:partial_delete example_db table1 --from 1341000000 --to 1341003600']
|
241
241
|
add_list 'table:expire', %w[db table expire_days], 'Expire data in table after specified number of days. Set to 0 to disable the expiration.', ['table:expire example_db table1 30']
|
242
242
|
|
@@ -332,7 +332,17 @@ module List
|
|
332
332
|
|
333
333
|
add_list 'update', %w[], 'Update td and related libraries for TreasureData toolbelt'
|
334
334
|
|
335
|
-
|
335
|
+
connector_guess_example_config = "
|
336
|
+
in:
|
337
|
+
type: s3
|
338
|
+
bucket: my-s3-bucket
|
339
|
+
endpoint: s3-us-west-1.amazonaws.com
|
340
|
+
path_prefix: path/prefix/to/import/
|
341
|
+
access_key_id: ABCXYZ123ABCXYZ123
|
342
|
+
secret_access_key: AbCxYz123aBcXyZ123
|
343
|
+
out:
|
344
|
+
mode: append"
|
345
|
+
add_list 'connector:guess', %w[config?], 'Run guess to generate connector config file', ["connector:guess config.yml -o td-bulkload.yml\n\nexample config.yml:#{connector_guess_example_config}"]
|
336
346
|
add_list 'connector:preview', %w[config], 'Show preview of connector execution', ['connector:preview td-bulkload.yml']
|
337
347
|
|
338
348
|
add_list 'connector:issue', %w[config], 'Run one time connector execution', ['connector:issue td-bulkload.yml']
|
data/lib/td/command/table.rb
CHANGED
@@ -18,9 +18,9 @@ module Command
|
|
18
18
|
primary_key = nil
|
19
19
|
primary_key_type = nil
|
20
20
|
|
21
|
-
op.on('-T', '--type TYPE', 'set table type (log
|
22
|
-
unless
|
23
|
-
raise "Unknown table type #{s.dump}. Supported types: log
|
21
|
+
op.on('-T', '--type TYPE', 'set table type (log)') {|s|
|
22
|
+
unless s == 'log'
|
23
|
+
raise "Unknown table type #{s.dump}. Supported types: log"
|
24
24
|
end
|
25
25
|
type = s.to_sym
|
26
26
|
}
|
@@ -49,19 +49,10 @@ module Command
|
|
49
49
|
$stderr.puts " For a list of all reserved keywords, see our FAQ: http://docs.treasure-data.com/articles/faq"
|
50
50
|
end
|
51
51
|
|
52
|
-
if type == :item && (primary_key.nil? || primary_key_type.nil?)
|
53
|
-
$stderr.puts "for TYPE 'item', the primary-key is required"
|
54
|
-
exit 1
|
55
|
-
end
|
56
|
-
|
57
52
|
client = get_client
|
58
53
|
|
59
54
|
begin
|
60
|
-
|
61
|
-
client.create_item_table(db_name, table_name, primary_key, primary_key_type)
|
62
|
-
else
|
63
|
-
client.create_log_table(db_name, table_name)
|
64
|
-
end
|
55
|
+
client.create_log_table(db_name, table_name)
|
65
56
|
rescue NotFoundError
|
66
57
|
cmd_debug_error $!
|
67
58
|
$stderr.puts "Database '#{db_name}' does not exist."
|
@@ -144,10 +135,6 @@ module Command
|
|
144
135
|
databases = client.databases
|
145
136
|
end
|
146
137
|
|
147
|
-
has_item = databases.select {|db|
|
148
|
-
db.permission != :import_only ? (db.tables.select {|table| table.type == :item}.length > 0) : false
|
149
|
-
}.length > 0
|
150
|
-
|
151
138
|
# ref. https://github.com/treasure-data/td/issues/26
|
152
139
|
should_number_format = [nil, "table"].include?(op.render_format)
|
153
140
|
rows = []
|
@@ -168,9 +155,7 @@ module Command
|
|
168
155
|
'Last log timestamp' => table.last_log_timestamp ? table.last_log_timestamp.localtime : nil,
|
169
156
|
:Schema => pschema
|
170
157
|
}
|
171
|
-
|
172
|
-
new_row['Primary key'] = "#{table.primary_key}:#{table.primary_key_type}"
|
173
|
-
end
|
158
|
+
|
174
159
|
rows << new_row
|
175
160
|
}
|
176
161
|
rescue APIError => e
|
@@ -185,12 +170,7 @@ module Command
|
|
185
170
|
[map[:Database], map[:Type].size, map[:Table]]
|
186
171
|
}
|
187
172
|
|
188
|
-
fields = []
|
189
|
-
if has_item
|
190
|
-
fields = [:Database, :Table, :Type, :Count, :Size, 'Last import', 'Last log timestamp', 'Primary key', :Schema]
|
191
|
-
else
|
192
|
-
fields = [:Database, :Table, :Type, :Count, :Size, 'Last import', 'Last log timestamp', :Schema]
|
193
|
-
end
|
173
|
+
fields = [:Database, :Table, :Type, :Count, :Size, 'Last import', 'Last log timestamp', :Schema]
|
194
174
|
$stdout.puts cmd_render_table(rows, :fields => fields, :max_width => 500, :render_format => op.render_format)
|
195
175
|
|
196
176
|
if rows.empty?
|
@@ -235,7 +215,6 @@ module Command
|
|
235
215
|
$stdout.puts "Type : #{table.type}"
|
236
216
|
$stdout.puts "Count : #{table.count}"
|
237
217
|
# p table.methods.each {|m| $stdout.puts m}
|
238
|
-
$stdout.puts "Primary key : #{table.primary_key}:#{table.primary_key_type}" if table.type == :item
|
239
218
|
$stdout.puts "Schema : ("
|
240
219
|
table.schema.fields.each {|f|
|
241
220
|
$stdout.puts " #{f.name}:#{f.type}"
|
@@ -244,27 +223,9 @@ module Command
|
|
244
223
|
end
|
245
224
|
|
246
225
|
def table_tail(op)
|
247
|
-
from = nil
|
248
|
-
to = nil
|
249
226
|
count = 10
|
250
227
|
pretty = nil
|
251
228
|
|
252
|
-
op.on('-t', '--to TIME', 'end time of logs to get') {|s|
|
253
|
-
if s.to_i.to_s == s
|
254
|
-
to = s.to_i
|
255
|
-
else
|
256
|
-
require 'time'
|
257
|
-
to = Time.parse(s).to_i
|
258
|
-
end
|
259
|
-
}
|
260
|
-
op.on('-f', '--from TIME', 'start time of logs to get') {|s|
|
261
|
-
if s.to_i.to_s == s
|
262
|
-
from = s.to_i
|
263
|
-
else
|
264
|
-
require 'time'
|
265
|
-
from = Time.parse(s).to_i
|
266
|
-
end
|
267
|
-
}
|
268
229
|
op.on('-n', '--count N', 'number of logs to get', Integer) {|i|
|
269
230
|
count = i
|
270
231
|
}
|
@@ -278,7 +239,7 @@ module Command
|
|
278
239
|
|
279
240
|
table = get_table(client, db_name, table_name)
|
280
241
|
|
281
|
-
rows = table.tail(count
|
242
|
+
rows = table.tail(count)
|
282
243
|
|
283
244
|
require 'json'
|
284
245
|
if pretty
|
data/lib/td/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -8,13 +8,19 @@ if ENV['SIMPLE_COV']
|
|
8
8
|
# SimpleCov
|
9
9
|
# https://github.com/colszowka/simplecov
|
10
10
|
require 'simplecov'
|
11
|
-
SimpleCov.start do
|
11
|
+
SimpleCov.start do
|
12
12
|
add_filter 'spec/'
|
13
13
|
add_filter 'pkg/'
|
14
14
|
add_filter 'vendor/'
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
# XXX skip coverage setting if run appveyor. Because, fail to push coveralls in appveyor.
|
19
|
+
unless ENV['APPVEYOR']
|
20
|
+
require 'coveralls'
|
21
|
+
Coveralls.wear!('rails')
|
22
|
+
end
|
23
|
+
|
18
24
|
require 'td/command/runner'
|
19
25
|
|
20
26
|
def execute_td(command_line)
|
@@ -6,6 +6,10 @@ require 'td/command/connector'
|
|
6
6
|
module TreasureData::Command
|
7
7
|
describe 'connector commands' do
|
8
8
|
describe '#connector_preview' do
|
9
|
+
let :command do
|
10
|
+
Class.new { include TreasureData::Command }.new
|
11
|
+
end
|
12
|
+
|
9
13
|
subject do
|
10
14
|
backup = $stdout.dup
|
11
15
|
buf = StringIO.new
|
@@ -13,7 +17,8 @@ module TreasureData::Command
|
|
13
17
|
begin
|
14
18
|
$stdout = buf
|
15
19
|
|
16
|
-
|
20
|
+
op = List::CommandParser.new("connector:preview", ["config"], [], nil, [File.join("spec", "td", "fixture", "bulk_load.yml")], true)
|
21
|
+
command.connector_preview(op)
|
17
22
|
|
18
23
|
buf.string
|
19
24
|
ensure
|
@@ -21,10 +26,6 @@ module TreasureData::Command
|
|
21
26
|
end
|
22
27
|
end
|
23
28
|
|
24
|
-
let(:tempfile) do
|
25
|
-
File.join("spec", "td", "fixture", "bulk_load.yml")
|
26
|
-
end
|
27
|
-
|
28
29
|
let(:preview_result) do
|
29
30
|
{
|
30
31
|
"schema" => [
|
@@ -42,7 +43,8 @@ module TreasureData::Command
|
|
42
43
|
end
|
43
44
|
|
44
45
|
before do
|
45
|
-
|
46
|
+
client = double(:client, bulk_load_preview: preview_result)
|
47
|
+
command.stub(:get_client).and_return(client)
|
46
48
|
end
|
47
49
|
|
48
50
|
it 'should include too_long_column_name without truncated' do
|
data/spec/td/command/job_spec.rb
CHANGED
@@ -13,7 +13,7 @@ module TreasureData::Command
|
|
13
13
|
end
|
14
14
|
|
15
15
|
describe 'write_result' do
|
16
|
-
let(:file) { Tempfile.new("job_spec") }
|
16
|
+
let(:file) { Tempfile.new("job_spec").tap {|s| s.close } }
|
17
17
|
|
18
18
|
let :job do
|
19
19
|
job = TreasureData::Job.new(nil, 12345, 'hive', 'select * from employee')
|
@@ -395,6 +395,14 @@ ACTUAL
|
|
395
395
|
[multibyte_string, 2.0, {multibyte_string => multibyte_string}]
|
396
396
|
end
|
397
397
|
|
398
|
+
let(:line_separator) {
|
399
|
+
if RUBY_PLATFORM =~ /mswin32|mingw32/
|
400
|
+
"\r\n"
|
401
|
+
else
|
402
|
+
"\n"
|
403
|
+
end
|
404
|
+
}
|
405
|
+
|
398
406
|
let :job do
|
399
407
|
row = multibyte_row
|
400
408
|
job = TreasureData::Job.new(nil, 12345, 'hive', 'select * from employee')
|
@@ -414,24 +422,24 @@ ACTUAL
|
|
414
422
|
|
415
423
|
it 'supports json output' do
|
416
424
|
row = multibyte_row
|
417
|
-
file = Tempfile.new("job_spec")
|
425
|
+
file = Tempfile.new("job_spec").tap {|s| s.close }
|
418
426
|
command.send(:show_result, job, file, nil, 'json')
|
419
|
-
File.read(file.path).should == '[' + [row, row].map { |e| Yajl.dump(e) }.join(",\n") + ']'
|
427
|
+
File.read(file.path, encoding: 'UTF-8').should == '[' + [row, row].map { |e| Yajl.dump(e) }.join(",\n") + ']'
|
420
428
|
end
|
421
429
|
|
422
430
|
it 'supports csv output' do
|
423
431
|
row = multibyte_row.map { |e| dump_column(e) }
|
424
|
-
file = Tempfile.new("job_spec")
|
432
|
+
file = Tempfile.new("job_spec").tap {|s| s.close }
|
425
433
|
command.send(:show_result, job, file, nil, 'csv')
|
426
|
-
File.binread(file.path).should == [row, row].map { |e| CSV.generate_line(e) }.join
|
434
|
+
File.binread(file.path).should == [row, row].map { |e| CSV.generate_line(e, :row_sep => line_separator) }.join
|
427
435
|
File.open(file.path, 'r:Windows-31J').read.encode('UTF-8').split.first.should == 'メール,2.0,"{""メール"":""メール""}"'
|
428
436
|
end
|
429
437
|
|
430
438
|
it 'supports tsv output' do
|
431
439
|
row = multibyte_row.map { |e| dump_column(e) }
|
432
|
-
file = Tempfile.new("job_spec")
|
440
|
+
file = Tempfile.new("job_spec").tap {|s| s.close }
|
433
441
|
command.send(:show_result, job, file, nil, 'tsv')
|
434
|
-
File.binread(file.path).should == [row, row].map { |e| e.join("\t") +
|
442
|
+
File.binread(file.path).should == [row, row].map { |e| e.join("\t") + line_separator }.join
|
435
443
|
File.open(file.path, 'r:Windows-31J').read.encode('UTF-8').split("\n").first.should == "メール\t2.0\t{\"メール\":\"メール\"}"
|
436
444
|
end
|
437
445
|
end
|
data/spec/td/updater_spec.rb
CHANGED
@@ -8,34 +8,42 @@ require 'logger'
|
|
8
8
|
|
9
9
|
module TreasureData::Updater
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
%w(x86_64-darwin14 i386-mingw32).each do |platform|
|
12
|
+
describe "RUBY_PLATFORM is '#{platform}'" do
|
13
|
+
before do
|
14
|
+
stub_const('RUBY_PLATFORM', platform)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'without the TD_TOOLBELT_UPDATE_ROOT environment variable defined' do
|
18
|
+
let :default_toolbelt_url do
|
19
|
+
"http://toolbelt.treasuredata.com"
|
20
|
+
end
|
15
21
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
22
|
+
describe 'endpoints methods' do
|
23
|
+
it 'use the default root path' do
|
24
|
+
TreasureData::Updater.endpoint_root.should == default_toolbelt_url
|
25
|
+
TreasureData::Updater.version_endpoint.should =~ Regexp.new(default_toolbelt_url)
|
26
|
+
TreasureData::Updater.update_package_endpoint.should =~ Regexp.new(default_toolbelt_url)
|
27
|
+
end
|
28
|
+
end
|
21
29
|
end
|
22
|
-
end
|
23
|
-
end
|
24
30
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
describe 'with the TD_TOOLBELT_UPDATE_ROOT environment variable defined' do
|
32
|
+
before do
|
33
|
+
ENV['TD_TOOLBELT_UPDATE_ROOT'] = 'https://0.0.0.0:5000/'
|
34
|
+
end
|
35
|
+
describe 'endpoints methods' do
|
36
|
+
it 'use the custom root path' do
|
37
|
+
TreasureData::Updater.endpoint_root.should == ENV['TD_TOOLBELT_UPDATE_ROOT']
|
38
|
+
TreasureData::Updater.version_endpoint.should =~ Regexp.new(ENV['TD_TOOLBELT_UPDATE_ROOT'])
|
39
|
+
TreasureData::Updater.update_package_endpoint.should =~ Regexp.new(ENV['TD_TOOLBELT_UPDATE_ROOT'])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
after do
|
43
|
+
ENV.delete 'TD_TOOLBELT_UPDATE_ROOT'
|
44
|
+
end
|
34
45
|
end
|
35
46
|
end
|
36
|
-
after do
|
37
|
-
ENV.delete 'TD_TOOLBELT_UPDATE_ROOT'
|
38
|
-
end
|
39
47
|
end
|
40
48
|
|
41
49
|
describe 'with a proxy' do
|
data/td.gemspec
CHANGED
@@ -21,10 +21,12 @@ Gem::Specification.new do |gem|
|
|
21
21
|
gem.add_dependency "yajl-ruby", "~> 1.1"
|
22
22
|
gem.add_dependency "hirb", ">= 0.4.5"
|
23
23
|
gem.add_dependency "parallel", "~> 0.6.1"
|
24
|
-
gem.add_dependency "td-client", "~> 0.8.
|
24
|
+
gem.add_dependency "td-client", "~> 0.8.71"
|
25
25
|
gem.add_dependency "td-logger", "~> 0.3.21"
|
26
|
-
gem.add_dependency "rubyzip", "~>
|
26
|
+
gem.add_dependency "rubyzip", "~> 1.1.7"
|
27
|
+
gem.add_dependency "zip-zip", "~> 0.3"
|
27
28
|
gem.add_development_dependency "rake", "~> 0.9"
|
28
29
|
gem.add_development_dependency "rspec", "~> 2.11.0"
|
29
|
-
gem.add_development_dependency "simplecov", "~> 0.
|
30
|
+
gem.add_development_dependency "simplecov", "~> 0.10.0"
|
31
|
+
gem.add_development_dependency 'coveralls'
|
30
32
|
end
|
metadata
CHANGED
@@ -1,34 +1,32 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: td
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
5
|
-
prerelease:
|
4
|
+
version: 0.11.11
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Treasure Data, Inc.
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2015-
|
11
|
+
date: 2015-07-15 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: msgpack
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 0.4.4
|
22
|
-
- -
|
20
|
+
- - '!='
|
23
21
|
- !ruby/object:Gem::Version
|
24
22
|
version: 0.5.0
|
25
|
-
- -
|
23
|
+
- - '!='
|
26
24
|
- !ruby/object:Gem::Version
|
27
25
|
version: 0.5.1
|
28
|
-
- -
|
26
|
+
- - '!='
|
29
27
|
- !ruby/object:Gem::Version
|
30
28
|
version: 0.5.2
|
31
|
-
- -
|
29
|
+
- - '!='
|
32
30
|
- !ruby/object:Gem::Version
|
33
31
|
version: 0.5.3
|
34
32
|
- - <
|
@@ -37,21 +35,20 @@ dependencies:
|
|
37
35
|
type: :runtime
|
38
36
|
prerelease: false
|
39
37
|
version_requirements: !ruby/object:Gem::Requirement
|
40
|
-
none: false
|
41
38
|
requirements:
|
42
|
-
- -
|
39
|
+
- - '>='
|
43
40
|
- !ruby/object:Gem::Version
|
44
41
|
version: 0.4.4
|
45
|
-
- -
|
42
|
+
- - '!='
|
46
43
|
- !ruby/object:Gem::Version
|
47
44
|
version: 0.5.0
|
48
|
-
- -
|
45
|
+
- - '!='
|
49
46
|
- !ruby/object:Gem::Version
|
50
47
|
version: 0.5.1
|
51
|
-
- -
|
48
|
+
- - '!='
|
52
49
|
- !ruby/object:Gem::Version
|
53
50
|
version: 0.5.2
|
54
|
-
- -
|
51
|
+
- - '!='
|
55
52
|
- !ruby/object:Gem::Version
|
56
53
|
version: 0.5.3
|
57
54
|
- - <
|
@@ -60,7 +57,6 @@ dependencies:
|
|
60
57
|
- !ruby/object:Gem::Dependency
|
61
58
|
name: yajl-ruby
|
62
59
|
requirement: !ruby/object:Gem::Requirement
|
63
|
-
none: false
|
64
60
|
requirements:
|
65
61
|
- - ~>
|
66
62
|
- !ruby/object:Gem::Version
|
@@ -68,7 +64,6 @@ dependencies:
|
|
68
64
|
type: :runtime
|
69
65
|
prerelease: false
|
70
66
|
version_requirements: !ruby/object:Gem::Requirement
|
71
|
-
none: false
|
72
67
|
requirements:
|
73
68
|
- - ~>
|
74
69
|
- !ruby/object:Gem::Version
|
@@ -76,23 +71,20 @@ dependencies:
|
|
76
71
|
- !ruby/object:Gem::Dependency
|
77
72
|
name: hirb
|
78
73
|
requirement: !ruby/object:Gem::Requirement
|
79
|
-
none: false
|
80
74
|
requirements:
|
81
|
-
- -
|
75
|
+
- - '>='
|
82
76
|
- !ruby/object:Gem::Version
|
83
77
|
version: 0.4.5
|
84
78
|
type: :runtime
|
85
79
|
prerelease: false
|
86
80
|
version_requirements: !ruby/object:Gem::Requirement
|
87
|
-
none: false
|
88
81
|
requirements:
|
89
|
-
- -
|
82
|
+
- - '>='
|
90
83
|
- !ruby/object:Gem::Version
|
91
84
|
version: 0.4.5
|
92
85
|
- !ruby/object:Gem::Dependency
|
93
86
|
name: parallel
|
94
87
|
requirement: !ruby/object:Gem::Requirement
|
95
|
-
none: false
|
96
88
|
requirements:
|
97
89
|
- - ~>
|
98
90
|
- !ruby/object:Gem::Version
|
@@ -100,7 +92,6 @@ dependencies:
|
|
100
92
|
type: :runtime
|
101
93
|
prerelease: false
|
102
94
|
version_requirements: !ruby/object:Gem::Requirement
|
103
|
-
none: false
|
104
95
|
requirements:
|
105
96
|
- - ~>
|
106
97
|
- !ruby/object:Gem::Version
|
@@ -108,23 +99,20 @@ dependencies:
|
|
108
99
|
- !ruby/object:Gem::Dependency
|
109
100
|
name: td-client
|
110
101
|
requirement: !ruby/object:Gem::Requirement
|
111
|
-
none: false
|
112
102
|
requirements:
|
113
103
|
- - ~>
|
114
104
|
- !ruby/object:Gem::Version
|
115
|
-
version: 0.8.
|
105
|
+
version: 0.8.71
|
116
106
|
type: :runtime
|
117
107
|
prerelease: false
|
118
108
|
version_requirements: !ruby/object:Gem::Requirement
|
119
|
-
none: false
|
120
109
|
requirements:
|
121
110
|
- - ~>
|
122
111
|
- !ruby/object:Gem::Version
|
123
|
-
version: 0.8.
|
112
|
+
version: 0.8.71
|
124
113
|
- !ruby/object:Gem::Dependency
|
125
114
|
name: td-logger
|
126
115
|
requirement: !ruby/object:Gem::Requirement
|
127
|
-
none: false
|
128
116
|
requirements:
|
129
117
|
- - ~>
|
130
118
|
- !ruby/object:Gem::Version
|
@@ -132,7 +120,6 @@ dependencies:
|
|
132
120
|
type: :runtime
|
133
121
|
prerelease: false
|
134
122
|
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
none: false
|
136
123
|
requirements:
|
137
124
|
- - ~>
|
138
125
|
- !ruby/object:Gem::Version
|
@@ -140,23 +127,34 @@ dependencies:
|
|
140
127
|
- !ruby/object:Gem::Dependency
|
141
128
|
name: rubyzip
|
142
129
|
requirement: !ruby/object:Gem::Requirement
|
143
|
-
none: false
|
144
130
|
requirements:
|
145
131
|
- - ~>
|
146
132
|
- !ruby/object:Gem::Version
|
147
|
-
version:
|
133
|
+
version: 1.1.7
|
148
134
|
type: :runtime
|
149
135
|
prerelease: false
|
150
136
|
version_requirements: !ruby/object:Gem::Requirement
|
151
|
-
none: false
|
152
137
|
requirements:
|
153
138
|
- - ~>
|
154
139
|
- !ruby/object:Gem::Version
|
155
|
-
version:
|
140
|
+
version: 1.1.7
|
141
|
+
- !ruby/object:Gem::Dependency
|
142
|
+
name: zip-zip
|
143
|
+
requirement: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ~>
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0.3'
|
148
|
+
type: :runtime
|
149
|
+
prerelease: false
|
150
|
+
version_requirements: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ~>
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0.3'
|
156
155
|
- !ruby/object:Gem::Dependency
|
157
156
|
name: rake
|
158
157
|
requirement: !ruby/object:Gem::Requirement
|
159
|
-
none: false
|
160
158
|
requirements:
|
161
159
|
- - ~>
|
162
160
|
- !ruby/object:Gem::Version
|
@@ -164,7 +162,6 @@ dependencies:
|
|
164
162
|
type: :development
|
165
163
|
prerelease: false
|
166
164
|
version_requirements: !ruby/object:Gem::Requirement
|
167
|
-
none: false
|
168
165
|
requirements:
|
169
166
|
- - ~>
|
170
167
|
- !ruby/object:Gem::Version
|
@@ -172,7 +169,6 @@ dependencies:
|
|
172
169
|
- !ruby/object:Gem::Dependency
|
173
170
|
name: rspec
|
174
171
|
requirement: !ruby/object:Gem::Requirement
|
175
|
-
none: false
|
176
172
|
requirements:
|
177
173
|
- - ~>
|
178
174
|
- !ruby/object:Gem::Version
|
@@ -180,7 +176,6 @@ dependencies:
|
|
180
176
|
type: :development
|
181
177
|
prerelease: false
|
182
178
|
version_requirements: !ruby/object:Gem::Requirement
|
183
|
-
none: false
|
184
179
|
requirements:
|
185
180
|
- - ~>
|
186
181
|
- !ruby/object:Gem::Version
|
@@ -188,19 +183,31 @@ dependencies:
|
|
188
183
|
- !ruby/object:Gem::Dependency
|
189
184
|
name: simplecov
|
190
185
|
requirement: !ruby/object:Gem::Requirement
|
191
|
-
none: false
|
192
186
|
requirements:
|
193
187
|
- - ~>
|
194
188
|
- !ruby/object:Gem::Version
|
195
|
-
version: 0.
|
189
|
+
version: 0.10.0
|
196
190
|
type: :development
|
197
191
|
prerelease: false
|
198
192
|
version_requirements: !ruby/object:Gem::Requirement
|
199
|
-
none: false
|
200
193
|
requirements:
|
201
194
|
- - ~>
|
202
195
|
- !ruby/object:Gem::Version
|
203
|
-
version: 0.
|
196
|
+
version: 0.10.0
|
197
|
+
- !ruby/object:Gem::Dependency
|
198
|
+
name: coveralls
|
199
|
+
requirement: !ruby/object:Gem::Requirement
|
200
|
+
requirements:
|
201
|
+
- - '>='
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '0'
|
204
|
+
type: :development
|
205
|
+
prerelease: false
|
206
|
+
version_requirements: !ruby/object:Gem::Requirement
|
207
|
+
requirements:
|
208
|
+
- - '>='
|
209
|
+
- !ruby/object:Gem::Version
|
210
|
+
version: '0'
|
204
211
|
description: CLI to manage data on Treasure Data, the Hadoop-based cloud data warehousing
|
205
212
|
email: support@treasure-data.com
|
206
213
|
executables:
|
@@ -208,11 +215,14 @@ executables:
|
|
208
215
|
extensions: []
|
209
216
|
extra_rdoc_files: []
|
210
217
|
files:
|
218
|
+
- .coveralls.yml
|
211
219
|
- .gitignore
|
220
|
+
- .travis.yml
|
212
221
|
- ChangeLog
|
213
222
|
- Gemfile
|
214
223
|
- README.rdoc
|
215
224
|
- Rakefile
|
225
|
+
- appveyor.yml
|
216
226
|
- bin/td
|
217
227
|
- contrib/completion/_td
|
218
228
|
- contrib/completion/td-completion.bash
|
@@ -277,30 +287,26 @@ files:
|
|
277
287
|
- td.gemspec
|
278
288
|
homepage: http://treasure-data.com/
|
279
289
|
licenses: []
|
290
|
+
metadata: {}
|
280
291
|
post_install_message:
|
281
292
|
rdoc_options: []
|
282
293
|
require_paths:
|
283
294
|
- lib
|
284
295
|
required_ruby_version: !ruby/object:Gem::Requirement
|
285
|
-
none: false
|
286
296
|
requirements:
|
287
|
-
- -
|
297
|
+
- - '>='
|
288
298
|
- !ruby/object:Gem::Version
|
289
299
|
version: '1.9'
|
290
300
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
291
|
-
none: false
|
292
301
|
requirements:
|
293
|
-
- -
|
302
|
+
- - '>='
|
294
303
|
- !ruby/object:Gem::Version
|
295
304
|
version: '0'
|
296
|
-
segments:
|
297
|
-
- 0
|
298
|
-
hash: -1990136432195876879
|
299
305
|
requirements: []
|
300
306
|
rubyforge_project:
|
301
|
-
rubygems_version:
|
307
|
+
rubygems_version: 2.0.14
|
302
308
|
signing_key:
|
303
|
-
specification_version:
|
309
|
+
specification_version: 4
|
304
310
|
summary: CLI to manage data on Treasure Data, the Hadoop-based cloud data warehousing
|
305
311
|
test_files:
|
306
312
|
- spec/file_reader/filter_spec.rb
|