iij-dag-client 1.0.1
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 +7 -0
- data/.gitignore +18 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +174 -0
- data/Rakefile +43 -0
- data/config/settings.yml +11 -0
- data/iij-dag-client.gemspec +31 -0
- data/lib/dag.rb +33 -0
- data/lib/dag/client.rb +36 -0
- data/lib/dag/client/api.rb +295 -0
- data/lib/dag/client/api/cluster.rb +111 -0
- data/lib/dag/client/api/database.rb +58 -0
- data/lib/dag/client/api/job.rb +116 -0
- data/lib/dag/client/api/list_params.rb +36 -0
- data/lib/dag/client/api/rest_parameter.rb +149 -0
- data/lib/dag/client/api/storage.rb +354 -0
- data/lib/dag/client/api/storage_result.rb +52 -0
- data/lib/dag/client/api/table.rb +131 -0
- data/lib/dag/client/cluster.rb +26 -0
- data/lib/dag/client/cluster_validation.rb +59 -0
- data/lib/dag/client/database.rb +79 -0
- data/lib/dag/client/exception.rb +43 -0
- data/lib/dag/client/job.rb +56 -0
- data/lib/dag/client/job_validation.rb +22 -0
- data/lib/dag/client/model.rb +9 -0
- data/lib/dag/client/model/bucket.rb +20 -0
- data/lib/dag/client/model/bucket_collection.rb +34 -0
- data/lib/dag/client/model/cluster.rb +100 -0
- data/lib/dag/client/model/cluster_collection.rb +76 -0
- data/lib/dag/client/model/database.rb +34 -0
- data/lib/dag/client/model/database_collection.rb +51 -0
- data/lib/dag/client/model/job.rb +125 -0
- data/lib/dag/client/model/job_collection.rb +114 -0
- data/lib/dag/client/model/object.rb +56 -0
- data/lib/dag/client/model/object_collection.rb +64 -0
- data/lib/dag/client/model/table.rb +55 -0
- data/lib/dag/client/model/table_collection.rb +60 -0
- data/lib/dag/client/storage.rb +41 -0
- data/lib/dag/client/table.rb +16 -0
- data/lib/dag/client/version.rb +5 -0
- data/lib/dag/settings.rb +9 -0
- metadata +210 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
module Dag
|
2
|
+
class ClusterCollection < Model
|
3
|
+
include Enumerable
|
4
|
+
include Dag::Client::ClusterValidation
|
5
|
+
|
6
|
+
def initialize(api)
|
7
|
+
super(api)
|
8
|
+
end
|
9
|
+
|
10
|
+
#
|
11
|
+
# == Parameters ==
|
12
|
+
# <tt>status</tt> - 'init', 'stopped', restarting, 'norm', 'failed', 'ptfailed', 'error', 'released'
|
13
|
+
def where(params)
|
14
|
+
validate_cluster_param_keys(params)
|
15
|
+
|
16
|
+
@status = params[:status] if params[:status]
|
17
|
+
@type = params[:type] if params[:type]
|
18
|
+
@cluster_name = params[:cluster_name] if params[:cluster_name].present?
|
19
|
+
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def order(o)
|
24
|
+
result = o.downcase.to_s
|
25
|
+
unless ['asc', 'desc'].include?(result)
|
26
|
+
raise Dag::Client::ParameterInvalid.new("Invalid order condition: #{o}")
|
27
|
+
end
|
28
|
+
|
29
|
+
@order = result
|
30
|
+
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def each
|
35
|
+
marker = nil
|
36
|
+
truncated = false
|
37
|
+
begin
|
38
|
+
cluster_info_list = @api.cluster_info_list(make_options(marker))
|
39
|
+
cluster_info_list['clusters'].each do |cluster_info|
|
40
|
+
yield Dag::Cluster.new(@api, cluster_info)
|
41
|
+
end
|
42
|
+
truncated = cluster_info_list['isTruncated']
|
43
|
+
marker = cluster_info_list['nextMarker']
|
44
|
+
end while truncated
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def make_options(marker = nil)
|
50
|
+
options = { max: 100 }
|
51
|
+
if marker
|
52
|
+
options = options.merge(marker: marker)
|
53
|
+
end
|
54
|
+
|
55
|
+
if @order
|
56
|
+
options = options.merge(order: @order)
|
57
|
+
end
|
58
|
+
|
59
|
+
if @status
|
60
|
+
status = @status.respond_to?(:join) ? @status.join(",") : @status
|
61
|
+
options = options.merge(status: status)
|
62
|
+
end
|
63
|
+
|
64
|
+
if @type
|
65
|
+
options = options.merge(type: @type)
|
66
|
+
end
|
67
|
+
|
68
|
+
if @cluster_name
|
69
|
+
options = options.merge(cluster_name: @cluster_name)
|
70
|
+
end
|
71
|
+
|
72
|
+
options
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Dag
|
2
|
+
class Database < Model
|
3
|
+
def initialize(api, cluster_name, db_name, cluster_status: nil)
|
4
|
+
super(api)
|
5
|
+
|
6
|
+
@cluster_name = cluster_name
|
7
|
+
@cluster_status = cluster_status
|
8
|
+
@db_name = db_name
|
9
|
+
@name = @db_name
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :cluster_name, :db_name, :name
|
13
|
+
|
14
|
+
def delete
|
15
|
+
@api.delete_database(@cluster_name, @name)
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# == parameters ==
|
20
|
+
# * <tt>label</tt> - label
|
21
|
+
# * <tt>input_object_keys</tt> - array of object_keys. ex ["#{bucket}/${big_object1}", "#{bucket}/${big_object2}"]
|
22
|
+
# * <tt>input_format</tt> - 'csv' or 'tsv' or 'json'
|
23
|
+
# * <tt>schema</tt> - schema
|
24
|
+
def split(tbl_name, params)
|
25
|
+
split_info = @api.split_table(@cluster_name, @db_name, tbl_name, params)
|
26
|
+
job_id = split_info['queryId']
|
27
|
+
|
28
|
+
query_info = @api.query_info(job_id)
|
29
|
+
Dag::Job.new(@api, query_info)
|
30
|
+
end
|
31
|
+
|
32
|
+
include Dag::Client::Table
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Dag
|
2
|
+
class DatabaseCollection < Model
|
3
|
+
include Enumerable
|
4
|
+
include Dag::Client::ClusterValidation
|
5
|
+
|
6
|
+
attr_reader :cluster_name
|
7
|
+
|
8
|
+
def initialize(api, cluster_name, cluster_status: nil)
|
9
|
+
super(api)
|
10
|
+
|
11
|
+
@cluster_name = cluster_name
|
12
|
+
@cluster_status = cluster_status
|
13
|
+
end
|
14
|
+
|
15
|
+
def each
|
16
|
+
validate_cluster
|
17
|
+
|
18
|
+
find_from_api unless find?
|
19
|
+
|
20
|
+
@databases.each do |db_name|
|
21
|
+
yield Dag::Database.new(@api, @cluster_name, db_name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def create(db_name)
|
26
|
+
validate_cluster
|
27
|
+
|
28
|
+
@api.create_database(@cluster_name, db_name)
|
29
|
+
Dag::Database.new(@api, @cluster_name, db_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def find_from_api
|
35
|
+
dbs = []
|
36
|
+
tmp = {}
|
37
|
+
params = { "max" => 100 }
|
38
|
+
begin
|
39
|
+
params.merge!({"marker" => tmp["nextMarker"]}) rescue nil
|
40
|
+
tmp = @api.database_list(@cluster_name , params: params)
|
41
|
+
dbs += tmp["databases"]
|
42
|
+
end while tmp["isTruncated"]
|
43
|
+
|
44
|
+
@databases = dbs
|
45
|
+
end
|
46
|
+
|
47
|
+
def find?
|
48
|
+
@databases.present?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Dag
|
2
|
+
class Job < Model
|
3
|
+
def initialize(api, job_info)
|
4
|
+
super(api)
|
5
|
+
update_parameters(job_info)
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :id, :status, :dsl, :process_engine, :start_at, :type, :cluster, :cluster_rebooted, :label, :stage, :progress,
|
9
|
+
:access_key_id, :query, :output_format, :output_resource_path, :job_id, :schema, :input_object_keys,
|
10
|
+
:input_format, :output_database, :output_table
|
11
|
+
|
12
|
+
def finished?
|
13
|
+
@status == 'finished'
|
14
|
+
end
|
15
|
+
|
16
|
+
def running?
|
17
|
+
@status == 'running'
|
18
|
+
end
|
19
|
+
|
20
|
+
def split?
|
21
|
+
@type == 'split'
|
22
|
+
end
|
23
|
+
|
24
|
+
def hive?
|
25
|
+
@type == 'select'
|
26
|
+
end
|
27
|
+
|
28
|
+
def cluster_rebooted?
|
29
|
+
!!@cluster_rebooted
|
30
|
+
end
|
31
|
+
|
32
|
+
def reload
|
33
|
+
job_info = @api.query_info(@id)
|
34
|
+
update_parameters(job_info)
|
35
|
+
end
|
36
|
+
|
37
|
+
def kill
|
38
|
+
validate_cancel_condition
|
39
|
+
@api.query_cancel(@id)
|
40
|
+
end
|
41
|
+
|
42
|
+
alias :cancel :kill
|
43
|
+
|
44
|
+
def download_urls(time_limit = 30)
|
45
|
+
raise Dag::Client::StatusInvalid.new("job status is not finished") unless finished?
|
46
|
+
expire_at = time_limit.minutes.since.to_i
|
47
|
+
object_uri = URI.parse(@output_resource_path)
|
48
|
+
bucket = object_uri.host
|
49
|
+
object_path = object_uri.path[1..-1]
|
50
|
+
object_path += '/' unless object_path.end_with? '/'
|
51
|
+
bucket_objects = @api.objects(bucket, prefix: object_path).objects
|
52
|
+
bucket_objects.map do |object|
|
53
|
+
path = if @api.force_path_style?
|
54
|
+
"/#{bucket}/#{object}"
|
55
|
+
else
|
56
|
+
"/#{object}"
|
57
|
+
end
|
58
|
+
|
59
|
+
parameters = {
|
60
|
+
"Expires" => expire_at,
|
61
|
+
"IIJGIOAccessKeyId" => @api.apikey,
|
62
|
+
"Signature" => @api.download_signature(expire_at, bucket, path)
|
63
|
+
}
|
64
|
+
|
65
|
+
uri = URI.parse(@api.storage_api)
|
66
|
+
url = if @api.force_path_style?
|
67
|
+
"http://#{uri.host}"
|
68
|
+
else
|
69
|
+
"http://#{bucket}.#{uri.host}"
|
70
|
+
end
|
71
|
+
url += ":#{uri.port}" unless uri.port == 80 || uri.port == 443
|
72
|
+
|
73
|
+
File.join(url, "#{path}?#{parameters.to_param}")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def log
|
78
|
+
validate_log_condition
|
79
|
+
log_info = @api.query_log(@id)
|
80
|
+
log_info ? log_info['log'] : ''
|
81
|
+
end
|
82
|
+
|
83
|
+
def validate_log_condition
|
84
|
+
if split?
|
85
|
+
raise Dag::Client::JobTypeInvalid.new("job type is not select")
|
86
|
+
end
|
87
|
+
|
88
|
+
if cluster_rebooted?
|
89
|
+
raise Dag::Client::ClusterRebooted.new("cluster is rebooted")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def validate_cancel_condition
|
94
|
+
unless running?
|
95
|
+
raise Dag::Client::StatusInvalid.new("job status is not running")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def update_parameters(job)
|
102
|
+
@id = job['id']
|
103
|
+
@status = job['status']
|
104
|
+
@process_engine = job['processEngine']
|
105
|
+
@dsl = job['dsl']
|
106
|
+
@cluster = job['clusterName']
|
107
|
+
@cluster_rebooted = job['clusterRebooted']
|
108
|
+
@start_at = Time.parse(job['startTime']) if job['startTime']
|
109
|
+
@access_key_id = job['accessKeyId']
|
110
|
+
@query = job['query']
|
111
|
+
@output_format = job['outputFormat']
|
112
|
+
@output_resource_path = job['outputResourcePath']
|
113
|
+
@type = job['type']
|
114
|
+
@label = job['label']
|
115
|
+
@stage = job['stage']
|
116
|
+
@progress = job['progress']
|
117
|
+
@job_id = job['jobId']
|
118
|
+
@schema = job['schema']
|
119
|
+
@input_object_keys = job['inputObjectKeys']
|
120
|
+
@input_format = job['inputFormat']
|
121
|
+
@output_database = job['outputDatabase']
|
122
|
+
@output_table = job['outputTable']
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Dag
|
2
|
+
class JobCollection < Model
|
3
|
+
include Enumerable
|
4
|
+
include Dag::Client::JobValidation
|
5
|
+
|
6
|
+
def initialize(api)
|
7
|
+
super(api)
|
8
|
+
end
|
9
|
+
|
10
|
+
def where(params = {})
|
11
|
+
validate_job_param_keys(params)
|
12
|
+
|
13
|
+
@status = params[:status] if params[:status].present?
|
14
|
+
@type = params[:type] if params[:type].present?
|
15
|
+
@cluster_name = params[:cluster_name] if params[:cluster_name].present?
|
16
|
+
@label = params[:label] if params[:label].present?
|
17
|
+
@cluster_rebooted = params[:cluster_rebooted]
|
18
|
+
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def order(o)
|
23
|
+
result = o.downcase.to_s
|
24
|
+
unless ['asc', 'desc'].include?(result)
|
25
|
+
raise Dag::Client::ParameterInvalid.new("Invalid order condition: #{o}")
|
26
|
+
end
|
27
|
+
|
28
|
+
@order = result
|
29
|
+
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def limit(number = 100)
|
34
|
+
@limit = number.to_i
|
35
|
+
max = 100
|
36
|
+
|
37
|
+
if number > max
|
38
|
+
@max = []
|
39
|
+
(number / max).times { @max << max }
|
40
|
+
if rem = (number % max)
|
41
|
+
@max << rem if rem != 0
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def each
|
49
|
+
if @limit
|
50
|
+
count, i = 0, 0
|
51
|
+
total = @max ? @max.inject(:+) : @limit
|
52
|
+
end
|
53
|
+
|
54
|
+
marker = nil
|
55
|
+
truncated = false
|
56
|
+
begin
|
57
|
+
@limit = @max[i] if @max
|
58
|
+
job_info_list = @api.query_info_list(make_options(marker))
|
59
|
+
job_info_list['queries'].each do |job_info|
|
60
|
+
yield Dag::Job.new(@api, job_info)
|
61
|
+
end
|
62
|
+
truncated = job_info_list['isTruncated']
|
63
|
+
marker = job_info_list['nextMarker']
|
64
|
+
|
65
|
+
if @limit
|
66
|
+
i += 1
|
67
|
+
count += @limit
|
68
|
+
break if total <= count
|
69
|
+
end
|
70
|
+
end while truncated
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def make_options(marker = nil)
|
76
|
+
options = { max: 100 }
|
77
|
+
|
78
|
+
if marker
|
79
|
+
options = options.merge(marker: marker)
|
80
|
+
end
|
81
|
+
|
82
|
+
if @limit
|
83
|
+
options = options.merge(max: @limit)
|
84
|
+
end
|
85
|
+
|
86
|
+
if @order
|
87
|
+
options = options.merge(order: @order)
|
88
|
+
end
|
89
|
+
|
90
|
+
if @status
|
91
|
+
status = @status.respond_to?(:join) ? @status.join(",") : @status
|
92
|
+
options = options.merge(status: status)
|
93
|
+
end
|
94
|
+
|
95
|
+
if @type
|
96
|
+
options = options.merge(type: @type)
|
97
|
+
end
|
98
|
+
|
99
|
+
if @cluster_name
|
100
|
+
options = options.merge(cluster_name: @cluster_name)
|
101
|
+
end
|
102
|
+
|
103
|
+
if @label
|
104
|
+
options = options.merge(label_prefix: @label)
|
105
|
+
end
|
106
|
+
|
107
|
+
unless @cluster_rebooted.nil?
|
108
|
+
options = options.merge(cluster_rebooted: @cluster_rebooted)
|
109
|
+
end
|
110
|
+
|
111
|
+
options
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Dag
|
2
|
+
class Object < Model
|
3
|
+
def initialize(api, bucket_name, object_name, opts = {})
|
4
|
+
super(api)
|
5
|
+
@bucket = bucket_name
|
6
|
+
@name = object_name
|
7
|
+
@opts = opts
|
8
|
+
end
|
9
|
+
|
10
|
+
def name
|
11
|
+
@name
|
12
|
+
end
|
13
|
+
|
14
|
+
def size
|
15
|
+
@opts["Size"][0].to_i
|
16
|
+
end
|
17
|
+
|
18
|
+
def etag
|
19
|
+
@opts["ETag"][0]
|
20
|
+
end
|
21
|
+
|
22
|
+
def lastmodified
|
23
|
+
Time.parse(@opts["LastModified"][0])
|
24
|
+
end
|
25
|
+
|
26
|
+
def read(range = nil)
|
27
|
+
@api.get_object(@bucket, @name, range)
|
28
|
+
end
|
29
|
+
|
30
|
+
def write(data, options = {})
|
31
|
+
if data.is_a?(String)
|
32
|
+
data = StringIO.new(data)
|
33
|
+
elsif data.is_a?(Pathname)
|
34
|
+
data = File.open(data, 'rb')
|
35
|
+
elsif data.respond_to?(:read) && data.respond_to?(:eof?)
|
36
|
+
end
|
37
|
+
|
38
|
+
unless options[:multipart]
|
39
|
+
@api.create_object(@bucket, @name, options) do
|
40
|
+
data
|
41
|
+
end
|
42
|
+
else
|
43
|
+
@api.create_multipart_object(@bucket, @name, options) do
|
44
|
+
data
|
45
|
+
end
|
46
|
+
end
|
47
|
+
data.close
|
48
|
+
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def delete
|
53
|
+
@api.delete_object(@bucket, @name)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|