td 0.11.9 → 0.11.10

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,3 +1,16 @@
1
+ == 2015-05-19 version 0.11.10
2
+
3
+ * Updated 'td-client' gem dependency to 0.8.70. The new gem removed client
4
+ side validation for connector commands to allow additional plugin configs
5
+ we're going to add in the future.
6
+ * connector:guess dumps configuration file to stdout that is guessed by the
7
+ server to check the config file easier.
8
+ * connector:preview shows full column name (not truncated) in the table.
9
+ * add --pool-name option to job registration.
10
+ * add sched:result command to show job results for a saved query.
11
+ * save to temporary file while downloading job result in job:show.
12
+ * show job duration in job list.
13
+
1
14
  == 2015-04-17 version 0.11.9
2
15
 
3
16
  * add connector commands.
@@ -41,10 +41,10 @@ module Command
41
41
  end
42
42
  end
43
43
 
44
- puts "Enter your Treasure Data credentials."
44
+ $stdout.puts "Enter your Treasure Data credentials."
45
45
  unless user_name
46
46
  begin
47
- print "Email: "
47
+ $stdout.print "Email: "
48
48
  line = STDIN.gets || ""
49
49
  user_name = line.strip
50
50
  rescue Interrupt
@@ -62,14 +62,14 @@ module Command
62
62
 
63
63
  3.times do
64
64
  begin
65
- print "Password (typing will be hidden): "
65
+ $stdout.print "Password (typing will be hidden): "
66
66
  password = get_password
67
67
  rescue Interrupt
68
68
  $stderr.print "\ncanceled."
69
69
  exit 1
70
70
  ensure
71
71
  system "stty echo" # TODO termios
72
- print "\n"
72
+ $stdout.print "\n"
73
73
  end
74
74
 
75
75
  if password.empty?
@@ -91,7 +91,7 @@ module Command
91
91
  end
92
92
  return unless client
93
93
 
94
- puts "Authenticated successfully."
94
+ $stdout.puts "Authenticated successfully."
95
95
 
96
96
  conf ||= Config.new
97
97
  conf["account.user"] = user_name
@@ -14,7 +14,7 @@ module Command
14
14
  rows << {:Subject => ac.subject, :Action => ac.action, :Scope => ac.scope, :"Grant option" => ac.grant_option}
15
15
  }
16
16
 
17
- puts cmd_render_table(rows, :fields => [:Subject, :Action, :Scope, :"Grant option"])
17
+ $stdout.puts cmd_render_table(rows, :fields => [:Subject, :Action, :Scope, :"Grant option"])
18
18
 
19
19
  if rows.empty?
20
20
  $stderr.puts "There are no access controls."
@@ -4,7 +4,7 @@ module Command
4
4
 
5
5
  def apikey_show(op)
6
6
  if Config.apikey
7
- puts Config.apikey
7
+ $stdout.puts Config.apikey
8
8
  return
9
9
  end
10
10
 
@@ -20,7 +20,7 @@ module Command
20
20
  exit 1
21
21
  end
22
22
 
23
- puts conf['account.apikey']
23
+ $stdout.puts conf['account.apikey']
24
24
  end
25
25
 
26
26
  def apikey_set(op)
@@ -55,8 +55,8 @@ module Command
55
55
  conf["account.apikey"] = apikey
56
56
  conf.save
57
57
 
58
- puts "API key is set."
59
- puts "Use '#{$prog} db:create <db_name>' to create a database."
58
+ $stdout.puts "API key is set."
59
+ $stdout.puts "Use '#{$prog} db:create <db_name>' to create a database."
60
60
  end
61
61
 
62
62
  end
@@ -16,7 +16,7 @@ module Command
16
16
  rows << {:Name=>bi.name, :Table=>"#{bi.database}.#{bi.table}", :Status=>bi.status.to_s.capitalize, :Frozen=>bi.upload_frozen? ? 'Frozen' : '', :JobID=>bi.job_id, :"Valid Parts"=>bi.valid_parts, :"Error Parts"=>bi.error_parts, :"Valid Records"=>bi.valid_records, :"Error Records"=>bi.error_records}
