td 0.13.2 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/ChangeLog +9 -0
- data/lib/td/command/export.rb +7 -0
- data/lib/td/command/job.rb +3 -0
- data/lib/td/command/query.rb +5 -0
- data/lib/td/command/runner.rb +1 -1
- data/lib/td/command/sched.rb +5 -1
- data/lib/td/updater.rb +18 -13
- data/lib/td/version.rb +1 -1
- data/spec/file_reader/filter_spec.rb +14 -14
- data/spec/file_reader/io_filter_spec.rb +7 -7
- data/spec/file_reader/line_reader_spec.rb +14 -14
- data/spec/file_reader/parsing_reader_spec.rb +5 -5
- data/spec/file_reader/shared_context.rb +1 -1
- data/spec/file_reader_spec.rb +39 -29
- data/spec/td/command/connector_spec.rb +21 -21
- data/spec/td/command/export_spec.rb +86 -0
- data/spec/td/command/import_spec.rb +11 -11
- data/spec/td/command/job_spec.rb +48 -48
- data/spec/td/command/query_spec.rb +42 -0
- data/spec/td/command/sched_spec.rb +6 -6
- data/spec/td/command/table_spec.rb +54 -54
- data/spec/td/common_spec.rb +21 -21
- data/spec/td/updater_spec.rb +8 -8
- data/spec/td/version_spec.rb +2 -2
- data/td.gemspec +3 -3
- metadata +12 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be3247f0bc28da7b0e3f1e5caa10aaf2f0b0ff52
|
4
|
+
data.tar.gz: bdf8a4ac5a21214084d2f66f791ae3f85b4777d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a5dfba44b1698e8f4f89bf0ee72c791e1b1ac54ab11398d5450b8e51d4fb214b0051cd91acf325604d6696b6dad503a69528fd71ba7aba7eec616b9c4d94688a
|
7
|
+
data.tar.gz: deeecc28efaa52310e34a732e77788162e6c5429bb119c3e3f7fe9efc1d3130ffbc1d728ab24fd749b53c8465007c19186746c2f369456af58356a86a7100a02
|
data/.travis.yml
CHANGED
data/ChangeLog
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 2016-04-25 version 0.14.0
|
2
|
+
|
3
|
+
* Use parallel v1.8.0 #161
|
4
|
+
* Support `td query --domain-key=KEY` #157
|
5
|
+
* Add encryption of export worker #156 #159
|
6
|
+
* Support dummy schedule #152
|
7
|
+
* output bulkload config with `td job:show` #151
|
8
|
+
* fix: make jar_update more solid #150
|
9
|
+
|
1
10
|
== 2016-01-25 version 0.13.2
|
2
11
|
|
3
12
|
* Replace Infinity and NaN inside Array or Hash
|
data/lib/td/command/export.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
module TreasureData
|
3
3
|
module Command
|
4
4
|
SUPPORTED_FORMATS = %W[json.gz line-json.gz tsv.gz]
|
5
|
+
SUPPORTED_ENCRYPT_METHOD = %W[s3]
|
5
6
|
|
6
7
|
def table_export(op)
|
7
8
|
from = nil
|
@@ -13,6 +14,7 @@ module Command
|
|
13
14
|
file_prefix = nil
|
14
15
|
file_format = "json.gz" # default
|
15
16
|
pool_name = nil
|
17
|
+
encryption = nil
|
16
18
|
|
17
19
|
op.on('-w', '--wait', 'wait until the job is completed', TrueClass) {|b|
|
18
20
|
wait = b
|
@@ -42,6 +44,10 @@ module Command
|
|
42
44
|
op.on('-O', '--pool-name NAME', 'specify resource pool by name') {|s|
|
43
45
|
pool_name = s
|
44
46
|
}
|
47
|
+
op.on('-e', '--encryption ENCRYPT_METHOD', 'export with server side encryption with the ENCRYPT_METHOD') {|s|
|
48
|
+
raise ArgumentError, "#{s} is not a supported encryption method" unless SUPPORTED_ENCRYPT_METHOD.include?(s)
|
49
|
+
encryption = s
|
50
|
+
}
|
45
51
|
|
46
52
|
db_name, table_name = op.cmd_parse
|
47
53
|
|
@@ -75,6 +81,7 @@ module Command
|
|
75
81
|
s3_opts['access_key_id'] = aws_access_key_id
|
76
82
|
s3_opts['secret_access_key'] = aws_secret_access_key
|
77
83
|
s3_opts['pool_name'] = pool_name if pool_name
|
84
|
+
s3_opts['encryption'] = encryption if encryption
|
78
85
|
|
79
86
|
job = client.export(db_name, table_name, "s3", s3_opts)
|
80
87
|
|
data/lib/td/command/job.rb
CHANGED
@@ -180,6 +180,9 @@ private
|
|
180
180
|
$stdout.puts "Query : #{job.query}"
|
181
181
|
elsif job.type == :bulk_import_perform
|
182
182
|
$stdout.puts "Destination : #{job.query}"
|
183
|
+
elsif job.type == :bulkload
|
184
|
+
require 'yaml'
|
185
|
+
$stdout.puts "Config :\n#{YAML.dump(job.query)}"
|
183
186
|
end
|
184
187
|
# if the job is done and is of type hive, show the Map-Reduce cumulated CPU time
|
185
188
|
if job.finished?
|
data/lib/td/command/query.rb
CHANGED
@@ -19,6 +19,7 @@ module Command
|
|
19
19
|
limit = nil
|
20
20
|
exclude = false
|
21
21
|
pool_name = nil
|
22
|
+
domain_key = nil
|
22
23
|
|
23
24
|
op.on('-d', '--database DB_NAME', 'use the database (required)') {|s|
|
24
25
|
db_name = s
|
@@ -85,6 +86,9 @@ module Command
|
|
85
86
|
op.on('-O', '--pool-name NAME', 'specify resource pool by name') {|s|
|
86
87
|
pool_name = s
|
87
88
|
}
|
89
|
+
op.on('--domain-key DOMAIN_KEY', 'optional user-provided unique ID. You can include this ID with your `create` request to ensure idempotence') {|s|
|
90
|
+
domain_key = s
|
91
|
+
}
|
88
92
|
|
89
93
|
sql = op.cmd_parse
|
90
94
|
|
@@ -134,6 +138,7 @@ module Command
|
|
134
138
|
opts = {}
|
135
139
|
opts['type'] = type if type
|
136
140
|
opts['pool_name'] = pool_name if pool_name
|
141
|
+
opts['domain_key'] = domain_key if domain_key
|
137
142
|
job = client.query(db_name, sql, result_url, priority, retry_limit, opts)
|
138
143
|
|
139
144
|
$stdout.puts "Job #{job.job_id} is queued."
|
data/lib/td/command/runner.rb
CHANGED
@@ -185,7 +185,7 @@ EOF
|
|
185
185
|
# => NotFoundError
|
186
186
|
# => AuthError
|
187
187
|
if ![ParameterConfigurationError, BulkImportExecutionError, UpdateError, ImportError,
|
188
|
-
APIError, ForbiddenError, NotFoundError, AuthError].include?(e.class) ||
|
188
|
+
APIError, ForbiddenError, NotFoundError, AuthError, AlreadyExistsError].include?(e.class) ||
|
189
189
|
!ENV['TD_TOOLBELT_DEBUG'].nil? || $verbose
|
190
190
|
show_backtrace "Error #{$!.class}: backtrace:", $!.backtrace
|
191
191
|
end
|
data/lib/td/command/sched.rb
CHANGED
@@ -116,7 +116,11 @@ module Command
|
|
116
116
|
exit 1
|
117
117
|
end
|
118
118
|
|
119
|
-
|
119
|
+
if first_time
|
120
|
+
$stderr.puts "Schedule '#{name}' is created. It starts at #{first_time.localtime}."
|
121
|
+
else
|
122
|
+
$stderr.puts "Schedule '#{name}' is created, which never runs."
|
123
|
+
end
|
120
124
|
end
|
121
125
|
|
122
126
|
def sched_delete(op)
|
data/lib/td/updater.rb
CHANGED
@@ -331,17 +331,6 @@ end # module ModuleDefinition
|
|
331
331
|
if updated > last_updated
|
332
332
|
FileUtils.mkdir_p(Updater.jarfile_dest_path) unless File.exists?(Updater.jarfile_dest_path)
|
333
333
|
Dir.chdir(Updater.jarfile_dest_path) do
|
334
|
-
File.open('VERSION', 'w') {|f|
|
335
|
-
if hourly
|
336
|
-
f.print "#{version} via hourly jar auto-update"
|
337
|
-
else
|
338
|
-
f.print "#{version} via import:jar_update command"
|
339
|
-
end
|
340
|
-
}
|
341
|
-
File.open('td-import-java.version', 'w') {|f|
|
342
|
-
f.print "#{version} #{updated}"
|
343
|
-
}
|
344
|
-
|
345
334
|
status = nil
|
346
335
|
indicator = Command::TimeBasedDownloadProgressIndicator.new(
|
347
336
|
"Updating td-import.jar", Time.new.to_i, 2)
|
@@ -355,8 +344,20 @@ end # module ModuleDefinition
|
|
355
344
|
if status
|
356
345
|
$stdout.puts "Installed td-import.jar v#{version} in '#{Updater.jarfile_dest_path}'.\n"
|
357
346
|
File.rename 'td-import.jar.new', 'td-import.jar'
|
347
|
+
|
348
|
+
File.open('VERSION', 'w') {|f|
|
349
|
+
if hourly
|
350
|
+
f.print "#{version} via hourly jar auto-update"
|
351
|
+
else
|
352
|
+
f.print "#{version} via import:jar_update command"
|
353
|
+
end
|
354
|
+
}
|
355
|
+
File.open('td-import-java.version', 'w') {|f|
|
356
|
+
f.print "#{version} #{updated}"
|
357
|
+
}
|
358
358
|
else
|
359
|
-
$stdout.puts "Update of td-import.jar failed."
|
359
|
+
$stdout.puts "Update of td-import.jar failed."
|
360
|
+
$stdout.puts "Please execute 'td import:jar_update' later to update td-import.jar correctly."
|
360
361
|
File.delete 'td-import.jar.new' if File.exists? 'td-import.jar.new'
|
361
362
|
end
|
362
363
|
end
|
@@ -366,7 +367,11 @@ end # module ModuleDefinition
|
|
366
367
|
end
|
367
368
|
|
368
369
|
def check_n_update_jar(hourly = false)
|
369
|
-
if
|
370
|
+
if !File.exist?(File.join(Updater.jarfile_dest_path, 'td-import.jar')) ||
|
371
|
+
!File.exist?(File.join(Updater.jarfile_dest_path, 'VERSION'))
|
372
|
+
# remove all file to install cleanly if a file is missing
|
373
|
+
FileUtils.rm_rf(Updater.jarfile_dest_path)
|
374
|
+
elsif hourly
|
370
375
|
if !ENV['TD_TOOLBELT_JAR_UPDATE'].nil?
|
371
376
|
# also validates the TD_TOOLBELT_JAR_UPDATE environment variable value
|
372
377
|
if ENV['TD_TOOLBELT_JAR_UPDATE'] == "0"
|
data/lib/td/version.rb
CHANGED
@@ -42,7 +42,7 @@ describe 'FileReader filters' do
|
|
42
42
|
|
43
43
|
it 'initialize' do
|
44
44
|
filter = FileReader::AutoTypeConvertParserFilter.new(parser, error, options)
|
45
|
-
filter.
|
45
|
+
expect(filter).not_to be_nil
|
46
46
|
end
|
47
47
|
|
48
48
|
context 'after initialization' do
|
@@ -51,14 +51,14 @@ describe 'FileReader filters' do
|
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'forward returns one converted line' do
|
54
|
-
filter.forward.
|
54
|
+
expect(filter.forward).to eq(dataset[0])
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'feeds all lines' do
|
58
58
|
begin
|
59
59
|
i = 0
|
60
60
|
while line = filter.forward
|
61
|
-
line.
|
61
|
+
expect(line).to eq(dataset[i])
|
62
62
|
i += 1
|
63
63
|
end
|
64
64
|
rescue
|
@@ -79,7 +79,7 @@ describe 'FileReader filters' do
|
|
79
79
|
|
80
80
|
it 'initialize' do
|
81
81
|
builder = FileReader::HashBuilder.new(parser, error, columns)
|
82
|
-
builder.
|
82
|
+
expect(builder).not_to be_nil
|
83
83
|
end
|
84
84
|
|
85
85
|
context 'after initialization' do
|
@@ -88,14 +88,14 @@ describe 'FileReader filters' do
|
|
88
88
|
end
|
89
89
|
|
90
90
|
it 'forward returns one converted line' do
|
91
|
-
builder.forward.
|
91
|
+
expect(builder.forward).to eq(built_dataset[0])
|
92
92
|
end
|
93
93
|
|
94
94
|
it 'feeds all lines' do
|
95
95
|
begin
|
96
96
|
i = 0
|
97
97
|
while line = builder.forward
|
98
|
-
line.
|
98
|
+
expect(line).to eq(built_dataset[i])
|
99
99
|
i += 1
|
100
100
|
end
|
101
101
|
rescue
|
@@ -111,7 +111,7 @@ describe 'FileReader filters' do
|
|
111
111
|
|
112
112
|
it 'initialize' do
|
113
113
|
filter = FileReader::TimeParserFilter.new(builder, error, :time_column => 'log_at')
|
114
|
-
filter.
|
114
|
+
expect(filter).not_to be_nil
|
115
115
|
end
|
116
116
|
|
117
117
|
context 'after initialization' do
|
@@ -125,14 +125,14 @@ describe 'FileReader filters' do
|
|
125
125
|
end
|
126
126
|
|
127
127
|
it 'forward returns one parse line with parsed log_at' do
|
128
|
-
filter.forward.
|
128
|
+
expect(filter.forward).to eq(timed_dataset[0])
|
129
129
|
end
|
130
130
|
|
131
131
|
it 'feeds all lines' do
|
132
132
|
begin
|
133
133
|
i = 0
|
134
134
|
while line = filter.forward
|
135
|
-
line.
|
135
|
+
expect(line).to eq(timed_dataset[i])
|
136
136
|
i += 1
|
137
137
|
end
|
138
138
|
rescue
|
@@ -157,7 +157,7 @@ describe 'FileReader filters' do
|
|
157
157
|
rescue RSpec::Expectations::ExpectationNotMetError => e
|
158
158
|
fail
|
159
159
|
rescue
|
160
|
-
i.
|
160
|
+
expect(i).to eq(0)
|
161
161
|
end
|
162
162
|
end
|
163
163
|
end
|
@@ -182,7 +182,7 @@ describe 'FileReader filters' do
|
|
182
182
|
rescue RSpec::Expectations::ExpectationNotMetError => e
|
183
183
|
fail
|
184
184
|
rescue
|
185
|
-
i.
|
185
|
+
expect(i).to eq(0)
|
186
186
|
end
|
187
187
|
end
|
188
188
|
}
|
@@ -199,7 +199,7 @@ describe 'FileReader filters' do
|
|
199
199
|
|
200
200
|
it 'initialize' do
|
201
201
|
filter = FileReader::SetTimeParserFilter.new(builder, error, :time_value => Time.now.to_i)
|
202
|
-
filter.
|
202
|
+
expect(filter).not_to be_nil
|
203
203
|
end
|
204
204
|
|
205
205
|
context 'after initialization' do
|
@@ -216,14 +216,14 @@ describe 'FileReader filters' do
|
|
216
216
|
end
|
217
217
|
|
218
218
|
it 'forward returns one converted line with time' do
|
219
|
-
filter.forward.
|
219
|
+
expect(filter.forward).to eq(timed_dataset[0])
|
220
220
|
end
|
221
221
|
|
222
222
|
it 'feeds all lines' do
|
223
223
|
begin
|
224
224
|
i = 0
|
225
225
|
while line = filter.forward
|
226
|
-
line.
|
226
|
+
expect(line).to eq(timed_dataset[i])
|
227
227
|
i += 1
|
228
228
|
end
|
229
229
|
rescue
|
@@ -47,12 +47,12 @@ describe 'FileReader io filters' do
|
|
47
47
|
|
48
48
|
it 'returns Zlib::GzipReader with :gzip' do
|
49
49
|
wrapped = FileReader::DecompressIOFilter.filter(gzipped_io, error, :compress => 'gzip')
|
50
|
-
wrapped.
|
50
|
+
expect(wrapped).to be_an_instance_of(Zlib::GzipReader)
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'returns Zlib::GzipReader with auto detection' do
|
54
54
|
wrapped = FileReader::DecompressIOFilter.filter(gzipped_io, error, {})
|
55
|
-
wrapped.
|
55
|
+
expect(wrapped).to be_an_instance_of(Zlib::GzipReader)
|
56
56
|
end
|
57
57
|
|
58
58
|
context 'after initialization' do
|
@@ -63,18 +63,18 @@ describe 'FileReader io filters' do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
it 'forward_row returns one line' do
|
66
|
-
reader.forward_row.
|
66
|
+
expect(reader.forward_row).to eq(lines[0])
|
67
67
|
end
|
68
68
|
|
69
69
|
it 'feeds all lines' do
|
70
70
|
begin
|
71
71
|
i = 0
|
72
72
|
while line = reader.forward_row
|
73
|
-
line.
|
73
|
+
expect(line).to eq(lines[i])
|
74
74
|
i += 1
|
75
75
|
end
|
76
76
|
rescue
|
77
|
-
gzipped_io.eof
|
77
|
+
expect(gzipped_io.eof?).to be_truthy
|
78
78
|
end
|
79
79
|
end
|
80
80
|
}
|
@@ -84,12 +84,12 @@ describe 'FileReader io filters' do
|
|
84
84
|
describe 'plain' do
|
85
85
|
it 'returns passed io with :plain' do
|
86
86
|
wrapped = FileReader::DecompressIOFilter.filter(io, error, :compress => 'plain')
|
87
|
-
wrapped.
|
87
|
+
expect(wrapped).to be_an_instance_of(StringIO)
|
88
88
|
end
|
89
89
|
|
90
90
|
it 'returns passed io with auto detection' do
|
91
91
|
wrapped = FileReader::DecompressIOFilter.filter(io, error, {})
|
92
|
-
wrapped.
|
92
|
+
expect(wrapped).to be_an_instance_of(StringIO)
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
@@ -27,7 +27,7 @@ describe FileReader::LineReader do
|
|
27
27
|
end
|
28
28
|
FileReader::LineReader.new(io, error, {})
|
29
29
|
if io.respond_to?(:external_encoding)
|
30
|
-
io.external_encoding.
|
30
|
+
expect(io.external_encoding).to eq(ee)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -46,8 +46,8 @@ describe FileReader::LineReader do
|
|
46
46
|
|
47
47
|
FileReader::LineReader.new(io, error, {:encoding => specified_encoding})
|
48
48
|
if io.respond_to?(:external_encoding)
|
49
|
-
io.external_encoding.
|
50
|
-
io.external_encoding.
|
49
|
+
expect(io.external_encoding).not_to eq(original_encoding)
|
50
|
+
expect(io.external_encoding).to eq(Encoding.find(specified_encoding))
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
@@ -57,7 +57,7 @@ describe FileReader::LineReader do
|
|
57
57
|
end
|
58
58
|
|
59
59
|
it 'forward_row returns one line' do
|
60
|
-
reader.forward_row.
|
60
|
+
expect(reader.forward_row).to eq(lines[0])
|
61
61
|
end
|
62
62
|
|
63
63
|
# TODO: integrate with following shared_examples_for
|
@@ -65,13 +65,13 @@ describe FileReader::LineReader do
|
|
65
65
|
begin
|
66
66
|
i = 0
|
67
67
|
while line = reader.forward_row
|
68
|
-
line.
|
68
|
+
expect(line).to eq(lines[i])
|
69
69
|
i += 1
|
70
70
|
end
|
71
71
|
rescue RSpec::Expectations::ExpectationNotMetError => e
|
72
72
|
fail
|
73
73
|
rescue
|
74
|
-
io.eof
|
74
|
+
expect(io.eof?).to be_truthy
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
@@ -82,13 +82,13 @@ describe FileReader::LineReader do
|
|
82
82
|
begin
|
83
83
|
i = 0
|
84
84
|
while line = parser.forward
|
85
|
-
line.
|
85
|
+
expect(line).to eq(get_expected.call(i))
|
86
86
|
i += step
|
87
87
|
end
|
88
88
|
rescue RSpec::Expectations::ExpectationNotMetError => e
|
89
89
|
fail
|
90
90
|
rescue
|
91
|
-
io.eof
|
91
|
+
expect(io.eof?).to be_truthy
|
92
92
|
end
|
93
93
|
end
|
94
94
|
end
|
@@ -96,7 +96,7 @@ describe FileReader::LineReader do
|
|
96
96
|
describe FileReader::JSONParser do
|
97
97
|
it 'initialize with LineReader' do
|
98
98
|
parser = FileReader::JSONParser.new(reader, error, {})
|
99
|
-
parser.
|
99
|
+
expect(parser).not_to be_nil
|
100
100
|
end
|
101
101
|
|
102
102
|
context 'after initialization' do
|
@@ -105,7 +105,7 @@ describe FileReader::LineReader do
|
|
105
105
|
end
|
106
106
|
|
107
107
|
it 'forward returns one line' do
|
108
|
-
parser.forward.
|
108
|
+
expect(parser.forward).to eq(JSON.parse(lines[0]))
|
109
109
|
end
|
110
110
|
|
111
111
|
let :get_expected do
|
@@ -144,7 +144,7 @@ describe FileReader::LineReader do
|
|
144
144
|
|
145
145
|
it "initialize with LineReader and #{pattern} delimiter" do
|
146
146
|
parser = FileReader::DelimiterParser.new(reader, error, {:delimiter_expr => Regexp.new(pattern)})
|
147
|
-
parser.
|
147
|
+
expect(parser).not_to be_nil
|
148
148
|
end
|
149
149
|
|
150
150
|
context 'after initialization' do
|
@@ -153,7 +153,7 @@ describe FileReader::LineReader do
|
|
153
153
|
end
|
154
154
|
|
155
155
|
it 'forward returns one line' do
|
156
|
-
parser.forward.
|
156
|
+
expect(parser.forward).to eq(lines[0].split(pattern))
|
157
157
|
end
|
158
158
|
|
159
159
|
let :get_expected do
|
@@ -198,7 +198,7 @@ describe FileReader::LineReader do
|
|
198
198
|
|
199
199
|
it "initialize with LineReader" do
|
200
200
|
parser = parser_class.new(reader, error, {})
|
201
|
-
parser.
|
201
|
+
expect(parser).not_to be_nil
|
202
202
|
end
|
203
203
|
|
204
204
|
context 'after initialization' do
|
@@ -207,7 +207,7 @@ describe FileReader::LineReader do
|
|
207
207
|
end
|
208
208
|
|
209
209
|
it 'forward returns one line' do
|
210
|
-
parser.forward.
|
210
|
+
expect(parser.forward).to eq(output[0])
|
211
211
|
end
|
212
212
|
|
213
213
|
let :get_expected do
|