cnvrg 0.0.145 → 0.0.146

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,26 @@
1
+ require 'thor'
2
+
3
+ class SubCommandBase < Thor
4
+ def self.banner(command, namespace = nil, subcommand = false)
5
+ "#{basename} #{subcommand_prefix} #{command.usage}"
6
+ end
7
+
8
+ def self.subcommand_prefix
9
+ self.name.gsub(%r{.*::}, '').gsub(%r{^[A-Z]}) { |match| match[0].downcase }.gsub(%r{[A-Z]}) { |match| "-#{match[0].downcase}" }
10
+ end
11
+ end
12
+ module Cnvrg
13
+ class Data < SubCommandBase
14
+ desc "init", "init data folder"
15
+
16
+ def init
17
+ puts "im in init"
18
+ end
19
+ desc "upload", "upload data folder"
20
+
21
+ def upload
22
+ puts "im in upload"
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,376 @@
1
+ require 'mimemagic'
2
+ require 'aws-sdk'
3
+ require 'URLcrypt'
4
+
5
+ module Cnvrg
6
+ class Datafiles
7
+
8
+ LARGE_FILE=1024*1024*5
9
+ attr_reader :base_resource
10
+
11
+ def initialize(owner, dataset_slug)
12
+ @dataset_slug = dataset_slug
13
+ @owner = owner
14
+ @base_resource = "users/#{owner}/datasets/#{dataset_slug}/"
15
+ end
16
+
17
+ def upload_file(absolute_path, relative_path, commit_sha1)
18
+ file_name = File.basename relative_path
19
+ file_size = File.size(absolute_path).to_f
20
+ mime_type = MimeMagic.by_path(absolute_path)
21
+ content_type = !(mime_type.nil? or mime_type.text?) ? mime_type.type : "text/plain"
22
+ upload_resp = Cnvrg::API.request(@base_resource + "upload_file", 'POST_FILE', {absolute_path: absolute_path, relative_path: relative_path,
23
+ commit_sha1: commit_sha1, file_name: file_name,
24
+ file_size: file_size, file_content_type: content_type})
25
+ if Cnvrg::CLI.is_response_success(upload_resp, false)
26
+ path = upload_resp["result"]["path"]
27
+ if file_size.to_f>= Cnvrg::Files::LARGE_FILE.to_f
28
+ s3_res = upload_large_files_s3(upload_resp, absolute_path)
29
+ else
30
+ s3_res = upload_small_files_s3(path, absolute_path, content_type)
31
+ end
32
+ if s3_res
33
+ Cnvrg::API.request(@base_resource + "update_s3", 'POST', {path: path, commit_id: upload_resp["result"]["commit_id"],
34
+ blob_id: upload_resp["result"]["id"]})
35
+ return true
36
+ end
37
+ end
38
+ return false
39
+ end
40
+ def upload_log_file(absolute_path, relative_path,log_date)
41
+ file_name = File.basename relative_path
42
+ file_size = File.size(absolute_path).to_f
43
+ content_type = "text/x-log"
44
+ upload_resp = Cnvrg::API.request("/users/#{@owner}/" + "upload_cli_log", 'POST_FILE', {absolute_path: absolute_path, relative_path: relative_path,
45
+ file_name: file_name,log_date:log_date,
46
+ file_size: file_size, file_content_type: content_type})
47
+ if Cnvrg::CLI.is_response_success(upload_resp, false)
48
+ path = upload_resp["result"]["path"]
49
+ s3_res = upload_small_files_s3(path, absolute_path, "text/plain")
50
+ end
51
+ if s3_res
52
+ return true
53
+ end
54
+ return false
55
+
56
+ end
57
+ def upload_exec_file(absolute_path,image_name,commit_id)
58
+ file_name = File.basename absolute_path
59
+ file_size = File.size(absolute_path).to_f
60
+ content_type = "application/zip"
61
+ begin
62
+ upload_resp = Cnvrg::API.request("users/#{@owner}/images/" + "upload_config", 'POST_FILE', {relative_path: absolute_path,
63
+ file_name: file_name,
64
+ image_name:image_name,
65
+ file_size: file_size,
66
+ file_content_type: content_type,
67
+ project_slug: @project_slug,
68
+ commit_id:commit_id})
69
+ # puts upload_resp
70
+ if Cnvrg::CLI.is_response_success(upload_resp, false)
71
+ if upload_resp["result"]["image"] == -1
72
+ return -1
73
+ end
74
+ path = upload_resp["result"]["path"]
75
+ s3_res = upload_small_files_s3(path, absolute_path, content_type)
76
+
77
+ end
78
+ if s3_res
79
+ return upload_resp["result"]["id"]
80
+ end
81
+ return false
82
+ rescue SignalException
83
+
84
+ say "\nAborting"
85
+ exit(1)
86
+ end
87
+
88
+ end
89
+
90
+
91
+
92
+ def upload_image(absolute_path, image_name, owner, is_public, is_base,dpkg,libraries,bash,message,commit_id)
93
+ file_name = File.basename absolute_path
94
+ file_size = File.size(absolute_path).to_f
95
+ if is_base
96
+
97
+ content_type = "application/zip"
98
+ else
99
+ content_type = "application/gzip"
100
+ end
101
+ begin
102
+ upload_resp = Cnvrg::API.request("users/#{owner}/images/" + "upload_cnvrg", 'POST_FILE', {relative_path: absolute_path,
103
+ file_name: file_name,
104
+ image_name: image_name,
105
+ file_size: file_size,
106
+ file_content_type: content_type,
107
+ is_public: is_public,
108
+ project_slug: @project_slug,
109
+ commit_id:commit_id ,
110
+ dpkg: dpkg,
111
+ py2: libraries,
112
+ py3: libraries,
113
+
114
+ bash_history: bash,
115
+ commit_message:message,
116
+ is_base: is_base})
117
+ # puts upload_resp
118
+ if Cnvrg::CLI.is_response_success(upload_resp, false)
119
+ path = upload_resp["result"]["path"]
120
+ s3_res = upload_small_files_s3(path, absolute_path, content_type)
121
+ if s3_res
122
+ commit_resp = Cnvrg::API.request("users/#{owner}/images/#{upload_resp["result"]["id"]}/" + "commit", 'GET')
123
+ if Cnvrg::CLI.is_response_success(commit_resp, false)
124
+ return commit_resp["result"]["image"]
125
+ else
126
+ return false
127
+ end
128
+
129
+ end
130
+ end
131
+ return false
132
+ rescue =>e
133
+ end
134
+
135
+ end
136
+ def upload_cnvrg_image(absolute_path, image_name, owner, is_public, is_base,dpkg,libraries,bash,message)
137
+ file_name = File.basename absolute_path
138
+ file_size = File.size(absolute_path).to_f
139
+ if is_base
140
+
141
+ content_type = "application/zip"
142
+ else
143
+ content_type = "application/gzip"
144
+ end
145
+ begin
146
+ upload_resp = Cnvrg::API.request("users/#{owner}/images/" + "upload_cnvrg", 'POST_FILE', {relative_path: absolute_path,
147
+ file_name: file_name,
148
+ image_name: image_name,
149
+ file_size: file_size,
150
+ file_content_type: content_type,
151
+ is_public: is_public,
152
+ dpkg: dpkg,
153
+ libraries: libraries,
154
+ bash_history: bash,
155
+ commit_message:message,
156
+ is_base: is_base})
157
+ # puts upload_resp
158
+ if Cnvrg::CLI.is_response_success(upload_resp, false)
159
+ path = upload_resp["result"]["path"]
160
+ s3_res = upload_small_files_s3(path, absolute_path, content_type)
161
+ if s3_res
162
+ commit_resp = Cnvrg::API.request("users/#{owner}/images/#{upload_resp["result"]["id"]}/" + "commit", 'GET')
163
+ if Cnvrg::CLI.is_response_success(commit_resp, false)
164
+ return commit_resp["result"]["image"]
165
+ else
166
+ return false
167
+ end
168
+
169
+ end
170
+ end
171
+ return false
172
+ rescue =>e
173
+ end
174
+
175
+ end
176
+
177
+ def download_image(file_path_to_store, image_slug, owner)
178
+
179
+
180
+ download_resp = Cnvrg::API.request("users/#{owner}/images/#{image_slug}/" + "download", 'GET')
181
+ path = download_resp["result"]["path"]
182
+
183
+ if Cnvrg::CLI.is_response_success(download_resp, false)
184
+ begin
185
+ open(file_path_to_store, 'wb') do |file|
186
+ file << open(path).read
187
+ end
188
+
189
+ return true
190
+ rescue => e
191
+ return false
192
+ end
193
+
194
+ return true
195
+ else
196
+ return false
197
+ end
198
+
199
+
200
+ end
201
+
202
+ def upload_large_files_s3(upload_resp, file_path)
203
+ begin
204
+ sts_path = upload_resp["result"]["path_sts"]
205
+ uri = URI.parse(sts_path)
206
+ http_object = Net::HTTP.new(uri.host, uri.port)
207
+ http_object.use_ssl = true if uri.scheme == 'https'
208
+ request = Net::HTTP::Get.new(sts_path)
209
+
210
+ body = ""
211
+ http_object.start do |http|
212
+ response = http.request request
213
+ body = response.read_body
214
+ end
215
+ URLcrypt::key = [body].pack('H*')
216
+ puts "file_size: #{File.size(file_path).to_f}"
217
+ puts "start_time: #{Time.now}"
218
+ s3 = Aws::S3::Resource.new(
219
+ :access_key_id => URLcrypt.decrypt(upload_resp["result"]["sts_a"]),
220
+ :secret_access_key => URLcrypt.decrypt(upload_resp["result"]["sts_s"]),
221
+ :session_token => URLcrypt.decrypt(upload_resp["result"]["sts_st"]),
222
+ :region => URLcrypt.decrypt(upload_resp["result"]["region"]))
223
+ resp = s3.bucket(URLcrypt.decrypt(upload_resp["result"]["bucket"])).
224
+ object(upload_resp["result"]["path"]+"/"+File.basename(file_path)).
225
+ upload_file(file_path,{:use_accelerate_endpoint=>true})
226
+ puts "end_time: #{Time.now}"
227
+
228
+ return resp
229
+ rescue =>e
230
+ puts e
231
+ return false
232
+
233
+ end
234
+ return true
235
+
236
+ end
237
+
238
+ def upload_small_files_s3(url_path, file_path, content_type)
239
+ url = URI.parse(url_path)
240
+ file = File.open(file_path, "rb")
241
+ body = file.read
242
+ begin
243
+ Net::HTTP.start(url.host) do |http|
244
+ http.send_request("PUT", url.request_uri, body, {
245
+ "content-type" => content_type,
246
+ })
247
+ end
248
+ return true
249
+ rescue Interrupt
250
+ return false
251
+ rescue
252
+ return false
253
+ end
254
+ end
255
+
256
+ def upload_url(file_path)
257
+ response = Cnvrg::API.request(@base_resource + "upload_url", 'POST', {file_s3_path: file_path})
258
+ if Cnvrg::CLI.is_response_success(response, false)
259
+ return response
260
+ else
261
+ return nil
262
+ end
263
+
264
+ end
265
+
266
+ def delete_file(absolute_path, relative_path, commit_sha1)
267
+ response = Cnvrg::API.request(@base_resource + "delete_file", 'DELETE', {absolute_path: absolute_path, relative_path: relative_path, commit_sha1: commit_sha1})
268
+ return Cnvrg::CLI.is_response_success(response, false)
269
+ end
270
+
271
+ def delete_dir(absolute_path, relative_path, commit_sha1)
272
+ response = Cnvrg::API.request(@base_resource + "delete_dir", 'DELETE', {absolute_path: absolute_path, relative_path: relative_path, commit_sha1: commit_sha1})
273
+ return Cnvrg::CLI.is_response_success(response, false)
274
+ end
275
+
276
+ def create_dir(absolute_path, relative_path, commit_sha1)
277
+ response = Cnvrg::API.request(@base_resource + "create_dir", 'POST', {absolute_path: absolute_path, relative_path: relative_path, commit_sha1: commit_sha1})
278
+ return Cnvrg::CLI.is_response_success(response, false)
279
+ end
280
+ def download_file_s3(absolute_path, relative_path, project_home, conflict=false)
281
+ begin
282
+ res = Cnvrg::API.request(@base_resource + "download_file", 'POST', {absolute_path: absolute_path, relative_path: relative_path})
283
+ Cnvrg::CLI.is_response_success(res, false)
284
+ if res["result"]
285
+ download_resp = res
286
+ filename = download_resp["result"]["filename"]
287
+
288
+ absolute_path += ".conflict" if conflict
289
+ sts_path = download_resp["result"]["path_sts"]
290
+ uri = URI.parse(sts_path)
291
+ http_object = Net::HTTP.new(uri.host, uri.port)
292
+ http_object.use_ssl = true if uri.scheme == 'https'
293
+ request = Net::HTTP::Get.new(sts_path)
294
+
295
+ body = ""
296
+ http_object.start do |http|
297
+ response = http.request request
298
+ body = response.read_body
299
+ end
300
+ URLcrypt::key = [body].pack('H*')
301
+ s3 = Aws::S3::Client.new(
302
+ :access_key_id => URLcrypt.decrypt(download_resp["result"]["sts_a"]),
303
+ :secret_access_key => URLcrypt.decrypt(download_resp["result"]["sts_s"]),
304
+ :session_token => URLcrypt.decrypt(download_resp["result"]["sts_st"]),
305
+ :region => URLcrypt.decrypt(download_resp["result"]["region"]))
306
+ File.open(project_home+"/"+absolute_path, 'wb') do |file|
307
+ resp = s3.get_object({ bucket:URLcrypt.decrypt(download_resp["result"]["bucket"]),
308
+ key:URLcrypt.decrypt(download_resp["result"]["key"])}, target: file)
309
+ end
310
+ return true
311
+ end
312
+
313
+ rescue =>e
314
+ return false
315
+
316
+ end
317
+ end
318
+ def download_file(absolute_path, relative_path, project_home, conflict=false)
319
+ res = Cnvrg::API.request(@base_resource + "download_file", 'POST', {absolute_path: absolute_path, relative_path: relative_path})
320
+ Cnvrg::CLI.is_response_success(res, false)
321
+ if res["result"]
322
+ res = res["result"]
323
+ return false if res["link"].empty? or res["filename"].empty?
324
+ filename = res["filename"]
325
+ file_location = absolute_path.gsub(/#{filename}\/?$/, "")
326
+
327
+ FileUtils.mkdir_p project_home + "/" + file_location
328
+ filename += ".conflict" if conflict
329
+
330
+ File.open("#{project_home}/#{file_location}/#{filename}", "wb") do |file|
331
+ file.write open(res["link"]).read
332
+ end
333
+ else
334
+ return false
335
+ end
336
+ return true
337
+ end
338
+
339
+ def download_dir(absolute_path, relative_path, project_home)
340
+ FileUtils.mkdir_p("#{project_home}/#{absolute_path}")
341
+ end
342
+ def revoke_download_dir(absolute_path, relative_path, project_home)
343
+ puts FileUtils.rmtree("#{absolute_path}")
344
+ end
345
+
346
+ def revoke_download_file(project_home,absolute_path,filename,conflict=false)
347
+ begin
348
+ file_location = absolute_path.gsub(/#{filename}\/?$/, "")
349
+
350
+ filename += ".conflict" if conflict
351
+ FileUtils.remove("#{file_location}/#{filename}")
352
+ return true
353
+ rescue
354
+ return false
355
+ end
356
+ end
357
+
358
+ def start_commit(new_branch)
359
+
360
+ response = Cnvrg::API.request("#{base_resource}/commit/start", 'POST', {dataset_slug: @dataset_slug,new_branch:false,
361
+ username: @owner})
362
+ Cnvrg::CLI.is_response_success(response)
363
+ return response
364
+ end
365
+
366
+ def end_commit(commit_sha1)
367
+ response = Cnvrg::API.request("#{base_resource}/commit/end", 'POST', {commit_sha1: commit_sha1})
368
+ return response
369
+ end
370
+
371
+ def rollback_commit(commit_sha1)
372
+ response = Cnvrg::API.request("#{base_resource}/commit/rollback", 'POST', {commit_sha1: commit_sha1})
373
+ Cnvrg::CLI.is_response_success(response, false)
374
+ end
375
+ end
376
+ end
@@ -0,0 +1,196 @@
1
+ require 'fileutils'
2
+ module Cnvrg
3
+ class Dataset
4
+ attr_reader :slug, :owner, :title, :local_path, :working_dir
5
+
6
+ RemoteURL ||= "https://cnvrg.io"
7
+
8
+ def initialize(project_home)
9
+ begin
10
+ config = YAML.load_file(project_home+"/.cnvrg/config.yml")
11
+ @local_path = project_home
12
+ @title = config[:dataset_name]
13
+ @slug = config[:dataset_slug]
14
+ @owner = config[:owner]
15
+ @working_dir = project_home
16
+ rescue => e
17
+ end
18
+
19
+ end
20
+
21
+
22
+ def last_local_commit
23
+ idx = YAML.load_file(@local_path + "/.cnvrg/idx.yml")
24
+ return idx[:commit]
25
+ end
26
+
27
+ def url
28
+ url = Cnvrg::Helpers.remote_url
29
+ "#{url}/#{self.owner}/projects/#{self.slug}"
30
+ end
31
+
32
+ def update_ignore_list(new_ignore)
33
+ if new_ignore.empty?
34
+ return true
35
+ end
36
+ begin
37
+ File.open(self.local_path+"/.cnvrgignore", "a+") do |f|
38
+ new_ignore.each do |i|
39
+ f.puts("#{i}\n")
40
+ end
41
+ end
42
+ return true
43
+ rescue
44
+ return false
45
+ end
46
+ end
47
+
48
+ def get_ignore_list
49
+ ignore_list = []
50
+ File.open(self.local_path+"/.cnvrgignore", "r").each_line do |line|
51
+ line = line.strip
52
+ if line.start_with? "#"
53
+ next
54
+ end
55
+ if line.end_with? "/"
56
+ ignore_list << line.chop
57
+ sub_dirs = Dir.glob("#{line}/**/*").each { |x| x.gsub!("//", "/") }
58
+ ignore_list << sub_dirs.flatten
59
+ else
60
+ ignore_list << line
61
+ end
62
+ end
63
+ return ignore_list.flatten
64
+
65
+ end
66
+
67
+
68
+ def self.init(owner, dataset_name, is_public=false)
69
+ list_dirs = [".cnvrg"
70
+ ]
71
+ list_files = [
72
+ ".cnvrgignore",
73
+ ".cnvrg/config.yml"
74
+ ]
75
+
76
+ cnvrgignore = Helpers.cnvrgignore_content
77
+ begin
78
+ response = Cnvrg::API.request("cli/create_dataset", 'POST', {title: dataset_name, owner: owner, is_public: is_public})
79
+ Cnvrg::CLI.is_response_success(response)
80
+ response = JSON.parse response["result"]
81
+ dataset_slug = response["slug"]
82
+
83
+ config = {dataset_name: dataset_name,
84
+ dataset_slug: dataset_slug,
85
+ owner: owner}
86
+ FileUtils.mkdir_p list_dirs
87
+ FileUtils.touch list_files
88
+ File.open(".cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
89
+ File.open(".cnvrgignore", "w+") { |f| f.write cnvrgignore } unless File.exist? ".cnvrgignore"
90
+ rescue => e
91
+
92
+ return false
93
+ end
94
+ return true
95
+ end
96
+
97
+
98
+ def get_idx
99
+ YAML.load_file("#{self.local_path}/.cnvrg/idx.yml")
100
+ end
101
+ def url
102
+ url = Cnvrg::Helpers.remote_url
103
+ "#{url}/#{self.owner}/datsets/#{self.slug}"
104
+ end
105
+ def generate_idx
106
+ if File.exists? "#{self.local_path}/.cnvrg/idx.yml"
107
+ old_idx = YAML.load_file("#{self.local_path}/.cnvrg/idx.yml")
108
+ else
109
+ old_idx = nil
110
+ end
111
+
112
+ tree_idx = Hash.new(0)
113
+
114
+ list = Dir.glob("#{self.local_path}/**/**", File::FNM_DOTMATCH).reject { |x| (x =~ /\/\.{1,2}$/) or (x =~ /^#{self.local_path}\/\.cnvrg\/*/) }
115
+ list_ignore = self.get_ignore_list()
116
+ list.each do |e|
117
+ label = e.gsub(self.local_path + "/", "")
118
+ if File.directory? e
119
+ if list_ignore.include? label
120
+ next
121
+ end
122
+ tree_idx[label+"/"] = nil
123
+ else
124
+ if list_ignore.include? label
125
+ next
126
+ end
127
+ sha1 = Digest::SHA1.file(e).hexdigest
128
+ if old_idx.nil? or old_idx.to_h[:tree].nil?
129
+ tree_idx[label] = {sha1: sha1, commit_time: nil}
130
+ elsif old_idx[:tree][label].nil? or old_idx[:tree][label][:sha1] != sha1
131
+ tree_idx[label] = {sha1: sha1, commit_time: nil}
132
+ else
133
+ tree_idx[label] = old_idx[:tree][label]
134
+ end
135
+ end
136
+ end
137
+
138
+ idx = {commit: old_idx.to_h[:commit], tree: tree_idx}
139
+
140
+ File.open("#{self.local_path}/.cnvrg/idx.yml", 'w') { |f| f.write idx.to_yaml }
141
+ return YAML.load_file("#{self.local_path}/.cnvrg/idx.yml")
142
+ end
143
+ def create_volume
144
+ response = Cnvrg::API.request("users/#{self.owner}/datasets/#{self.slug}/volumes/create", 'POST')
145
+ CLI.is_response_success(response)
146
+ return response
147
+ end
148
+
149
+ def compare_idx(new_branch, commit=last_local_commit)
150
+
151
+ local_idx = self.generate_idx
152
+ response = Cnvrg::API.request("users/#{self.owner}/datasets/#{self.slug}/status", 'POST', {idx: local_idx, new_branch: new_branch, current_commit: commit})
153
+ CLI.is_response_success(response)
154
+ return response
155
+ end
156
+
157
+ def compare_commit(commit)
158
+ if commit.nil? or commit.empty?
159
+ commit = last_local_commit
160
+ end
161
+ response = Cnvrg::API.request("users/#{self.owner}/projects/#{self.slug}/commit/compare", 'POST', {current_commit: commit})
162
+ CLI.is_response_success(response)
163
+ update_is_new_branch(response["result"]["new_branch"])
164
+ return response["result"]["new_branch"]
165
+ end
166
+
167
+ def update_idx_with_files_commits!(files, commit_time)
168
+
169
+ idx_hash = YAML.load_file("#{self.local_path}/.cnvrg/idx.yml")
170
+ files.each do |path|
171
+ idx_hash[:tree].to_h[path].to_h[:commit_time] = commit_time
172
+ end
173
+ File.open("#{self.local_path}/.cnvrg/idx.yml", 'w') { |f| f.write idx_hash.to_yaml }
174
+
175
+ return true
176
+ end
177
+
178
+
179
+ def update_idx_with_commit!(commit)
180
+ idx_hash = YAML.load_file("#{self.local_path}/.cnvrg/idx.yml")
181
+ idx_hash[:commit] = commit
182
+
183
+ File.open("#{self.local_path}/.cnvrg/idx.yml", 'w') { |f| f.write idx_hash.to_yaml }
184
+ return true
185
+ end
186
+
187
+ def revert(working_dir)
188
+ FileUtils.rm_rf working_dir
189
+ # response = Cnvrg::API.request("users/#{self.owner}/projects/#{self.slug}/revert", 'GET')
190
+ # CLI.is_response_success(response)
191
+
192
+
193
+ end
194
+
195
+ end
196
+ end