td 0.11.12 → 0.11.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 36266b9c823ecc10de37fafc29ed07458a50a728
4
- data.tar.gz: 92ec61eb2983e7b284565252729aaedadf1483f9
3
+ metadata.gz: 844dda6ec2ea3ce703d94332d12f07da0c8130c1
4
+ data.tar.gz: 2fe722894996e437589d8841b06dcf0d8da0534d
5
5
  SHA512:
6
- metadata.gz: 545c05fd90e3577b175d732742182fca1bdd02dd9bf58666213006e89c0033e6ded3410cd610cc4f503b67db1f6e0f630d75249f33cd4f1ab56c326f0106b380
7
- data.tar.gz: 92ff25f768e6a82dceb87fddb41e395624a2de9b0e8bd64160b584f709cf28bfaaa7790f8cd5bfc3fe2de7169cf3d7305d99024eaafc2afec7a2735d51eb70ae
6
+ metadata.gz: 467d5b84f145cb1a2e11926b8332018eed6734fab410bbae0271873b4481ea1755c2aea6475e5835cef7981fb3f18605e7a5b8fbe983f9a608fbd2ca447ae12c
7
+ data.tar.gz: c1fae992cf68fc41304fe1b8326e8d1782ca29ad0b6b52828bb75553f66df0b4aa85ebf33888a0516e04929bbcdd1a406abb6cd25f68b77a043741e1c79ccb3b
data/ChangeLog CHANGED
@@ -1,3 +1,8 @@
1
+ == 2015-07-29 version 0.11.13
2
+
3
+ * allow retry when `td query -w` fail show result.
4
+ * `connector:issue` create database and table if use `--auto-create-table`
5
+
1
6
  == 2015-07-27 version 0.11.12
2
7
 
3
8
  * query command support msgpack.gz format save
@@ -247,6 +247,30 @@ EOS
247
247
  table
248
248
  end
249
249
 
250
+ def create_database_and_table_if_not_exist(client, db_name, table_name)
251
+ # Merge with db_create and table_create after refactoring
252
+ API.validate_database_name(db_name)
253
+ begin
254
+ client.database(db_name)
255
+ rescue NotFoundError
256
+ begin
257
+ client.create_database(db_name)
258
+ $stderr.puts "Database '#{db_name}' is created."
259
+ rescue AlreadyExistsError
260
+ # do nothing
261
+ end
262
+ rescue ForbiddenError
263
+ # do nothing
264
+ end
265
+
266
+ API.validate_table_name(table_name)
267
+ begin
268
+ client.create_log_table(db_name, table_name)
269
+ $stderr.puts "Table '#{db_name}.#{table_name}' is created."
270
+ rescue AlreadyExistsError
271
+ end
272
+ end
273
+
250
274
  def ask_password(max=3, &block)
251
275
  3.times do
252
276
  begin
@@ -109,13 +109,18 @@ module Command
109
109
 
110
110
  def connector_issue(op)
111
111
  database = table = nil
112
- time_column = nil
113
- wait = exclude = false
112
+ time_column = nil
113
+ wait = exclude = false
114
+ auto_create = false
115
+
114
116
  op.on('--database DB_NAME', "destination database") { |s| database = s }
115
117
  op.on('--table TABLE_NAME', "destination table") { |s| table = s }
116
118
  op.on('--time-column COLUMN_NAME', "data partitioning key") { |s| time_column = s } # unnecessary but for backward compatibility
117
119
  op.on('-w', '--wait', 'wait for finishing the job', TrueClass) { |b| wait = b }
118
120
  op.on('-x', '--exclude', 'do not automatically retrieve the job result', TrueClass) { |b| exclude = b }
121
+ op.on('--auto-create-table', "Create table and database if doesn't exist", TrueClass) { |b|
122
+ auto_create = b
123
+ }
119
124
 
120
125
  config_file = op.cmd_parse
121
126
 
@@ -126,6 +131,11 @@ module Command
126
131
  (config['out'] ||= {})['time_column'] = time_column if time_column # TODO will not work once embulk implements multi-job
127
132
 
