td 0.13.2 → 0.14.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 +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
|