td 0.11.1 → 0.11.2
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 +8 -8
- data/ChangeLog +29 -0
- data/README.rdoc +64 -0
- data/Rakefile +11 -0
- data/dist/exe.rake +1 -1
- data/dist/pkg.rake +2 -2
- data/lib/td/command/account.rb +18 -5
- data/lib/td/command/acl.rb +1 -1
- data/lib/td/command/apikey.rb +2 -3
- data/lib/td/command/bulk_import.rb +7 -7
- data/lib/td/command/common.rb +91 -6
- data/lib/td/command/db.rb +2 -2
- data/lib/td/command/export.rb +1 -1
- data/lib/td/command/import.rb +48 -18
- data/lib/td/command/job.rb +11 -64
- data/lib/td/command/list.rb +6 -5
- data/lib/td/command/query.rb +1 -4
- data/lib/td/command/result.rb +5 -3
- data/lib/td/command/runner.rb +33 -12
- data/lib/td/command/sample.rb +4 -4
- data/lib/td/command/sched.rb +7 -8
- data/lib/td/command/server.rb +21 -0
- data/lib/td/command/status.rb +3 -3
- data/lib/td/command/table.rb +7 -8
- data/lib/td/command/update.rb +3 -3
- data/lib/td/command/user.rb +7 -7
- data/lib/td/config.rb +45 -20
- data/lib/td/updater.rb +391 -378
- data/lib/td/version.rb +1 -1
- data/td.gemspec +14 -14
- metadata +6 -6
data/lib/td/command/sample.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
module TreasureData
|
3
2
|
module Command
|
4
3
|
|
@@ -23,9 +22,10 @@ module Command
|
|
23
22
|
}
|
24
23
|
}
|
25
24
|
|
26
|
-
$stderr.
|
27
|
-
$stderr.puts "
|
28
|
-
|
25
|
+
$stderr.print "Created #{fname} with #{i} records whose time is "
|
26
|
+
$stderr.puts "in the [#{Time.at(last_time)}, #{Time.at(t)}] range."
|
27
|
+
|
28
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "table:import <db> <table> --json #{fname}' to import this file."
|
29
29
|
end
|
30
30
|
|
31
31
|
end
|
data/lib/td/command/sched.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
module TreasureData
|
3
2
|
module Command
|
4
3
|
|
@@ -127,7 +126,7 @@ module Command
|
|
127
126
|
rescue NotFoundError
|
128
127
|
cmd_debug_error $!
|
129
128
|
$stderr.puts "Schedule '#{name}' does not exist."
|
130
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
129
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "sched:list' to show list of the schedules."
|
131
130
|
exit 1
|
132
131
|
end
|
133
132
|
|
@@ -156,7 +155,7 @@ module Command
|
|
156
155
|
op.on('-d', '--database DB_NAME', 'change the database') {|s|
|
157
156
|
db_name = s
|
158
157
|
}
|
159
|
-
op.on('-r', '--result
|
158
|
+
op.on('-r', '--result RESULT_URL', 'change the result target (see also result:create subcommand)') {|s|
|
160
159
|
result = s
|
161
160
|
}
|
162
161
|
op.on('-t', '--timezone TZ', "name of the timezone.",
|
@@ -210,7 +209,7 @@ module Command
|
|
210
209
|
rescue NotFoundError
|
211
210
|
cmd_debug_error $!
|
212
211
|
$stderr.puts "Schedule '#{name}' does not exist."
|
213
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
212
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "sched:list' to show list of the schedules."
|
214
213
|
exit 1
|
215
214
|
end
|
216
215
|
|
@@ -246,7 +245,7 @@ module Command
|
|
246
245
|
rescue NotFoundError
|
247
246
|
cmd_debug_error $!
|
248
247
|
$stderr.puts "Schedule '#{name}' does not exist."
|
249
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
248
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "sched:list' to show list of the schedules."
|
250
249
|
exit 1
|
251
250
|
end
|
252
251
|
|
@@ -302,7 +301,7 @@ module Command
|
|
302
301
|
rescue NotFoundError
|
303
302
|
cmd_debug_error $!
|
304
303
|
$stderr.puts "Schedule '#{name}' does not exist."
|
305
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
304
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "sched:list' to show list of the schedules."
|
306
305
|
exit 1
|
307
306
|
end
|
308
307
|
|
@@ -315,5 +314,5 @@ module Command
|
|
315
314
|
puts cmd_render_table(rows, :fields => [:JobID, :Time], :max_width=>500, :render_format => op.render_format)
|
316
315
|
end
|
317
316
|
|
318
|
-
end
|
319
|
-
end
|
317
|
+
end # module Command
|
318
|
+
end # module TreasureData
|
data/lib/td/command/server.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'uri'
|
1
2
|
|
2
3
|
module TreasureData
|
3
4
|
module Command
|
@@ -8,6 +9,26 @@ module Command
|
|
8
9
|
puts Client.server_status
|
9
10
|
end
|
10
11
|
|
12
|
+
def server_endpoint(op)
|
13
|
+
endpoint = op.cmd_parse
|
14
|
+
|
15
|
+
Command.validate_api_endpoint(endpoint)
|
16
|
+
|
17
|
+
if Config.cl_endpoint and endpoint != Config.endpoint
|
18
|
+
raise ParameterConfigurationError,
|
19
|
+
"You specified the API server endpoint in the command options as well (-e / --endpoint option) but it does not match the value provided to the 'server:endpoint' command. Please remove the option or ensure the endpoints URLs match each other."
|
20
|
+
end
|
21
|
+
|
22
|
+
conf = nil
|
23
|
+
begin
|
24
|
+
conf = Config.read
|
25
|
+
rescue ConfigError
|
26
|
+
conf = Config.new
|
27
|
+
end
|
28
|
+
conf["account.endpoint"] = endpoint
|
29
|
+
conf.save
|
30
|
+
end
|
31
|
+
|
11
32
|
end
|
12
33
|
end
|
13
34
|
|
data/lib/td/command/status.rb
CHANGED
@@ -34,7 +34,7 @@ module Command
|
|
34
34
|
j = client.jobs(0, 4)
|
35
35
|
j.each {|job|
|
36
36
|
start = job.start_at
|
37
|
-
elapsed = humanize_elapsed_time(start, job.end_at)
|
37
|
+
elapsed = Command.humanize_elapsed_time(start, job.end_at)
|
38
38
|
jobs << {:JobID => job.job_id, :Status => job.status, :Query => job.query.to_s, :Start => (start ? start.localtime : ''), :Elapsed => elapsed, :Result => job.result_url}
|
39
39
|
}
|
40
40
|
x2, y2 = status_render(0, 0, "[Jobs]", jobs, :fields => [:JobID, :Status, :Start, :Elapsed, :Result, :Query])
|
@@ -84,6 +84,6 @@ module Command
|
|
84
84
|
return movex+max_width, height
|
85
85
|
end
|
86
86
|
|
87
|
-
end
|
88
|
-
end
|
87
|
+
end # module Command
|
88
|
+
end # module TreasureData
|
89
89
|
|
data/lib/td/command/table.rb
CHANGED
@@ -40,7 +40,6 @@ module Command
|
|
40
40
|
|
41
41
|
db_name, table_name = op.cmd_parse
|
42
42
|
|
43
|
-
#API.validate_database_name(db_name)
|
44
43
|
API.validate_table_name(table_name)
|
45
44
|
|
46
45
|
if HIVE_RESERVED_KEYWORDS.include?(table_name.upcase)
|
@@ -65,7 +64,7 @@ module Command
|
|
65
64
|
rescue NotFoundError
|
66
65
|
cmd_debug_error $!
|
67
66
|
$stderr.puts "Database '#{db_name}' does not exist."
|
68
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
67
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "db:create #{db_name}' to create the database."
|
69
68
|
exit 1
|
70
69
|
rescue AlreadyExistsError
|
71
70
|
cmd_debug_error $!
|
@@ -111,7 +110,7 @@ module Command
|
|
111
110
|
rescue NotFoundError
|
112
111
|
cmd_debug_error $!
|
113
112
|
$stderr.puts "Table '#{db_name}.#{table_name}' does not exist."
|
114
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
113
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "table:list #{db_name}' to show list of the tables."
|
115
114
|
exit 1
|
116
115
|
end
|
117
116
|
|
@@ -189,13 +188,13 @@ module Command
|
|
189
188
|
if rows.empty?
|
190
189
|
if db_name
|
191
190
|
$stderr.puts "Database '#{db_name}' has no tables."
|
192
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
191
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "table:create <db> <table>' to create a table."
|
193
192
|
elsif databases.empty?
|
194
193
|
$stderr.puts "There are no databases."
|
195
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
194
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "db:create <db>' to create a database."
|
196
195
|
else
|
197
196
|
$stderr.puts "There are no tables."
|
198
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
197
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "table:create <db> <table>' to create a table."
|
199
198
|
end
|
200
199
|
end
|
201
200
|
end
|
@@ -336,7 +335,7 @@ module Command
|
|
336
335
|
job = table.export('s3', opts)
|
337
336
|
|
338
337
|
$stderr.puts "Export job #{job.job_id} is queued."
|
339
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
338
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "job:show #{job.job_id}' to show the status."
|
340
339
|
|
341
340
|
if wait && !job.finished?
|
342
341
|
wait_job(job)
|
@@ -395,7 +394,7 @@ module Command
|
|
395
394
|
job = client.partial_delete(db_name, table_name, to, from, opts)
|
396
395
|
|
397
396
|
$stderr.puts "Partial delete job #{job.job_id} is queued."
|
398
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
397
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "job:show #{job.job_id}' to show the status."
|
399
398
|
|
400
399
|
if wait && !job.finished?
|
401
400
|
wait_job(job)
|
data/lib/td/command/update.rb
CHANGED
@@ -14,12 +14,12 @@ module Command
|
|
14
14
|
start_time = Time.now
|
15
15
|
puts "Updating 'td' from #{TOOLBELT_VERSION}..."
|
16
16
|
if new_version = Updater.update
|
17
|
-
puts "Successfully updated to #{new_version} in #{humanize_time((Time.now - start_time).to_i)}."
|
17
|
+
puts "Successfully updated to #{new_version} in #{Command.humanize_time((Time.now - start_time).to_i)}."
|
18
18
|
else
|
19
19
|
puts "Nothing to update."
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
end
|
24
|
-
end
|
23
|
+
end # module Command
|
24
|
+
end # module TreasureData
|
25
25
|
|
data/lib/td/command/user.rb
CHANGED
@@ -11,7 +11,7 @@ module Command
|
|
11
11
|
user = users.find {|user| name == user.name }
|
12
12
|
unless user
|
13
13
|
$stderr.puts "User '#{name}' does not exist."
|
14
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
14
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "user:create <name>' to create an user."
|
15
15
|
exit 1
|
16
16
|
end
|
17
17
|
|
@@ -37,7 +37,7 @@ module Command
|
|
37
37
|
|
38
38
|
if rows.empty?
|
39
39
|
$stderr.puts "There are no users."
|
40
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
40
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "user:create <name>' to create an users."
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -120,7 +120,7 @@ module Command
|
|
120
120
|
client.add_user(name, nil, email, password)
|
121
121
|
|
122
122
|
$stderr.puts "User '#{name}' is created."
|
123
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
123
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "user:apikeys #{name}' to show the API key."
|
124
124
|
end
|
125
125
|
|
126
126
|
def user_delete(op)
|
@@ -146,12 +146,12 @@ module Command
|
|
146
146
|
client.add_apikey(name)
|
147
147
|
rescue TreasureData::NotFoundError
|
148
148
|
$stderr.puts "User '#{name}' does not exist."
|
149
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
149
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "users' to show users."
|
150
150
|
exit 1
|
151
151
|
end
|
152
152
|
|
153
153
|
$stderr.puts "Added an API key to user '#{name}'."
|
154
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
154
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "user:apikeys #{name}' to show the API key"
|
155
155
|
end
|
156
156
|
|
157
157
|
def user_apikey_remove(op)
|
@@ -163,8 +163,8 @@ module Command
|
|
163
163
|
client.remove_apikey(name, key)
|
164
164
|
rescue TreasureData::NotFoundError
|
165
165
|
$stderr.puts "User '#{name}' or API key '#{key}' does not exist."
|
166
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
167
|
-
$stderr.puts "Use '#{$prog} " + Config.
|
166
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "users' to show users."
|
167
|
+
$stderr.puts "Use '#{$prog} " + Config.cl_options_string + "user:apikeys '#{key}' to show API keys"
|
168
168
|
exit 1
|
169
169
|
end
|
170
170
|
|
data/lib/td/config.rb
CHANGED
@@ -13,6 +13,16 @@ end
|
|
13
13
|
|
14
14
|
|
15
15
|
class Config
|
16
|
+
# class variables
|
17
|
+
@@path = ENV['TREASURE_DATA_CONFIG_PATH'] || ENV['TD_CONFIG_PATH'] || File.join(ENV['HOME'], '.td', 'td.conf')
|
18
|
+
@@apikey = ENV['TREASURE_DATA_API_KEY'] || ENV['TD_API_KEY']
|
19
|
+
@@apikey = nil if @@apikey == ""
|
20
|
+
@@cl_apikey = false # flag to indicate whether an apikey has been provided through the command-line
|
21
|
+
@@endpoint = ENV['TREASURE_DATA_API_SERVER'] || ENV['TD_API_SERVER']
|
22
|
+
@@endpoint = nil if @@endpoint == ""
|
23
|
+
@@cl_endpoint = false # flag to indicate whether an endpoint has been provided through the command-line
|
24
|
+
@@secure = true
|
25
|
+
|
16
26
|
def initialize
|
17
27
|
@path = nil
|
18
28
|
@conf = {} # section.key = val
|
@@ -76,23 +86,18 @@ class Config
|
|
76
86
|
FileUtils.mkdir_p File.dirname(@path)
|
77
87
|
File.open(@path, "w") {|f|
|
78
88
|
@conf.keys.map {|cate_key|
|
79
|
-
cate_key.split('.',2)
|
80
|
-
}.zip(@conf.values).group_by {|(section,key),val|
|
89
|
+
cate_key.split('.', 2)
|
90
|
+
}.zip(@conf.values).group_by {|(section,key), val|
|
81
91
|
section
|
82
92
|
}.each {|section,cate_key_vals|
|
83
93
|
f.puts "[#{section}]"
|
84
|
-
cate_key_vals.each {|(section,key),val|
|
94
|
+
cate_key_vals.each {|(section,key), val|
|
85
95
|
f.puts " #{key} = #{val}"
|
86
96
|
}
|
87
97
|
}
|
88
98
|
}
|
89
99
|
end
|
90
100
|
|
91
|
-
@@path = ENV['TREASURE_DATA_CONFIG_PATH'] || ENV['TD_CONFIG_PATH'] || File.join(ENV['HOME'], '.td', 'td.conf')
|
92
|
-
@@apikey = ENV['TREASURE_DATA_API_KEY'] || ENV['TD_API_KEY']
|
93
|
-
@@apikey = nil if @@apikey == ""
|
94
|
-
@@cl_apikey = false # flag to indicate whether an apikey has been provided through the command-line
|
95
|
-
@@secure = true
|
96
101
|
|
97
102
|
def self.path
|
98
103
|
@@path
|
@@ -102,6 +107,16 @@ class Config
|
|
102
107
|
@@path = path
|
103
108
|
end
|
104
109
|
|
110
|
+
|
111
|
+
def self.secure
|
112
|
+
@@secure
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.secure=(secure)
|
116
|
+
@@secure = secure
|
117
|
+
end
|
118
|
+
|
119
|
+
|
105
120
|
def self.apikey
|
106
121
|
@@apikey || Config.read['account.apikey']
|
107
122
|
end
|
@@ -118,22 +133,32 @@ class Config
|
|
118
133
|
@@cl_apikey = flag
|
119
134
|
end
|
120
135
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
else
|
125
|
-
""
|
126
|
-
end
|
136
|
+
|
137
|
+
def self.endpoint
|
138
|
+
@@endpoint || Config.read['account.endpoint']
|
127
139
|
end
|
128
140
|
|
129
|
-
def self.
|
130
|
-
@@
|
141
|
+
def self.endpoint=(endpoint)
|
142
|
+
@@endpoint = endpoint
|
131
143
|
end
|
132
144
|
|
133
|
-
def self.
|
134
|
-
@@
|
145
|
+
def self.cl_endpoint
|
146
|
+
@@cl_endpoint
|
135
147
|
end
|
136
|
-
end
|
137
148
|
|
149
|
+
def self.cl_endpoint=(flag)
|
150
|
+
@@cl_endpoint = flag
|
151
|
+
end
|
138
152
|
|
139
|
-
|
153
|
+
# renders the apikey and endpoint options as a string for the helper commands
|
154
|
+
def self.cl_options_string
|
155
|
+
string = ""
|
156
|
+
string += "-k #{@@apikey}" if @@cl_apikey
|
157
|
+
string += " " unless string.empty?
|
158
|
+
string += "-e #{@@endpoint}" if @@cl_endpoint
|
159
|
+
string += " " unless string.empty?
|
160
|
+
string
|
161
|
+
end
|
162
|
+
|
163
|
+
end # class Config
|
164
|
+
end # module TreasureData
|
data/lib/td/updater.rb
CHANGED
@@ -4,429 +4,442 @@ require "shellwords"
|
|
4
4
|
require "zip/zip"
|
5
5
|
|
6
6
|
module TreasureData
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
7
|
+
module Updater
|
8
|
+
#
|
9
|
+
# Toolbelt upgrade
|
10
|
+
#
|
11
|
+
|
12
|
+
def self.raise_error(message)
|
13
|
+
# TODO: Replace better Exception class
|
14
|
+
raise RuntimeError.new(message)
|
15
|
+
end
|
16
|
+
|
17
|
+
# copied from TreasureData::Helpers to avoid load issue.
|
18
|
+
def self.home_directory
|
19
|
+
on_windows? ? ENV['USERPROFILE'].gsub("\\","/") : ENV['HOME']
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.on_windows?
|
23
|
+
RUBY_PLATFORM =~ /mswin32|mingw32/
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.on_mac?
|
27
|
+
RUBY_PLATFORM =~ /-darwin\d/
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.updating_lock_path
|
31
|
+
File.join(home_directory, ".td", "updating")
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.installed_client_path
|
35
|
+
File.expand_path("../../../../../..", __FILE__)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.updated_client_path
|
39
|
+
File.join(home_directory, ".td", "updated")
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.latest_local_version
|
43
|
+
installed_version = client_version_from_path(installed_client_path)
|
44
|
+
updated_version = client_version_from_path(updated_client_path)
|
45
|
+
if compare_versions(updated_version, installed_version) > 0
|
46
|
+
updated_version
|
47
|
+
else
|
48
|
+
installed_version
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.get_client_version_file(path)
|
53
|
+
td_gems = Dir[File.join(path, "vendor/gems/td-*")]
|
54
|
+
td_gems.each { |td_gem|
|
55
|
+
if td_gem =~ /#{"#{Regexp.escape(path)}\/vendor\/gems\/td-\\d*.\\d*.\\d*"}/
|
56
|
+
return File.join(td_gem, "/lib/td/version.rb")
|
49
57
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
58
|
+
}
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.client_version_from_path(path)
|
63
|
+
if version_file = get_client_version_file(path)
|
64
|
+
File.read(version_file).match(/TOOLBELT_VERSION = '([^']+)'/)[1]
|
65
|
+
else
|
66
|
+
'0.0.0'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.disable(message)
|
71
|
+
@disable = message
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.disable?
|
75
|
+
!@disable.nil?
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.disable_message
|
79
|
+
@disable
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.wait_for_lock(path, wait_for = 5, check_every = 0.5)
|
83
|
+
start = Time.now.to_i
|
84
|
+
while File.exists?(path)
|
85
|
+
sleep check_every
|
86
|
+
if (Time.now.to_i - start) > wait_for
|
87
|
+
raise_error "Unable to acquire update lock"
|
67
88
|
end
|
68
89
|
end
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
raise_error "Non supported environment"
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def self.fetch(uri)
|
111
|
-
require 'net/http'
|
112
|
-
require 'openssl'
|
113
|
-
|
114
|
-
# open-uri can't treat 'http -> https' redirection and
|
115
|
-
# Net::HTTP.get_response can't get response from HTTPS endpoint.
|
116
|
-
# So we use following code to avoid above issues.
|
117
|
-
u = URI(uri)
|
118
|
-
response =
|
119
|
-
if u.scheme == 'https'
|
120
|
-
http = Net::HTTP.new(u.host, u.port)
|
121
|
-
http.use_ssl = true
|
122
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
123
|
-
http.request(Net::HTTP::Get.new(u.path))
|
124
|
-
else
|
125
|
-
Net::HTTP.get_response(u)
|
126
|
-
end
|
127
|
-
|
128
|
-
case response
|
129
|
-
when Net::HTTPSuccess then response.body
|
130
|
-
when Net::HTTPRedirection then fetch(response['Location'])
|
90
|
+
begin
|
91
|
+
FileUtils.touch(path)
|
92
|
+
ret = yield
|
93
|
+
ensure
|
94
|
+
FileUtils.rm_f(path)
|
95
|
+
end
|
96
|
+
ret
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.package_category
|
100
|
+
case
|
101
|
+
when on_windows?
|
102
|
+
'exe'
|
103
|
+
when on_mac?
|
104
|
+
'pkg'
|
105
|
+
else
|
106
|
+
raise_error "Non supported environment"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.fetch(url)
|
111
|
+
require 'net/http'
|
112
|
+
require 'openssl'
|
113
|
+
|
114
|
+
http_class = Command.get_http_class
|
115
|
+
|
116
|
+
# open-uri can't treat 'http -> https' redirection and
|
117
|
+
# Net::HTTP.get_response can't get response from HTTPS endpoint.
|
118
|
+
# So we use following code to avoid these issues.
|
119
|
+
uri = URI(url)
|
120
|
+
response =
|
121
|
+
if uri.scheme == 'https' and ENV['HTTP_PROXY'].nil?
|
122
|
+
# NOTE: SSL is force off for communications over proxy
|
123
|
+
http = http_class.new(uri.host, uri.port)
|
124
|
+
http.use_ssl = true
|
125
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
126
|
+
http.request(Net::HTTP::Get.new(uri.path))
|
131
127
|
else
|
132
|
-
|
133
|
-
response.error!
|
128
|
+
http_class.get_response(uri)
|
134
129
|
end
|
135
|
-
end
|
136
130
|
|
137
|
-
|
138
|
-
|
131
|
+
case response
|
132
|
+
when Net::HTTPSuccess then response.body
|
133
|
+
when Net::HTTPRedirection then fetch(response['Location'])
|
134
|
+
else
|
135
|
+
raise "An error occurred when fetching from '#{url}'."
|
136
|
+
response.error!
|
139
137
|
end
|
138
|
+
end
|
140
139
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
def self.update_package_endpoint
|
146
|
-
"#{endpoint_root}/td-update-#{package_category}.zip"
|
147
|
-
end
|
140
|
+
def self.endpoint_root
|
141
|
+
ENV['TD_TOOLBELT_UPDATE_ROOT'] || "http://toolbelt.treasuredata.com"
|
142
|
+
end
|
148
143
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
require 'open-uri'
|
153
|
-
require "tmpdir"
|
154
|
-
require "zip/zip"
|
155
|
-
|
156
|
-
latest_version = fetch(version_endpoint)
|
157
|
-
|
158
|
-
if compare_versions(latest_version, latest_local_version) > 0
|
159
|
-
Dir.mktmpdir do |download_dir|
|
160
|
-
|
161
|
-
# initialize the progress indicator
|
162
|
-
base_msg = "Downloading updated toolbelt package"
|
163
|
-
print base_msg + " " * 10
|
164
|
-
start_time = last_time = Time.new.to_i
|
165
|
-
|
166
|
-
# downloading the update compressed file
|
167
|
-
File.open("#{download_dir}/td-update.zip", "wb") do |file|
|
168
|
-
endpoint = update_package_endpoint
|
169
|
-
puts "\npackage '#{endpoint}'... " unless ENV['TD_TOOLBELT_DEBUG'].nil?
|
170
|
-
stream_fetch(endpoint, file) {
|
171
|
-
|
172
|
-
# progress indicator
|
173
|
-
if (time = Time.now.to_i) - last_time > 2
|
174
|
-
msg = "\r" + base_msg + ": #{time - start_time}s elapsed"
|
175
|
-
# TODO parse 'time - start_time' with humanize_time from common.rb
|
176
|
-
# once this method is not static
|
177
|
-
print msg + " " * 10
|
178
|
-
last_time = time
|
179
|
-
end
|
180
|
-
}
|
181
|
-
end
|
144
|
+
def self.version_endpoint
|
145
|
+
"#{endpoint_root}/version.#{package_category}"
|
146
|
+
end
|
182
147
|
|
183
|
-
|
184
|
-
|
148
|
+
def self.update_package_endpoint
|
149
|
+
"#{endpoint_root}/td-update-#{package_category}.zip"
|
150
|
+
end
|
185
151
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
152
|
+
def self.update(autoupdate = false)
|
153
|
+
wait_for_lock(updating_lock_path, 5) do
|
154
|
+
require "td"
|
155
|
+
require 'open-uri'
|
156
|
+
require "tmpdir"
|
157
|
+
require "zip/zip"
|
158
|
+
|
159
|
+
latest_version = fetch(version_endpoint)
|
160
|
+
|
161
|
+
if compare_versions(latest_version, latest_local_version) > 0
|
162
|
+
Dir.mktmpdir do |download_dir|
|
163
|
+
|
164
|
+
indicator = Command::TimeBasedDownloadProgressIndicator.new(
|
165
|
+
"Downloading updated toolbelt package", Time.new.to_i, 2)
|
166
|
+
# downloading the update compressed file
|
167
|
+
File.open("#{download_dir}/td-update.zip", "wb") do |file|
|
168
|
+
endpoint = update_package_endpoint
|
169
|
+
puts "\npackage '#{endpoint}'... " unless ENV['TD_TOOLBELT_DEBUG'].nil?
|
170
|
+
stream_fetch(endpoint, file) {
|
171
|
+
indicator.update
|
172
|
+
}
|
173
|
+
end
|
174
|
+
indicator.finish
|
175
|
+
|
176
|
+
print "Unpacking updated toolbelt package..."
|
177
|
+
Zip::ZipFile.open("#{download_dir}/td-update.zip") do |zip|
|
178
|
+
zip.each do |entry|
|
179
|
+
target = File.join(download_dir, entry.to_s)
|
180
|
+
FileUtils.mkdir_p(File.dirname(target))
|
181
|
+
zip.extract(entry, target) { true }
|
193
182
|
end
|
194
|
-
|
183
|
+
end
|
184
|
+
print "done\n"
|
195
185
|
|
196
|
-
|
186
|
+
FileUtils.rm "#{download_dir}/td-update.zip"
|
197
187
|
|
198
|
-
|
199
|
-
|
188
|
+
old_version = latest_local_version
|
189
|
+
new_version = client_version_from_path(download_dir)
|
200
190
|
|
201
|
-
|
202
|
-
|
203
|
-
|
191
|
+
if compare_versions(new_version, old_version) < 0 && !autoupdate
|
192
|
+
raise_error "Installed version (#{old_version}) is newer than the latest available update (#{new_version})"
|
193
|
+
end
|
204
194
|
|
205
|
-
|
206
|
-
|
207
|
-
|
195
|
+
FileUtils.rm_rf updated_client_path
|
196
|
+
FileUtils.mkdir_p File.dirname(updated_client_path)
|
197
|
+
FileUtils.cp_r(download_dir, updated_client_path)
|
208
198
|
|
209
|
-
|
210
|
-
end
|
211
|
-
else
|
212
|
-
false # already up to date
|
199
|
+
new_version
|
213
200
|
end
|
201
|
+
else
|
202
|
+
false # already up to date
|
214
203
|
end
|
215
|
-
ensure
|
216
|
-
FileUtils.rm_f(updating_lock_path)
|
217
204
|
end
|
205
|
+
ensure
|
206
|
+
FileUtils.rm_f(updating_lock_path)
|
207
|
+
end
|
218
208
|
|
219
|
-
|
220
|
-
|
221
|
-
|
209
|
+
def self.compare_versions(first_version, second_version)
|
210
|
+
first_version.split('.').map { |part| Integer(part) rescue part } <=> second_version.split('.').map { |part| Integer(part) rescue part }
|
211
|
+
end
|
222
212
|
|
223
|
-
|
224
|
-
|
225
|
-
|
213
|
+
def self.inject_libpath
|
214
|
+
old_version = client_version_from_path(installed_client_path)
|
215
|
+
new_version = client_version_from_path(updated_client_path)
|
226
216
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
end
|
232
|
-
load('td/updater.rb') # reload updated updater
|
217
|
+
if compare_versions(new_version, old_version) > 0
|
218
|
+
vendored_gems = Dir[File.join(updated_client_path, "vendor", "gems", "*")]
|
219
|
+
vendored_gems.each do |vendored_gem|
|
220
|
+
$:.unshift File.join(vendored_gem, "lib")
|
233
221
|
end
|
222
|
+
load('td/updater.rb') # reload updated updater
|
223
|
+
end
|
234
224
|
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
225
|
+
# check every hour if the toolbelt can be updated.
|
226
|
+
# => If so, update in the background
|
227
|
+
if File.exists?(last_toolbelt_autoupdate_timestamp)
|
228
|
+
return if (Time.now.to_i - File.mtime(last_toolbelt_autoupdate_timestamp).to_i) < 60 * 60 * 1 # every 1 hours
|
229
|
+
end
|
230
|
+
log_path = File.join(home_directory, '.td', 'autoupdate.log')
|
231
|
+
FileUtils.mkdir_p File.dirname(log_path)
|
232
|
+
td_binary = File.expand_path($0)
|
233
|
+
pid = if defined?(RUBY_VERSION) and RUBY_VERSION =~ /^1\.8\.\d+/
|
234
|
+
fork do
|
235
|
+
exec("#{Shellwords.escape(td_binary)} update &> #{Shellwords.escape(log_path)} 2>&1")
|
239
236
|
end
|
240
|
-
|
241
|
-
|
242
|
-
td_binary
|
243
|
-
|
244
|
-
|
245
|
-
|
237
|
+
else
|
238
|
+
log_file = File.open(log_path, "w")
|
239
|
+
spawn(td_binary, 'update', :err => log_file, :out => log_file)
|
240
|
+
end
|
241
|
+
Process.detach(pid)
|
242
|
+
FileUtils.mkdir_p File.dirname(last_toolbelt_autoupdate_timestamp)
|
243
|
+
FileUtils.touch last_toolbelt_autoupdate_timestamp
|
244
|
+
end
|
245
|
+
|
246
|
+
def self.last_toolbelt_autoupdate_timestamp
|
247
|
+
File.join(home_directory, ".td", "autoupdate.last")
|
248
|
+
end
|
249
|
+
|
250
|
+
#
|
251
|
+
# td-import.jar upgrade
|
252
|
+
#
|
253
|
+
|
254
|
+
# locate the root of the td package which is 3 folders up from the location of this file
|
255
|
+
def jarfile_dest_path
|
256
|
+
File.join(Updater.home_directory, ".td", "java")
|
257
|
+
end
|
258
|
+
|
259
|
+
private
|
260
|
+
def self.stream_fetch(url, binfile, &progress)
|
261
|
+
require 'net/http'
|
262
|
+
|
263
|
+
uri = URI(url)
|
264
|
+
http_class = Command.get_http_class
|
265
|
+
http = http_class.new(uri.host, uri.port)
|
266
|
+
|
267
|
+
# NOTE: keep SSL off when using a proxy
|
268
|
+
if uri.scheme == 'https' and ENV['HTTP_PROXY'].nil?
|
269
|
+
http.use_ssl = true
|
270
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
271
|
+
end
|
272
|
+
|
273
|
+
http.request_get(uri.path) {|response|
|
274
|
+
if response.class == Net::HTTPOK
|
275
|
+
# print a . every tick_period seconds
|
276
|
+
response.read_body do |chunk|
|
277
|
+
binfile.write chunk
|
278
|
+
progress.call unless progress.nil?
|
246
279
|
end
|
280
|
+
return true
|
281
|
+
elsif response.class == Net::HTTPFound || \
|
282
|
+
response.class == Net::HTTPRedirection
|
283
|
+
puts "redirect '#{url}' to '#{response['Location']}'... " unless ENV['TD_TOOLBELT_DEBUG'].nil?
|
284
|
+
return stream_fetch(response['Location'], binfile, &progress)
|
247
285
|
else
|
248
|
-
|
249
|
-
|
286
|
+
raise "An error occurred when fetching from '#{uri}' " +
|
287
|
+
"(#{response.class.to_s}: #{response.message})."
|
288
|
+
return false
|
250
289
|
end
|
251
|
-
|
252
|
-
|
253
|
-
FileUtils.touch last_toolbelt_autoupdate_timestamp
|
254
|
-
end
|
290
|
+
}
|
291
|
+
end
|
255
292
|
|
256
|
-
|
257
|
-
|
258
|
-
|
293
|
+
private
|
294
|
+
def jar_update(hourly = false)
|
295
|
+
require 'rexml/document'
|
296
|
+
require 'open-uri'
|
297
|
+
require 'fileutils'
|
259
298
|
|
260
|
-
|
261
|
-
# td-import.jar upgrade
|
262
|
-
#
|
299
|
+
maven_repo = "http://maven.treasure-data.com/com/treasure_data/td-import"
|
263
300
|
|
264
|
-
|
265
|
-
|
266
|
-
|
301
|
+
begin
|
302
|
+
xml = Updater.fetch("#{maven_repo}/maven-metadata.xml")
|
303
|
+
rescue Exception => exc
|
304
|
+
raise Command::UpdateError,
|
305
|
+
"There was a problem accessing the remote XML resource '#{maven_repo}/maven-metadata.xml' " +
|
306
|
+
"(#{exc.class.to_s}: #{exc.message})"
|
267
307
|
end
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
require 'net/http'
|
272
|
-
|
273
|
-
uri = URI(url)
|
274
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
275
|
-
if uri.scheme == 'https'
|
276
|
-
http.use_ssl = true
|
277
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
278
|
-
end
|
279
|
-
http.start
|
280
|
-
request = Net::HTTP::Get.new(uri.to_s)
|
281
|
-
http.request request do |response|
|
282
|
-
if response.class == Net::HTTPOK
|
283
|
-
# print a . every tick_period seconds
|
284
|
-
response.read_body do |chunk|
|
285
|
-
binfile.write chunk
|
286
|
-
progress.call #unless progress.nil?
|
287
|
-
end
|
288
|
-
return true
|
289
|
-
elsif response.class == Net::HTTPFound || \
|
290
|
-
response.class == Net::HTTPRedirection
|
291
|
-
puts "redirect '#{url}' to '#{response['Location']}'... " unless ENV['TD_TOOLBELT_DEBUG'].nil?
|
292
|
-
return stream_fetch(response['Location'], binfile, &progress)
|
293
|
-
else
|
294
|
-
raise "An error occurred when fetching from '#{uri}'."
|
295
|
-
return false
|
296
|
-
end
|
297
|
-
end
|
308
|
+
if xml.nil? || xml.empty?
|
309
|
+
raise Command::UpdateError,
|
310
|
+
"The remote XML resource '#{maven_repo}/maven-metadata.xml' returned an empty file."
|
298
311
|
end
|
299
312
|
|
300
|
-
|
301
|
-
|
302
|
-
|
313
|
+
# read version and update date from the xml file
|
314
|
+
doc = REXML::Document.new(xml)
|
315
|
+
updated = Time.strptime(REXML::XPath.match(doc, '/metadata/versioning/lastUpdated').first.text, "%Y%m%d%H%M%S")
|
316
|
+
version = REXML::XPath.match(doc, '/metadata/versioning/release').first.text
|
303
317
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
doc = REXML::Document.new(open("#{maven_repo}/maven-metadata.xml") { |f| f.read })
|
309
|
-
updated = Time.strptime(REXML::XPath.match(doc, '/metadata/versioning/lastUpdated').first.text, "%Y%m%d%H%M%S")
|
310
|
-
version = REXML::XPath.match(doc, '/metadata/versioning/release').first.text
|
311
|
-
|
312
|
-
# Convert into UTF to compare time correctly
|
313
|
-
updated = (updated + updated.gmt_offset).utc unless updated.gmt?
|
314
|
-
last_updated = existent_jar_updated_time
|
315
|
-
|
316
|
-
if updated > last_updated
|
317
|
-
FileUtils.mkdir_p(jarfile_dest_path) unless File.exists?(jarfile_dest_path)
|
318
|
-
Dir.chdir jarfile_dest_path
|
319
|
-
|
320
|
-
File.open('VERSION', 'w') { |f| f.print "#{version} via import:jar_update" }
|
321
|
-
File.open('td-import-java.version', 'w') { |f| f.print "#{version} #{updated}" }
|
322
|
-
|
323
|
-
# initialize the progress indicator
|
324
|
-
base_msg = "Updating td-import.jar"
|
325
|
-
start_time = last_time = Time.new.to_i
|
326
|
-
print base_msg + " " * 10
|
327
|
-
|
328
|
-
binfile = File.open 'td-import.jar.new', 'wb'
|
329
|
-
status = Updater.stream_fetch("#{maven_repo}/#{version}/td-import-#{version}-jar-with-dependencies.jar", binfile) {
|
330
|
-
|
331
|
-
# progress indicator
|
332
|
-
if (time = Time.now.to_i) - last_time > 2
|
333
|
-
msg = "\r" + base_msg + ": #{humanize_time(time - start_time)} elapsed"
|
334
|
-
# TODO parse 'time - start_time' with humanize_time from common.rb
|
335
|
-
# once this method is not static
|
336
|
-
print msg + " " * 10
|
337
|
-
last_time = time
|
338
|
-
end
|
339
|
-
}
|
340
|
-
binfile.close
|
318
|
+
# Convert into UTF to compare time correctly
|
319
|
+
updated = (updated + updated.gmt_offset).utc unless updated.gmt?
|
320
|
+
last_updated = existent_jar_updated_time
|
341
321
|
|
342
|
-
|
343
|
-
|
322
|
+
if updated > last_updated
|
323
|
+
FileUtils.mkdir_p(jarfile_dest_path) unless File.exists?(jarfile_dest_path)
|
324
|
+
Dir.chdir jarfile_dest_path
|
344
325
|
|
345
|
-
|
346
|
-
|
347
|
-
|
326
|
+
File.open('VERSION', 'w') {|f|
|
327
|
+
if hourly
|
328
|
+
f.print "#{version} via hourly jar auto-update"
|
348
329
|
else
|
349
|
-
|
350
|
-
File.delete 'td-import.jar.new' if File.exists? 'td-import.jar.new'
|
330
|
+
f.print "#{version} via import:jar_update command"
|
351
331
|
end
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
def check_n_update_jar(hourly = false)
|
358
|
-
if hourly && \
|
359
|
-
File.exists?(last_jar_autoupdate_timestamp) && \
|
360
|
-
(Time.now - File.mtime(last_jar_autoupdate_timestamp)).to_i < (60 * 60 * 1) # every hour
|
361
|
-
return
|
362
|
-
end
|
363
|
-
jar_update(hourly)
|
364
|
-
FileUtils.touch File.join(jarfile_dest_path, "td-import-java.version")
|
365
|
-
end
|
366
|
-
|
367
|
-
private
|
368
|
-
def last_jar_autoupdate_timestamp
|
369
|
-
File.join(jarfile_dest_path, "td-import-java.version")
|
370
|
-
end
|
371
|
-
|
372
|
-
private
|
373
|
-
def existent_jar_updated_time
|
374
|
-
files = find_files("td-import-java.version", [jarfile_dest_path])
|
375
|
-
if files.empty?
|
376
|
-
return Time.at(0)
|
377
|
-
end
|
378
|
-
content = File.open(files.first).read
|
379
|
-
index = content.index(' ')
|
380
|
-
time = nil
|
381
|
-
if index.nil?
|
382
|
-
time = Time.at(0).utc
|
383
|
-
else
|
384
|
-
time = Time.parse(content[index+1..-1].strip).utc
|
385
|
-
end
|
386
|
-
time
|
387
|
-
end
|
332
|
+
}
|
333
|
+
File.open('td-import-java.version', 'w') {|f|
|
334
|
+
f.print "#{version} #{updated}"
|
335
|
+
}
|
388
336
|
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
locations.each {|loc|
|
395
|
-
files = Dir.glob("#{loc}/#{glob}")
|
396
|
-
break unless files.empty?
|
337
|
+
indicator = Command::TimeBasedDownloadProgressIndicator.new(
|
338
|
+
"Updating td-import.jar", Time.new.to_i, 2)
|
339
|
+
binfile = File.open 'td-import.jar.new', 'wb'
|
340
|
+
status = Updater.stream_fetch("#{maven_repo}/#{version}/td-import-#{version}-jar-with-dependencies.jar", binfile) {
|
341
|
+
indicator.update
|
397
342
|
}
|
398
|
-
|
399
|
-
|
343
|
+
binfile.close
|
344
|
+
indicator.finish()
|
400
345
|
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
346
|
+
if status
|
347
|
+
puts "Installed td-import.jar v#{version} in '#{jarfile_dest_path}'.\n"
|
348
|
+
File.rename 'td-import.jar.new', 'td-import.jar'
|
349
|
+
else
|
350
|
+
puts "Update of td-import.jar failed." unless ENV['TD_TOOLBELT_DEBUG'].nil?
|
351
|
+
File.delete 'td-import.jar.new' if File.exists? 'td-import.jar.new'
|
406
352
|
end
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
353
|
+
else
|
354
|
+
puts 'Installed td-import.jar is already at the latest version.' unless hourly
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
def check_n_update_jar(hourly = false)
|
359
|
+
if hourly
|
360
|
+
if !ENV['TD_TOOLBELT_JAR_UPDATE'].nil?
|
361
|
+
# also validates the TD_TOOLBELT_JAR_UPDATE environment variable value
|
362
|
+
if ENV['TD_TOOLBELT_JAR_UPDATE'] == "0"
|
363
|
+
puts "Warning: Bulk Import JAR auto-update disabled by TD_TOOLBELT_JAR_UPDATE=0"
|
364
|
+
return
|
365
|
+
elsif ENV['TD_TOOLBELT_JAR_UPDATE'] != "1"
|
366
|
+
raise UpdateError,
|
367
|
+
"Invalid value for TD_TOOLBELT_JAR_UPDATE environment variable. Only 0 and 1 are allowed."
|
368
|
+
end
|
415
369
|
end
|
416
|
-
jar.first
|
417
|
-
end
|
418
|
-
|
419
|
-
def find_logging_property
|
420
|
-
installed_path = File.join(File.expand_path('../..', File.dirname(__FILE__)), 'java')
|
421
370
|
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
[]
|
426
|
-
else
|
427
|
-
config.first
|
371
|
+
if File.exists?(last_jar_autoupdate_timestamp) && \
|
372
|
+
(Time.now - File.mtime(last_jar_autoupdate_timestamp)).to_i < (60 * 60 * 1) # every hour
|
373
|
+
return
|
428
374
|
end
|
429
375
|
end
|
430
|
-
|
431
|
-
|
432
|
-
end
|
376
|
+
jar_update(hourly)
|
377
|
+
FileUtils.touch last_jar_autoupdate_timestamp
|
378
|
+
end
|
379
|
+
|
380
|
+
private
|
381
|
+
def last_jar_autoupdate_timestamp
|
382
|
+
File.join(jarfile_dest_path, "td-import-java.version")
|
383
|
+
end
|
384
|
+
|
385
|
+
private
|
386
|
+
def existent_jar_updated_time
|
387
|
+
files = find_files("td-import-java.version", [jarfile_dest_path])
|
388
|
+
if files.empty?
|
389
|
+
return Time.at(0)
|
390
|
+
end
|
391
|
+
content = File.read(files.first)
|
392
|
+
index = content.index(' ')
|
393
|
+
time = nil
|
394
|
+
if index.nil?
|
395
|
+
time = Time.at(0).utc
|
396
|
+
else
|
397
|
+
time = Time.parse(content[index+1..-1].strip).utc
|
398
|
+
end
|
399
|
+
time
|
400
|
+
end
|
401
|
+
|
402
|
+
#
|
403
|
+
# Helpers
|
404
|
+
#
|
405
|
+
def find_files(glob, locations)
|
406
|
+
files = []
|
407
|
+
locations.each {|loc|
|
408
|
+
files = Dir.glob("#{loc}/#{glob}")
|
409
|
+
break unless files.empty?
|
410
|
+
}
|
411
|
+
files
|
412
|
+
end
|
413
|
+
|
414
|
+
def find_version_file
|
415
|
+
version = find_files('VERSION', [jarfile_dest_path])
|
416
|
+
if version.empty?
|
417
|
+
$stderr.puts "Cannot find VERSION file in '#{jarfile_dest_path}'."
|
418
|
+
exit 10
|
419
|
+
end
|
420
|
+
version.first
|
421
|
+
end
|
422
|
+
|
423
|
+
def find_td_import_jar
|
424
|
+
jar = find_files('td-import.jar', [jarfile_dest_path])
|
425
|
+
if jar.empty?
|
426
|
+
$stderr.puts "Cannot find td-import.jar in '#{jarfile_dest_path}'."
|
427
|
+
exit 10
|
428
|
+
end
|
429
|
+
jar.first
|
430
|
+
end
|
431
|
+
|
432
|
+
def find_logging_property
|
433
|
+
installed_path = File.join(File.expand_path('../..', File.dirname(__FILE__)), 'java')
|
434
|
+
|
435
|
+
config = find_files("logging.properties", [installed_path])
|
436
|
+
if config.empty?
|
437
|
+
puts "Cannot find 'logging.properties' file in '#{installed_path}'." unless ENV['TD_TOOLBELT_DEBUG'].nil?
|
438
|
+
[]
|
439
|
+
else
|
440
|
+
config.first
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
end # module Updater
|
445
|
+
end # module TreasureData
|