17
17
  }
18
18
 
19
- puts cmd_render_table(rows, :fields => [:Name, :Table, :Status, :Frozen, :JobID, :"Valid Parts", :"Error Parts", :"Valid Records", :"Error Records"], :max_width=>200, :render_format => op.render_format)
19
+ $stdout.puts cmd_render_table(rows, :fields => [:Name, :Table, :Status, :Frozen, :JobID, :"Valid Parts", :"Error Parts", :"Valid Records", :"Error Records"], :max_width=>200, :render_format => op.render_format)
20
20
 
21
21
  if rows.empty?
22
22
  $stderr.puts "There are no bulk import sessions."
@@ -75,7 +75,7 @@ module Command
75
75
 
76
76
  list = client.list_bulk_import_parts(name)
77
77
  list.each {|name|
78
- puts " #{name}"
78
+ $stdout.puts " #{name}"
79
79
  }
80
80
  end
81
81
 
@@ -100,6 +100,7 @@ module Command
100
100
  part_prefix = ""
101
101
  auto_perform = false
102
102
  parallel = 2
103
+ pool_name = nil
103
104
 
104
105
  op.on('-P', '--prefix NAME', 'add prefix to parts name') {|s|
105
106
  part_prefix = s
@@ -113,6 +114,9 @@ module Command
113
114
  op.on('--parallel NUM', 'perform uploading in parallel (default: 2; max 8)', Integer) {|i|
114
115
  parallel = i
115
116
  }
117
+ op.on('-O', '--pool-name NAME', 'specify resource pool by name') {|s|
118
+ pool_name = s
119
+ }
116
120
 
117
121
  name, *files = op.cmd_parse
118
122
 
@@ -176,8 +180,10 @@ module Command
176
180
  $stderr.puts "done."
177
181
 
178
182
  if auto_perform
183
+ opts = {}
184
+ opts['pool_name'] = pool_name if pool_name
179
185
  client = get_client
180
- job = client.perform_bulk_import(name)
186
+ job = client.perform_bulk_import(name, opts)
181
187
 
182
188
  $stderr.puts "Job #{job.job_id} is queued."
183
189
  $stderr.puts "Use '#{$prog} " + Config.cl_options_string + "job:show [-w] #{job.job_id}' to show the status."
@@ -185,7 +191,7 @@ module Command
185
191
  end
186
192
 
187
193
  def bulk_import_upload_parts2(op)
188
- puts "This command is moved to 'td import:upload' since 0.10.85."
194
+ $stdout.puts "This command is moved to 'td import:upload' since 0.10.85."
189
195
  end
190
196
 
191
197
  # obsoleted
@@ -223,6 +229,7 @@ module Command
223
229
  def bulk_import_perform(op)
224
230
  wait = false
225
231
  force = false
232
+ pool_name = nil
226
233
 
227
234
  op.on('-w', '--wait', 'wait for finishing the job', TrueClass) {|b|
228
235
  wait = b
@@ -230,6 +237,9 @@ module Command
230
237
  op.on('-f', '--force', 'force start performing', TrueClass) {|b|
231
238
  force = b
232
239
  }
240
+ op.on('-O', '--pool-name NAME', 'specify resource pool by name') {|s|
241
+ pool_name = s
242
+ }
233
243
 
234
244
  name = op.cmd_parse
235
245
 
@@ -252,7 +262,9 @@ module Command
252
262
  end
253
263
  end
254
264
 
255
- job = client.perform_bulk_import(name)
265
+ opts = {}
266
+ opts['pool_name'] = pool_name if pool_name
267
+ job = client.perform_bulk_import(name, opts)
256
268
 
257
269
  $stderr.puts "Job #{job.job_id} is queued."
258
270
  $stderr.puts "Use '#{$prog} " + Config.cl_options_string + "job:show [-w] #{job.job_id}' to show the status."
@@ -338,7 +350,7 @@ module Command
338
350
 
339
351
  require 'yajl'
340
352
  client.bulk_import_error_records(name) {|r|
341
- puts Yajl.dump(r)
353
+ $stdout.puts Yajl.dump(r)
342
354
  }
343
355
  end
344
356
 
@@ -459,7 +471,7 @@ module Command
459
471
  end
460
472
 
461
473
  def bulk_import_prepare_parts2(op)
462
- puts "This command is moved to 'td import:prepare' since 0.10.85."
474
+ $stdout.puts "This command is moved to 'td import:prepare' since 0.10.85."
463
475
  end
464
476
 
465
477
  private
@@ -2,6 +2,8 @@ require 'td/version'
2
2
 
3
3
  module TreasureData
4
4
 
5
+ require "td/config"
6
+
5
7
  autoload :API, 'td/client/api'
6
8
  autoload :Client, 'td/client'
7
9
  autoload :Database, 'td/client'
@@ -249,7 +251,7 @@ EOS
249
251
  3.times do
250
252
  begin
251
253
  system "stty -echo" # TODO termios
252
- print "Password (typing will be hidden): "
254
+ $stdout.print "Password (typing will be hidden): "
253
255
  password = STDIN.gets || ""
254
256
  password = password[0..-2] # strip \n
255
257
  rescue Interrupt
@@ -257,7 +259,7 @@ EOS
257
259
  exit 1
258
260
  ensure
259
261
  system "stty echo" # TODO termios
260
- print "\n"
262
+ $stdout.print "\n"
261
263
  end
262
264
 
263
265
  if password.empty?
@@ -328,7 +330,7 @@ EOS
328
330
  class DownloadProgressIndicator
329
331
  def initialize(msg)
330
332
  @base_msg = msg
331
- print @base_msg + " " * 10
333
+ $stdout.print @base_msg + " " * 10
332
334
  end
333
335
  end
334
336
 
@@ -343,8 +345,8 @@ EOS
343
345
  def update
344
346
  if (time = Time.now.to_i) - @last_time >= @periodicity
345
347
  msg = "\r#{@base_msg}: #{Command.humanize_elapsed_time(@start_time, time)} elapsed"
346
- print "\r" + " " * (msg.length + 10)
347
- print msg
348
+ $stdout.print "\r" + " " * (msg.length + 10)
349
+ $stdout.print msg
348
350
  @last_time = time
349
351
  true
350
352
  else
@@ -353,7 +355,7 @@ EOS
353
355
  end
354
356
 
355
357
  def finish
356
- puts "\r#{@base_msg}...done" + " " * 20
358
+ $stdout.puts "\r#{@base_msg}...done" + " " * 20
357
359
  end
358
360
  end
359
361
 
@@ -378,15 +380,15 @@ EOS
378
380
  def update(curr_size)
379
381
  if @size.nil? || @size == 0
380
382
  msg = "\r#{@base_msg}: #{Command.humanize_bytesize(curr_size)}"
381
- print msg
383
+ $stdout.print msg
382
384
  true
383
385
  else
384
386
  ratio = (curr_size.to_f * 100 / @size).round(1)
385
387
  if ratio >= (@last_perc_step + @perc_step) &&
386
388
  (!@min_periodicity || (time = Time.now.to_i) - @last_time >= @min_periodicity)
387
389
  msg = "\r#{@base_msg}: #{Command.humanize_bytesize(curr_size)} / #{ratio}%"
388
- print "\r" + " " * (msg.length + 10)
389
- print msg
390
+ $stdout.print "\r" + " " * (msg.length + 10)
391
+ $stdout.print msg
390
392
  @last_perc_step = ratio
391
393
  @last_time = time
392
394
  true
@@ -397,7 +399,7 @@ EOS
397
399
  end
398
400
 
399
401
  def finish
400
- print "\r#{@base_msg}...done" + " " * 20
402
+ $stdout.print "\r#{@base_msg}...done" + " " * 20
401
403
  end
402
404
  end
403
405
 
@@ -40,7 +40,7 @@ module Command
40
40
  bucket = path_components.shift.sub(/\//, '')
41
41
  path_prefix = path_components.join.sub(/\//, '')
42
42
 
43
- job = API::BulkLoad::BulkLoad.from_hash(
43
+ job = {
44
44
  :config => {
45
45
  :type => type,
46
46
  :access_key_id => id,
@@ -49,7 +49,7 @@ module Command
49
49
  :bucket => bucket,
50
50
  :path_prefix => path_prefix,
51
51
  }
52
- ).validate
52
+ }
53
53
  end
54
54
 
55
55
  client = get_client
@@ -57,16 +57,20 @@ module Command
57
57
 
58
58
  create_bulkload_job_file_backup(out)
59
59
  if /\.json\z/ =~ out
60
- config_str = JSON.pretty_generate(job.to_h)
60
+ config_str = JSON.pretty_generate(job)
61
61
  else
62
- config_str = YAML.dump(job.to_h)
62
+ config_str = YAML.dump(job)
63
63
  end
64
64
  File.open(out, 'w') do |f|
65
65
  f << config_str
66
66
  end
67
67
 
68
- puts "Created #{out} file."
69
- puts "Use '#{$prog} " + Config.cl_options_string + "connector:preview #{out}' to see bulk load preview."
68
+ $stdout.puts "Guessed configuration:"
69
+ $stdout.puts
70
+ $stdout.puts config_str
71
+ $stdout.puts
72
+ $stdout.puts "Created #{out} file."
73
+ $stdout.puts "Use '#{$prog} " + Config.cl_options_string + "connector:preview #{out}' to see bulk load preview."
70
74
  end
71
75
 
72
76
  def connector_preview(op)
@@ -76,23 +80,23 @@ module Command
76
80
  client = get_client()
77
81
  preview = client.bulk_load_preview(job)
78
82
 
79
- cols = preview.schema.sort_by { |col|
83
+ cols = preview['schema'].sort_by { |col|
80
84
  col['index']
81
85
  }
82
86
  fields = cols.map { |col| col['name'] + ':' + col['type'] }
83
87
  types = cols.map { |col| col['type'] }
84
- rows = preview.records.map { |row|
88
+ rows = preview['records'].map { |row|
85
89
  cols = {}
86
90
  row.each_with_index do |col, idx|
87
91
  cols[fields[idx]] = col.inspect
88
92
  end
89
93
  cols
90
- }
94
+ }
91
95
 
92
- puts cmd_render_table(rows, :fields => fields, :render_format => op.render_format)
96
+ $stdout.puts cmd_render_table(rows, :fields => fields, :render_format => op.render_format, :resize => false)
93
97
 
94
- puts "Update #{config_file} and use '#{$prog} " + Config.cl_options_string + "connector:preview #{config_file}' to preview again."
95
- puts "Use '#{$prog} " + Config.cl_options_string + "connector:issue #{config_file}' to run Server-side bulk load."
98
+ $stdout.puts "Update #{config_file} and use '#{$prog} " + Config.cl_options_string + "connector:preview #{config_file}' to preview again."
99
+ $stdout.puts "Use '#{$prog} " + Config.cl_options_string + "connector:issue #{config_file}' to run Server-side bulk load."
96
100
  end
97
101
 
98
102
  def connector_issue(op)
@@ -116,8 +120,8 @@ module Command
116
120
  client = get_client()
117
121
  job_id = client.bulk_load_issue(database, table, job)
118
122
 
119
- puts "Job #{job_id} is queued."
120
- puts "Use '#{$prog} " + Config.cl_options_string + "job:show #{job_id}' to show the status."
123
+ $stdout.puts "Job #{job_id} is queued."
124
+ $stdout.puts "Use '#{$prog} " + Config.cl_options_string + "job:show #{job_id}' to show the status."
121
125
 
122
126
  if wait
123
127
  wait_connector_job(client, job_id, exclude)
@@ -135,10 +139,10 @@ module Command
135
139
  rows = client.bulk_load_list().sort_by { |e|
136
140
  e['name']
137
141
  }.map { |e|
138
- Hash[fields.zip(e.to_h.values_at(*keys))]
142
+ Hash[fields.zip(e.values_at(*keys))]
139
143
  }
140
144
 
141
- puts cmd_render_table(rows, :fields => fields, :render_format => op.render_format)
145
+ $stdout.puts cmd_render_table(rows, :fields => fields, :render_format => op.render_format)
142
146
  end
143
147
 
144
148
  def connector_create(op)
@@ -195,8 +199,8 @@ module Command
195
199
 
196
200
  client = get_client()
197
201
  session = client.bulk_load_delete(name)
198
- puts 'Deleted session'
199
- puts '--'
202
+ $stdout.puts 'Deleted session'
203
+ $stdout.puts '--'
200
204
  dump_connector_session(session)
201
205
  end
202
206
 
@@ -219,7 +223,7 @@ module Command
219
223
  :Duration => (e.end_at.nil? ? Time.now.to_i : e.end_at) - e.start_at,
220
224
  }
221
225
  }
222
- puts cmd_render_table(rows, :fields => fields, :render_format => op.render_format)
226
+ $stdout.puts cmd_render_table(rows, :fields => fields, :render_format => op.render_format)
223
227
  end
224
228
 
225
229
  def connector_run(op)
@@ -231,8 +235,8 @@ module Command
231
235
 
232
236
  client = get_client()
233
237
  job_id = client.bulk_load_run(name)
234
- puts "Job #{job_id} is queued."
235
- puts "Use '#{$prog} " + Config.cl_options_string + "job:show #{job_id}' to show the status."
238
+ $stdout.puts "Job #{job_id} is queued."
239
+ $stdout.puts "Use '#{$prog} " + Config.cl_options_string + "job:show #{job_id}' to show the status."
236
240
 
237
241
  if wait
238
242
  wait_connector_job(client, job_id, exclude)
@@ -263,7 +267,7 @@ private
263
267
  if file_type(config_str) == :yaml
264
268
  config_str = JSON.pretty_generate(YAML.load(config_str))
265
269
  end
266
- API::BulkLoad::BulkLoad.from_json(config_str)
270
+ JSON.load(config_str)
267
271
  end
268
272
 
269
273
  def create_bulkload_job_file_backup(out)
@@ -279,20 +283,20 @@ private
279
283
  end
280
284
 
281
285
  def dump_connector_session(session)
282
- puts "Name : #{session.name}"
283
- puts "Cron : #{session.cron}"
284
- puts "Timezone : #{session.timezone}"
285
- puts "Delay : #{session.delay}"
286
- puts "Database : #{session.database}"
287
- puts "Table : #{session.table}"
288
- puts "Config"
289
- puts YAML.dump(session.config.to_h)
286
+ $stdout.puts "Name : #{session.name}"
287
+ $stdout.puts "Cron : #{session.cron}"
288
+ $stdout.puts "Timezone : #{session.timezone}"
289
+ $stdout.puts "Delay : #{session.delay}"
290
+ $stdout.puts "Database : #{session.database}"
291
+ $stdout.puts "Table : #{session.table}"
292
+ $stdout.puts "Config"
293
+ $stdout.puts YAML.dump(session.config)
290
294
  end
291
295
 
292
296
  def wait_connector_job(client, job_id, exclude)
293
297
  job = client.job(job_id)
294
298
  wait_job(job, true)
295
- puts "Status : #{job.status}"
299
+ $stdout.puts "Status : #{job.status}"
296
300
  end
297
301
 
298
302
  end
data/lib/td/command/db.rb CHANGED
@@ -22,7 +22,7 @@ module Command
22
22
  [map[:Type].size, map[:Table]]
23
23
  }
24
24
 
25
- puts cmd_render_table(rows, :fields => [:Table, :Type, :Count, :Schema], :render_format => op.render_format)
25
+ $stdout.puts cmd_render_table(rows, :fields => [:Table, :Type, :Count, :Schema], :render_format => op.render_format)
26
26
  end
27
27
 
28
28
  def db_list(op)
@@ -37,7 +37,7 @@ module Command
37
37
  dbs.each {|db|
38
38
  rows << {:Name=>db.name, :Count=>db.count}
39
39
  }
40
- puts cmd_render_table(rows, :fields => [:Name, :Count], :render_format => op.render_format)
40
+ $stdout.puts cmd_render_table(rows, :fields => [:Name, :Count], :render_format => op.render_format)
41
41
 
42
42
  if dbs.empty?
43
43
  $stderr.puts "There are no databases."
@@ -12,6 +12,7 @@ module Command
12
12
  aws_secret_access_key = nil
13
13
  file_prefix = nil
14
14
  file_format = "json.gz" # default
15
+ pool_name = nil
15
16
 
16
17
  op.on('-w', '--wait', 'wait until the job is completed', TrueClass) {|b|
17
18
  wait = b
@@ -38,6 +39,9 @@ module Command
38
39
  raise ArgumentError, "#{s} is not a supported file format" unless SUPPORTED_FORMATS.include?(s)
39
40
  file_format = s
40
41
  }
42
+ op.on('-O', '--pool-name NAME', 'specify resource pool by name') {|s|
43
+ pool_name = s
44
+ }
41
45
 
42
46
  db_name, table_name = op.cmd_parse
43
47
 
@@ -70,6 +74,7 @@ module Command
70
74
  s3_opts['bucket'] = s3_bucket
71
75
  s3_opts['access_key_id'] = aws_access_key_id
72
76
  s3_opts['secret_access_key'] = aws_secret_access_key
77
+ s3_opts['pool_name'] = pool_name if pool_name
73
78
 
74
79
  job = client.export(db_name, table_name, "s3", s3_opts)
75
80
 
@@ -78,7 +83,7 @@ module Command
78
83
 
79
84
  if wait && !job.finished?
80
85
  wait_job(job)
81
- puts "Status : #{job.status}"
86
+ $stdout.puts "Status : #{job.status}"
82
87
  end
83
88
  end
84
89
 
@@ -13,7 +13,7 @@ module Command
13
13
 
14
14
  elsif c.name != cmd && c.group == cmd
15
15
  # group command
16
- puts List.cmd_usage(cmd)
16
+ $stdout.puts List.cmd_usage(cmd)
17
17
  exit 1
18
18
 
19
19
  else
@@ -26,8 +26,8 @@ module Command
26
26
  cmd = op.cmd_parse
27
27
 
28
28
  TreasureData::Command::List.show_help(op.summary_indent)
29
- puts ""
30
- puts "Type '#{$prog} help COMMAND' for more information on a specific command."
29
+ $stdout.puts ""
30
+ $stdout.puts "Type '#{$prog} help COMMAND' for more information on a specific command."
31
31
  end
32
32
 
33
33
  end
@@ -27,7 +27,7 @@ module Command
27
27
  def import_jar_version(op)
28
28
  op.cmd_parse
29
29
  version = find_version_file
30
- puts "td-import-java #{File.open(version, 'r').read}"
30
+ $stdout.puts "td-import-java #{File.open(version, 'r').read}"
31
31
  end
32
32
 
33
33
  def import_jar_update(op)
@@ -90,7 +90,7 @@ module Command
90
90
  if op.cmd_requires_connectivity
91
91
  raise e
92
92
  else
93
- puts "Warning: JAR update skipped for connectivity issues"
93
+ $stdout.puts "Warning: JAR update skipped for connectivity issues"
94
94
  end
95
95
  end
96
96
 
@@ -303,7 +303,7 @@ module Command
303
303
  installed_path = File.join(File.expand_path('../../..', File.dirname(__FILE__)), 'java')
304
304
  config = Command.find_files("logging.properties", [Updater.jarfile_dest_path, installed_path])
305
305
  if config.empty?
306
- puts "Cannot find 'logging.properties' file in '#{Updater.jarfile_dest_path}' or " +
306
+ $stdout.puts "Cannot find 'logging.properties' file in '#{Updater.jarfile_dest_path}' or " +
307
307
  "'#{installed_path}'." unless ENV['TD_TOOLBELT_DEBUG'].nil?
308
308
  []
309
309
  else