td-client 0.8.67 → 0.8.68
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/td/client.rb +12 -2
- data/lib/td/client/api.rb +51 -1040
- data/lib/td/client/api/access_control.rb +62 -0
- data/lib/td/client/api/account.rb +41 -0
- data/lib/td/client/api/bulk_import.rb +154 -0
- data/lib/td/client/api/database.rb +47 -0
- data/lib/td/client/api/export.rb +21 -0
- data/lib/td/client/api/import.rb +31 -0
- data/lib/td/client/api/job.rb +251 -0
- data/lib/td/client/api/partial_delete.rb +21 -0
- data/lib/td/client/api/result.rb +41 -0
- data/lib/td/client/api/schedule.rb +106 -0
- data/lib/td/client/api/server_status.rb +20 -0
- data/lib/td/client/api/table.rb +123 -0
- data/lib/td/client/api/user.rb +117 -0
- data/lib/td/client/api_error.rb +26 -0
- data/lib/td/client/model.rb +7 -5
- data/lib/td/client/version.rb +1 -1
- data/lib/td/core_ext/openssl/ssl/sslcontext/set_params.rb +18 -0
- data/spec/spec_helper.rb +8 -4
- data/spec/td/client/access_control_api_spec.rb +37 -0
- data/spec/td/client/account_api_spec.rb +34 -0
- data/spec/td/client/api_ssl_connection_spec.rb +10 -7
- data/spec/td/client/bulk_import_spec.rb +144 -0
- data/spec/td/client/import_api_spec.rb +73 -0
- data/spec/td/client/job_api_spec.rb +124 -1
- data/spec/td/client/result_api_spec.rb +23 -0
- data/spec/td/client/sched_api_spec.rb +33 -0
- data/spec/td/client/server_status_api_spec.rb +25 -0
- data/spec/td/client/table_api_spec.rb +45 -0
- data/spec/td/client/user_api_spec.rb +118 -0
- data/spec/td/client_sched_spec.rb +54 -0
- metadata +37 -4
@@ -0,0 +1,21 @@
|
|
1
|
+
class TreasureData::API
|
2
|
+
module PartialDelete
|
3
|
+
|
4
|
+
####
|
5
|
+
## Partial delete API
|
6
|
+
##
|
7
|
+
|
8
|
+
def partial_delete(db, table, to, from, opts={})
|
9
|
+
params = opts.dup
|
10
|
+
params['to'] = to.to_s
|
11
|
+
params['from'] = from.to_s
|
12
|
+
code, body, res = post("/v3/table/partialdelete/#{e db}/#{e table}", params)
|
13
|
+
if code != "200"
|
14
|
+
raise_error("Partial delete failed", res)
|
15
|
+
end
|
16
|
+
js = checked_json(body, %w[job_id])
|
17
|
+
return js['job_id'].to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class TreasureData::API
|
2
|
+
module Result
|
3
|
+
|
4
|
+
####
|
5
|
+
## Result API
|
6
|
+
##
|
7
|
+
|
8
|
+
def list_result
|
9
|
+
code, body, res = get("/v3/result/list")
|
10
|
+
if code != "200"
|
11
|
+
raise_error("List result table failed", res)
|
12
|
+
end
|
13
|
+
js = checked_json(body, %w[results])
|
14
|
+
result = []
|
15
|
+
js['results'].map {|m|
|
16
|
+
result << [m['name'], m['url'], nil] # same as database
|
17
|
+
}
|
18
|
+
return result
|
19
|
+
end
|
20
|
+
|
21
|
+
# => true
|
22
|
+
def create_result(name, url, opts={})
|
23
|
+
params = {'url'=>url}.merge(opts)
|
24
|
+
code, body, res = post("/v3/result/create/#{e name}", params)
|
25
|
+
if code != "200"
|
26
|
+
raise_error("Create result table failed", res)
|
27
|
+
end
|
28
|
+
return true
|
29
|
+
end
|
30
|
+
|
31
|
+
# => true
|
32
|
+
def delete_result(name)
|
33
|
+
code, body, res = post("/v3/result/delete/#{e name}")
|
34
|
+
if code != "200"
|
35
|
+
raise_error("Delete result table failed", res)
|
36
|
+
end
|
37
|
+
return true
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
class TreasureData::API
|
2
|
+
module Schedule
|
3
|
+
|
4
|
+
####
|
5
|
+
## Schedule API
|
6
|
+
##
|
7
|
+
|
8
|
+
# => start:String
|
9
|
+
def create_schedule(name, opts)
|
10
|
+
params = opts.update({:type=> opts[:type] || opts['type'] || 'hive'})
|
11
|
+
code, body, res = post("/v3/schedule/create/#{e name}", params)
|
12
|
+
if code != "200"
|
13
|
+
raise_error("Create schedule failed", res)
|
14
|
+
end
|
15
|
+
js = checked_json(body, %w[start])
|
16
|
+
return js['start']
|
17
|
+
end
|
18
|
+
|
19
|
+
# => cron:String, query:String
|
20
|
+
def delete_schedule(name)
|
21
|
+
code, body, res = post("/v3/schedule/delete/#{e name}")
|
22
|
+
if code != "200"
|
23
|
+
raise_error("Delete schedule failed", res)
|
24
|
+
end
|
25
|
+
js = checked_json(body, %w[])
|
26
|
+
return js['cron'], js["query"]
|
27
|
+
end
|
28
|
+
|
29
|
+
# => [(name:String, cron:String, query:String, database:String, result_url:String)]
|
30
|
+
def list_schedules
|
31
|
+
code, body, res = get("/v3/schedule/list")
|
32
|
+
if code != "200"
|
33
|
+
raise_error("List schedules failed", res)
|
34
|
+
end
|
35
|
+
js = checked_json(body, %w[schedules])
|
36
|
+
result = []
|
37
|
+
js['schedules'].each {|m|
|
38
|
+
name = m['name']
|
39
|
+
cron = m['cron']
|
40
|
+
query = m['query']
|
41
|
+
database = m['database']
|
42
|
+
result_url = m['result']
|
43
|
+
timezone = m['timezone']
|
44
|
+
delay = m['delay']
|
45
|
+
next_time = m['next_time']
|
46
|
+
priority = m['priority']
|
47
|
+
retry_limit = m['retry_limit']
|
48
|
+
result << [name, cron, query, database, result_url, timezone, delay, next_time, priority, retry_limit, nil] # same as database
|
49
|
+
}
|
50
|
+
return result
|
51
|
+
end
|
52
|
+
|
53
|
+
def update_schedule(name, params)
|
54
|
+
code, body, res = post("/v3/schedule/update/#{e name}", params)
|
55
|
+
if code != "200"
|
56
|
+
raise_error("Update schedule failed", res)
|
57
|
+
end
|
58
|
+
return nil
|
59
|
+
end
|
60
|
+
|
61
|
+
def history(name, from=0, to=nil)
|
62
|
+
params = {}
|
63
|
+
params['from'] = from.to_s if from
|
64
|
+
params['to'] = to.to_s if to
|
65
|
+
code, body, res = get("/v3/schedule/history/#{e name}", params)
|
66
|
+
if code != "200"
|
67
|
+
raise_error("List history failed", res)
|
68
|
+
end
|
69
|
+
js = checked_json(body, %w[history])
|
70
|
+
result = []
|
71
|
+
js['history'].each {|m|
|
72
|
+
job_id = m['job_id']
|
73
|
+
type = (m['type'] || '?').to_sym
|
74
|
+
database = m['database']
|
75
|
+
status = m['status']
|
76
|
+
query = m['query']
|
77
|
+
start_at = m['start_at']
|
78
|
+
end_at = m['end_at']
|
79
|
+
scheduled_at = m['scheduled_at']
|
80
|
+
result_url = m['result']
|
81
|
+
priority = m['priority']
|
82
|
+
result << [scheduled_at, job_id, type, status, query, start_at, end_at, result_url, priority, database]
|
83
|
+
}
|
84
|
+
return result
|
85
|
+
end
|
86
|
+
|
87
|
+
def run_schedule(name, time, num)
|
88
|
+
params = {}
|
89
|
+
params = {'num' => num} if num
|
90
|
+
code, body, res = post("/v3/schedule/run/#{e name}/#{e time}", params)
|
91
|
+
if code != "200"
|
92
|
+
raise_error("Run schedule failed", res)
|
93
|
+
end
|
94
|
+
js = checked_json(body, %w[jobs])
|
95
|
+
result = []
|
96
|
+
js['jobs'].each {|m|
|
97
|
+
job_id = m['job_id']
|
98
|
+
scheduled_at = m['scheduled_at']
|
99
|
+
type = (m['type'] || '?').to_sym
|
100
|
+
result << [job_id, type, scheduled_at]
|
101
|
+
}
|
102
|
+
return result
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class TreasureData::API
|
2
|
+
module ServerStatus
|
3
|
+
|
4
|
+
####
|
5
|
+
## Server Status API
|
6
|
+
##
|
7
|
+
|
8
|
+
# => status:String
|
9
|
+
def server_status
|
10
|
+
code, body, res = get('/v3/system/server_status')
|
11
|
+
if code != "200"
|
12
|
+
return "Server is down (#{code})"
|
13
|
+
end
|
14
|
+
js = checked_json(body, %w[status])
|
15
|
+
status = js['status']
|
16
|
+
return status
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
class TreasureData::API
|
2
|
+
module Table
|
3
|
+
|
4
|
+
####
|
5
|
+
## Table API
|
6
|
+
##
|
7
|
+
|
8
|
+
# => {name:String => [type:Symbol, count:Integer]}
|
9
|
+
def list_tables(db)
|
10
|
+
code, body, res = get("/v3/table/list/#{e db}")
|
11
|
+
if code != "200"
|
12
|
+
raise_error("List tables failed", res)
|
13
|
+
end
|
14
|
+
js = checked_json(body, %w[tables])
|
15
|
+
result = {}
|
16
|
+
js["tables"].map {|m|
|
17
|
+
name = m['name']
|
18
|
+
type = (m['type'] || '?').to_sym
|
19
|
+
count = (m['count'] || 0).to_i # TODO?
|
20
|
+
created_at = m['created_at']
|
21
|
+
updated_at = m['updated_at']
|
22
|
+
last_import = m['counter_updated_at']
|
23
|
+
last_log_timestamp = m['last_log_timestamp']
|
24
|
+
estimated_storage_size = m['estimated_storage_size'].to_i
|
25
|
+
schema = JSON.parse(m['schema'] || '[]')
|
26
|
+
expire_days = m['expire_days']
|
27
|
+
primary_key = m['primary_key']
|
28
|
+
primary_key_type = m['primary_key_type']
|
29
|
+
result[name] = [type, schema, count, created_at, updated_at, estimated_storage_size, last_import, last_log_timestamp, expire_days, primary_key, primary_key_type]
|
30
|
+
}
|
31
|
+
return result
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_log_or_item_table(db, table, type)
|
35
|
+
code, body, res = post("/v3/table/create/#{e db}/#{e table}/#{type}")
|
36
|
+
if code != "200"
|
37
|
+
raise_error("Create #{type} table failed", res)
|
38
|
+
end
|
39
|
+
return true
|
40
|
+
end
|
41
|
+
private :create_log_or_item_table
|
42
|
+
|
43
|
+
# => true
|
44
|
+
def create_log_table(db, table)
|
45
|
+
create_table(db, table, :log)
|
46
|
+
end
|
47
|
+
|
48
|
+
# => true
|
49
|
+
def create_item_table(db, table, primary_key, primary_key_type)
|
50
|
+
params = {'primary_key' => primary_key, 'primary_key_type' => primary_key_type}
|
51
|
+
create_table(db, table, :item, params)
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_table(db, table, type, params={})
|
55
|
+
schema = schema.to_s
|
56
|
+
code, body, res = post("/v3/table/create/#{e db}/#{e table}/#{type}", params)
|
57
|
+
if code != "200"
|
58
|
+
raise_error("Create #{type} table failed", res)
|
59
|
+
end
|
60
|
+
return true
|
61
|
+
end
|
62
|
+
private :create_table
|
63
|
+
|
64
|
+
# => true
|
65
|
+
def swap_table(db, table1, table2)
|
66
|
+
code, body, res = post("/v3/table/swap/#{e db}/#{e table1}/#{e table2}")
|
67
|
+
if code != "200"
|
68
|
+
raise_error("Swap tables failed", res)
|
69
|
+
end
|
70
|
+
return true
|
71
|
+
end
|
72
|
+
|
73
|
+
# => true
|
74
|
+
def update_schema(db, table, schema_json)
|
75
|
+
code, body, res = post("/v3/table/update-schema/#{e db}/#{e table}", {'schema'=>schema_json})
|
76
|
+
if code != "200"
|
77
|
+
raise_error("Create schema table failed", res)
|
78
|
+
end
|
79
|
+
return true
|
80
|
+
end
|
81
|
+
|
82
|
+
def update_expire(db, table, expire_days)
|
83
|
+
code, body, res = post("/v3/table/update/#{e db}/#{e table}", {'expire_days'=>expire_days})
|
84
|
+
if code != "200"
|
85
|
+
raise_error("Update table expiration failed", res)
|
86
|
+
end
|
87
|
+
return true
|
88
|
+
end
|
89
|
+
|
90
|
+
# => type:Symbol
|
91
|
+
def delete_table(db, table)
|
92
|
+
code, body, res = post("/v3/table/delete/#{e db}/#{e table}")
|
93
|
+
if code != "200"
|
94
|
+
raise_error("Delete table failed", res)
|
95
|
+
end
|
96
|
+
js = checked_json(body, %w[])
|
97
|
+
type = (js['type'] || '?').to_sym
|
98
|
+
return type
|
99
|
+
end
|
100
|
+
|
101
|
+
def tail(db, table, count, to, from, &block)
|
102
|
+
params = {'format' => 'msgpack'}
|
103
|
+
params['count'] = count.to_s if count
|
104
|
+
params['to'] = to.to_s if to
|
105
|
+
params['from'] = from.to_s if from
|
106
|
+
code, body, res = get("/v3/table/tail/#{e db}/#{e table}", params)
|
107
|
+
if code != "200"
|
108
|
+
raise_error("Tail table failed", res)
|
109
|
+
end
|
110
|
+
if block
|
111
|
+
MessagePack::Unpacker.new.feed_each(body, &block)
|
112
|
+
nil
|
113
|
+
else
|
114
|
+
result = []
|
115
|
+
MessagePack::Unpacker.new.feed_each(body) {|row|
|
116
|
+
result << row
|
117
|
+
}
|
118
|
+
return result
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
class TreasureData::API
|
2
|
+
module User
|
3
|
+
|
4
|
+
####
|
5
|
+
## User API
|
6
|
+
##
|
7
|
+
|
8
|
+
# apikey:String
|
9
|
+
def authenticate(user, password)
|
10
|
+
code, body, res = post("/v3/user/authenticate", {'user'=>user, 'password'=>password})
|
11
|
+
if code != "200"
|
12
|
+
if code == "400"
|
13
|
+
raise_error("Authentication failed", res, AuthError)
|
14
|
+
else
|
15
|
+
raise_error("Authentication failed", res)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
js = checked_json(body, %w[apikey])
|
19
|
+
apikey = js['apikey']
|
20
|
+
return apikey
|
21
|
+
end
|
22
|
+
|
23
|
+
# => [[name:String,organization:String,[user:String]]
|
24
|
+
def list_users
|
25
|
+
code, body, res = get("/v3/user/list")
|
26
|
+
if code != "200"
|
27
|
+
raise_error("List users failed", res)
|
28
|
+
end
|
29
|
+
js = checked_json(body, %w[users])
|
30
|
+
result = js["users"].map {|roleinfo|
|
31
|
+
name = roleinfo['name']
|
32
|
+
email = roleinfo['email']
|
33
|
+
[name, nil, nil, email] # set nil to org and role for API compatibility
|
34
|
+
}
|
35
|
+
return result
|
36
|
+
end
|
37
|
+
|
38
|
+
# => true
|
39
|
+
def add_user(name, org, email, password)
|
40
|
+
params = {'organization'=>org, :email=>email, :password=>password}
|
41
|
+
code, body, res = post("/v3/user/add/#{e name}", params)
|
42
|
+
if code != "200"
|
43
|
+
raise_error("Adding user failed", res)
|
44
|
+
end
|
45
|
+
return true
|
46
|
+
end
|
47
|
+
|
48
|
+
# => true
|
49
|
+
def remove_user(user)
|
50
|
+
code, body, res = post("/v3/user/remove/#{e user}")
|
51
|
+
if code != "200"
|
52
|
+
raise_error("Removing user failed", res)
|
53
|
+
end
|
54
|
+
return true
|
55
|
+
end
|
56
|
+
|
57
|
+
# => true
|
58
|
+
def change_email(user, email)
|
59
|
+
params = {'email' => email}
|
60
|
+
code, body, res = post("/v3/user/email/change/#{e user}", params)
|
61
|
+
if code != "200"
|
62
|
+
raise_error("Changing email failed", res)
|
63
|
+
end
|
64
|
+
return true
|
65
|
+
end
|
66
|
+
|
67
|
+
# => [apikey:String]
|
68
|
+
def list_apikeys(user)
|
69
|
+
code, body, res = get("/v3/user/apikey/list/#{e user}")
|
70
|
+
if code != "200"
|
71
|
+
raise_error("List API keys failed", res)
|
72
|
+
end
|
73
|
+
js = checked_json(body, %w[apikeys])
|
74
|
+
return js['apikeys']
|
75
|
+
end
|
76
|
+
|
77
|
+
# => true
|
78
|
+
def add_apikey(user)
|
79
|
+
code, body, res = post("/v3/user/apikey/add/#{e user}")
|
80
|
+
if code != "200"
|
81
|
+
raise_error("Adding API key failed", res)
|
82
|
+
end
|
83
|
+
return true
|
84
|
+
end
|
85
|
+
|
86
|
+
# => true
|
87
|
+
def remove_apikey(user, apikey)
|
88
|
+
params = {'apikey' => apikey}
|
89
|
+
code, body, res = post("/v3/user/apikey/remove/#{e user}", params)
|
90
|
+
if code != "200"
|
91
|
+
raise_error("Removing API key failed", res)
|
92
|
+
end
|
93
|
+
return true
|
94
|
+
end
|
95
|
+
|
96
|
+
# => true
|
97
|
+
def change_password(user, password)
|
98
|
+
params = {'password' => password}
|
99
|
+
code, body, res = post("/v3/user/password/change/#{e user}", params)
|
100
|
+
if code != "200"
|
101
|
+
raise_error("Changing password failed", res)
|
102
|
+
end
|
103
|
+
return true
|
104
|
+
end
|
105
|
+
|
106
|
+
# => true
|
107
|
+
def change_my_password(old_password, password)
|
108
|
+
params = {'old_password' => old_password, 'password' => password}
|
109
|
+
code, body, res = post("/v3/user/password/change", params)
|
110
|
+
if code != "200"
|
111
|
+
raise_error("Changing password failed", res)
|
112
|
+
end
|
113
|
+
return true
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module TreasureData
|
2
|
+
|
3
|
+
class ParameterValidationError < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
# Generic API error
|
7
|
+
class APIError < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
# 401 API errors
|
11
|
+
class AuthError < APIError
|
12
|
+
end
|
13
|
+
|
14
|
+
# 403 API errors, used for database permissions
|
15
|
+
class ForbiddenError < APIError
|
16
|
+
end
|
17
|
+
|
18
|
+
# 409 API errors
|
19
|
+
class AlreadyExistsError < APIError
|
20
|
+
end
|
21
|
+
|
22
|
+
# 404 API errors
|
23
|
+
class NotFoundError < APIError
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|