128
133
  client = get_client()
134
+
135
+ if auto_create
136
+ create_database_and_table_if_not_exist(client, database, table)
137
+ end
138
+
129
139
  job_id = client.bulk_load_issue(database, table, config: config)
130
140
 
131
141
  $stdout.puts "Job #{job_id} is queued."
@@ -142,11 +142,10 @@ module Command
142
142
 
143
143
  if wait
144
144
  wait_job(job, true)
145
- $stdout.puts "Status : #{job.status}"
145
+ $stdout.puts "Status : #{job.status}"
146
146
  if job.success? && !exclude
147
- $stdout.puts "Result :"
148
147
  begin
149
- show_result(job, output, limit, format, render_opts)
148
+ show_result_with_retry(job, output, limit, format, render_opts)
150
149
  rescue TreasureData::NotFoundError => e
151
150
  end
152
151
  end
@@ -372,28 +372,30 @@ module Command
372
372
  time_key = 'time'
373
373
  auto_create = false
374
374
 
375
+ import_params = {}
376
+
375
377
  op.on('--format FORMAT', "file format (default: #{format})") {|s|
376
- format = s
378
+ import_params[:format] = s
377
379
  }
378
380
 
379
381
  op.on('--apache', "same as --format apache; apache common log format") {
380
- format = 'apache'
382
+ import_params[:format] = 'apache'
381
383
  }
382
384
 
383
385
  op.on('--syslog', "same as --format syslog; syslog") {
384
- format = 'syslog'
386
+ import_params[:format] = 'syslog'
385
387
  }
386
388
 
387
389
  op.on('--msgpack', "same as --format msgpack; msgpack stream format") {
388
- format = 'msgpack'
390
+ import_params[:format] = 'msgpack'
389
391
  }
390
392
 
391
393
  op.on('--json', "same as --format json; LF-separated json format") {
392
- format = 'json'
394
+ import_params[:format] = 'json'
393
395
  }
394
396
 
395
397
  op.on('-t', '--time-key COL_NAME', "time key name for json and msgpack format (e.g. 'created_at')") {|s|
396
- time_key = s
398
+ import_params[:time_key] = s
397
399
  }
398
400
 
399
401
  op.on('--auto-create-table', "Create table and database if doesn't exist", TrueClass) { |b|
@@ -401,63 +403,51 @@ module Command
401
403
  }
402
404
 
403
405
  db_name, table_name, *paths = op.cmd_parse
406
+ import_params[:db_name] = db_name
407
+ import_params[:table_name] = table_name
408
+ import_params[:paths] = paths
404
409
 
405
410
  client = get_client
406
411
 
407
412
  if auto_create
408
- # Merge with db_create and table_create after refactoring
409
- API.validate_database_name(db_name)
410
- begin
411
- client.database(db_name)
412
- rescue NotFoundError
413
- begin
414
- client.create_database(db_name)
415
- $stderr.puts "Database '#{db_name}' is created."
416
- rescue AlreadyExistsError
417
- # do nothing
418
- end
419
- rescue ForbiddenError
420
- # do nothing
421
- end
422
-
423
- API.validate_table_name(table_name)
424
- begin
425
- client.create_log_table(db_name, table_name)
426
- $stderr.puts "Table '#{db_name}.#{table_name}' is created."
427
- rescue AlreadyExistsError
428
- end
413
+ create_database_and_table_if_not_exist(client, db_name, table_name)
429
414
  end
430
415
 
431
- case format
416
+ do_table_import(client, import_params)
417
+ end
418
+
419
+ private
420
+ def do_table_import(client, import_params)
421
+ case import_params[:format]
432
422
  when 'json', 'msgpack'
433
423
  #unless time_key
434
424
  # $stderr.puts "-t, --time-key COL_NAME (e.g. '-t created_at') parameter is required for #{format} format"
435
425
  # exit 1
436
426
  #end
437
- if format == 'json'
427
+ if import_params[:format] == 'json'
438
428
  require 'json'
439
429
  require 'time'
440
- parser = JsonParser.new(time_key)
430
+ parser = JsonParser.new(import_params[:time_key])
441
431
  else
442
- parser = MessagePackParser.new(time_key)
432
+ parser = MessagePackParser.new(import_params[:time_key])
443
433
  end
444
434
 
445
435
  else # apache, syslog
446
- regexp, names, time_format = IMPORT_TEMPLATES[format]
436
+ regexp, names, time_format = IMPORT_TEMPLATES[import_params[:format]]
447
437
  if !regexp || !names || !time_format
448
- $stderr.puts "Unknown format '#{format}'"
438
+ $stderr.puts "Unknown format '#{import_params[:format]}'"
449
439
  exit 1
450
440
  end
451
441
  parser = TextParser.new(names, regexp, time_format)
452
442
  end
453
443
 
454
444
  begin
455
- db = client.database(db_name)
445
+ db = client.database(import_params[:db_name])
456
446
  rescue ForbiddenError => e
457
447
  $stdout.puts "Warning: database and table validation skipped - #{e.message}"
458
448
  else
459
449
  begin
460
- table = db.table(table_name)
450
+ table = db.table(import_params[:table_name])
461
451
  rescue ForbiddenError => e
462
452
  $stdout.puts "Warning: table validation skipped - #{e.message}"
463
453
  end
@@ -466,7 +456,7 @@ module Command
466
456
  require 'zlib'
467
457
 
468
458
  begin
469
- files = paths.map {|path|
459
+ files = import_params[:paths].map {|path|
470
460
  if path == '-'
471
461
  $stdin
472
462
  elsif path =~ /\.gz$/
@@ -484,14 +474,13 @@ module Command
484
474
  require 'tempfile'
485
475
  #require 'thread'
486
476
 
487
- files.zip(paths).each {|file, path|
488
- import_log_file(file, path, client, db_name, table_name, parser)
477
+ files.zip(import_params[:paths]).each {|file, path|
478
+ import_log_file(file, path, client, import_params[:db_name], import_params[:table_name], parser)
489
479
  }
490
480
 
491
481
  $stdout.puts "done."
492
482
  end
493
483
 
494
- private
495
484
  def import_log_file(file, path, client, db_name, table_name, parser)
496
485
  $stdout.puts "importing #{path}..."
497
486
 
@@ -1,3 +1,3 @@
1
1
  module TreasureData
2
- TOOLBELT_VERSION = '0.11.12'
2
+ TOOLBELT_VERSION = '0.11.13'
3
3
  end
@@ -58,29 +58,75 @@ module TreasureData::Command
58
58
  Class.new { include TreasureData::Command }.new
59
59
  end
60
60
 
61
+ let(:stderr_io) do
62
+ StringIO.new
63
+ end
64
+
61
65
  subject do
62
66
  backup = $stdout.dup
67
+ stderr_backup = $stderr.dup
63
68
  buf = StringIO.new
64
69
 
65
70
  begin
66
71
  $stdout = buf
72
+ $stderr = stderr_io
67
73
 
68
- op = List::CommandParser.new("connector:issue", ["config"], ['database', 'table'], nil, [File.join("spec", "td", "fixture", "bulk_load.yml"), '--database', 'database', '--table', 'table'], true)
69
- command.connector_issue(op)
74
+ command.connector_issue(option)
70
75
 
71
76
  buf.string
72
77
  ensure
73
78
  $stdout = backup
79
+ $stderr = stderr_backup
74
80
  end
75
81
  end
76
82
 
77
- before do
78
- client = double(:client, bulk_load_issue: 1234)
79
- command.stub(:get_client).and_return(client)
83
+ describe 'queueing job' do
84
+ let(:option) {
85
+ List::CommandParser.new("connector:issue", ["config"], ['database', 'table'], nil, [File.join("spec", "td", "fixture", "bulk_load.yml"), '--database', 'database', '--table', 'table'], true)
86
+ }
87
+
88
+ before do
89
+ client = double(:client, bulk_load_issue: 1234)
90
+ command.stub(:get_client).and_return(client)
91
+ command.stub(:create_database_and_table_if_not_exist)
92
+ end
93
+
94
+ it 'should include too_long_column_name without truncated' do
95
+ expect(subject).to include "Job 1234 is queued."
96
+ end
80
97
  end
81
98
 
82
- it 'should include too_long_column_name without truncated' do
83
- expect(subject).to include "Job 1234 is queued."
99
+ describe 'distination table' do
100
+ let(:client) { double(:client, bulk_load_issue: 1234) }
101
+
102
+ before do
103
+ command.stub(:get_client).and_return(client)
104
+ client.stub(:database)
105
+ end
106
+
107
+ context 'set auto crate table option' do
108
+ let(:option) {
109
+ List::CommandParser.new("connector:issue", ["config"], ['database', 'table'], nil, [File.join("spec", "td", "fixture", "bulk_load.yml"), '--database', 'database', '--table', 'table', '--auto-create-table'], true)
110
+ }
111
+
112
+ it 'call create_database_and_table_if_not_exist' do
113
+ command.should_receive(:create_database_and_table_if_not_exist)
114
+
115
+ subject
116
+ end
117
+ end
118
+
119
+ context 'not set auto crate table option' do
120
+ let(:option) {
121
+ List::CommandParser.new("connector:issue", ["config"], ['database', 'table'], nil, [File.join("spec", "td", "fixture", "bulk_load.yml"), '--database', 'database', '--table', 'table'], true)
122
+ }
123
+
124
+ it 'call create_database_and_table_if_not_exist' do
125
+ command.should_not_receive(:create_database_and_table_if_not_exist)
126
+
127
+ subject
128
+ end
129
+ end
84
130
  end
85
131
  end
86
132
  end
@@ -179,5 +179,43 @@ module TreasureData::Command
179
179
  end
180
180
  end
181
181
  end
182
+
183
+ describe '#table_import' do
184
+ let(:db_name) { 'database' }
185
+ let(:table_name) { 'table' }
186
+ let(:client) { double('client') }
187
+ let(:command) { Class.new { include TreasureData::Command }.new }
188
+
189
+ describe 'auto create table' do
190
+ before do
191
+ command.stub(:get_client) { client }
192
+ command.stub(:do_table_import)
193
+ end
194
+
195
+ context 'set --auto-create-table' do
196
+ let(:option) {
197
+ List::CommandParser.new('table:import', [], %w(db_name table_name path), false, [db_name, table_name, 'path', '--auto-create-table'], true)
198
+ }
199
+
200
+ it 'create table' do
201
+ command.should_receive(:create_database_and_table_if_not_exist).with(client, db_name, table_name)
202
+
203
+ command.table_import(option)
204
+ end
205
+ end
206
+
207
+ context 'not set --auto-create-table' do
208
+ let(:option) {
209
+ List::CommandParser.new('table:import', [], %w(db_name table_name path), false, [db_name, table_name, 'path'], true)
210
+ }
211
+
212
+ it 'not create table' do
213
+ command.should_not_receive(:create_database_and_table_if_not_exist)
214
+
215
+ command.table_import(option)
216
+ end
217
+ end
218
+ end
219
+ end
182
220
  end
183
221
  end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
2
  require 'td/command/common'
3
+ require 'td/client/api_error'
3
4
 
4
5
  module TreasureData::Command
5
6
  describe 'humanize_bytesize' do
@@ -189,4 +190,105 @@ module TreasureData::Command
189
190
  end
190
191
  }
191
192
  end
193
+
194
+ describe '#create_database_and_table_if_not_exist' do
195
+ let(:command_class) { Class.new { include TreasureData::Command } }
196
+ let(:command) { command_class.new }
197
+ let(:client) { double(:client) }
198
+ let(:database_name) { 'database' }
199
+ let(:table_name) { 'table1' }
200
+
201
+ let(:stderr_io) { StringIO.new }
202
+
203
+ subject(:call_create_database_and_table_if_not_exist) {
204
+ stderr = $stderr.dup
205
+ begin
206
+ $stderr = stderr_io
207
+
208
+ command.__send__(:create_database_and_table_if_not_exist, client, database_name, table_name)
209
+ ensure
210
+ $stderr = stderr
211
+ end
212
+ }
213
+
214
+ describe 'create database' do
215
+ before do
216
+ client.stub(:create_log_table)
217
+ end
218
+
219
+ context 'client.database success' do
220
+ it 'not call client.create_database' do
221
+ client.should_receive(:database).with(database_name)
222
+ client.should_not_receive(:create_database)
223
+
224
+ call_create_database_and_table_if_not_exist
225
+ expect(stderr_io.string).not_to include "Database '#{database_name}'"
226
+ end
227
+ end
228
+
229
+ context 'client.database raise NotFoundError' do
230
+ before do
231
+ client.should_receive(:database).with(database_name).and_return { raise TreasureData::NotFoundError }
232
+ end
233
+
234
+ context 'craet_database success' do
235
+ it 'call client.create_database' do
236
+ client.should_receive(:create_database).with(database_name)
237
+
238
+ call_create_database_and_table_if_not_exist
239
+ expect(stderr_io.string).to include "Database '#{database_name}'"
240
+ end
241
+ end
242
+
243
+ context 'craet_database raise AlreadyExistsError' do
244
+ it 'resuce in method' do
245
+ client.should_receive(:create_database).with(database_name).and_return { raise TreasureData::AlreadyExistsError }
246
+
247
+ expect {
248
+ call_create_database_and_table_if_not_exist
249
+ }.not_to raise_error
250
+
251
+ expect(stderr_io.string).not_to include "Database '#{database_name}'"
252
+ end
253
+ end
254
+ end
255
+
256
+ context 'client.database raise ForbiddenError' do
257
+ it 'not call client.create_database' do
258
+ client.should_receive(:database).with(database_name).and_return { raise TreasureData::ForbiddenError }
259
+ client.should_not_receive(:create_database)
260
+
261
+ call_create_database_and_table_if_not_exist
262
+ expect(stderr_io.string).not_to include "Database '#{database_name}'"
263
+ end
264
+ end
265
+ end
266
+
267
+ describe 'create table' do
268
+ before do
269
+ client.stub(:database)
270
+ end
271
+
272
+ context 'create_log_table success' do
273
+ it 'show message' do
274
+ client.should_receive(:create_log_table).with(database_name, table_name)
275
+
276
+ call_create_database_and_table_if_not_exist
277
+ expect(stderr_io.string).to include "Table '#{database_name}.#{table_name}'"
278
+ end
279
+ end
280
+
281
+ context 'create_log_table raise AlreadyExistsError' do
282
+ it 'resuce in method' do
283
+ client.should_receive(:create_log_table).with(database_name, table_name).and_return { raise TreasureData::AlreadyExistsError }
284
+
285
+ expect {
286
+ call_create_database_and_table_if_not_exist
287
+ }.not_to raise_error
288
+
289
+ expect(stderr_io.string).not_to include "Table '#{database_name}.#{table_name}'"
290
+ end
291
+ end
292
+ end
293
+ end
192
294
  end
data/td.gemspec CHANGED
@@ -21,7 +21,7 @@ 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.72"
24
+ gem.add_dependency "td-client", "~> 0.8.73"
25
25
  gem.add_dependency "td-logger", "~> 0.3.21"
26
26
  gem.add_dependency "rubyzip", "~> 1.1.7"
27
27
  gem.add_dependency "zip-zip", "~> 0.3"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: td
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.12
4
+ version: 0.11.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Treasure Data, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-27 00:00:00.000000000 Z
11
+ date: 2015-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -102,14 +102,14 @@ dependencies:
102
102
  requirements:
103
103
  - - ~>
104
104
  - !ruby/object:Gem::Version
105
- version: 0.8.72
105
+ version: 0.8.73
106
106
  type: :runtime
107
107
  prerelease: false
108
108
  version_requirements: !ruby/object:Gem::Requirement
109
109
  requirements:
110
110
  - - ~>
111
111
  - !ruby/object:Gem::Version
112
- version: 0.8.72
112
+ version: 0.8.73
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: td-logger
115
115
  requirement: !ruby/object:Gem::Requirement