cnvrg 1.9.9.9.7

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.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/bin/cnvrg +9 -0
  3. data/cnvrg.gemspec +47 -0
  4. data/lib/cnvrg.rb +7 -0
  5. data/lib/cnvrg/Images.rb +351 -0
  6. data/lib/cnvrg/api.rb +247 -0
  7. data/lib/cnvrg/api_v2.rb +14 -0
  8. data/lib/cnvrg/auth.rb +79 -0
  9. data/lib/cnvrg/cli.rb +5715 -0
  10. data/lib/cnvrg/cli/flow.rb +166 -0
  11. data/lib/cnvrg/cli/library_cli.rb +33 -0
  12. data/lib/cnvrg/cli/subcommand.rb +28 -0
  13. data/lib/cnvrg/cli/task.rb +116 -0
  14. data/lib/cnvrg/colors.rb +8 -0
  15. data/lib/cnvrg/connect_job_ssh.rb +31 -0
  16. data/lib/cnvrg/data.rb +335 -0
  17. data/lib/cnvrg/datafiles.rb +1325 -0
  18. data/lib/cnvrg/dataset.rb +892 -0
  19. data/lib/cnvrg/downloader/client.rb +101 -0
  20. data/lib/cnvrg/downloader/clients/azure_client.rb +45 -0
  21. data/lib/cnvrg/downloader/clients/gcp_client.rb +50 -0
  22. data/lib/cnvrg/downloader/clients/s3_client.rb +78 -0
  23. data/lib/cnvrg/experiment.rb +209 -0
  24. data/lib/cnvrg/files.rb +1047 -0
  25. data/lib/cnvrg/flow.rb +137 -0
  26. data/lib/cnvrg/helpers.rb +422 -0
  27. data/lib/cnvrg/helpers/agent.rb +188 -0
  28. data/lib/cnvrg/helpers/executer.rb +213 -0
  29. data/lib/cnvrg/hyper.rb +21 -0
  30. data/lib/cnvrg/image.rb +113 -0
  31. data/lib/cnvrg/image_cli.rb +25 -0
  32. data/lib/cnvrg/job_cli.rb +73 -0
  33. data/lib/cnvrg/job_ssh.rb +48 -0
  34. data/lib/cnvrg/logger.rb +111 -0
  35. data/lib/cnvrg/org_helpers.rb +5 -0
  36. data/lib/cnvrg/project.rb +822 -0
  37. data/lib/cnvrg/result.rb +29 -0
  38. data/lib/cnvrg/runner.rb +49 -0
  39. data/lib/cnvrg/ssh.rb +94 -0
  40. data/lib/cnvrg/storage.rb +128 -0
  41. data/lib/cnvrg/task.rb +165 -0
  42. data/lib/cnvrg/version.rb +3 -0
  43. metadata +460 -0
@@ -0,0 +1,1325 @@
1
+ require 'mimemagic'
2
+ require 'aws-sdk-s3'
3
+ require 'URLcrypt'
4
+ require 'parallel'
5
+ require 'fileutils'
6
+
7
+
8
+ module Cnvrg
9
+ class Datafiles
10
+ ParallelThreads ||= Cnvrg::Helpers.parallel_threads
11
+
12
+ LARGE_FILE=1024*1024*5
13
+ MULTIPART_SPLIT=10000000
14
+
15
+ attr_reader :base_resource
16
+
17
+ def initialize(owner, dataset_slug, dataset: nil)
18
+ @dataset_slug = dataset_slug
19
+ @owner = owner
20
+ @dataset = dataset
21
+ @base_resource = "users/#{owner}/datasets/#{dataset_slug}/"
22
+ @downloader = @dataset.get_storage_client
23
+ @token_issue_time = Time.current
24
+ end
25
+
26
+ def refresh_storage_token
27
+ current_time = Time.current
28
+ if current_time - @token_issue_time > 1.hours
29
+ @downloader = @dataset.get_storage_client
30
+ @token_issue_time = Time.current
31
+ end
32
+ end
33
+
34
+ def check_file_sha1(filename, org_sha1, tag: 'conflict')
35
+ file_loc = "#{Dir.pwd}/#{filename}"
36
+ sha1 = OpenSSL::Digest::SHA1.file(file_loc).hexdigest
37
+ return 0 if sha1 == org_sha1
38
+ FileUtils.cp(file_loc, "#{file_loc}.#{tag}")
39
+ return 1
40
+ end
41
+
42
+ def verify_files_exists(files)
43
+ paths = []
44
+ files.each do |file|
45
+ if File.exists? file
46
+ if File.directory? file
47
+ paths += Dir.glob("#{file}/**/*")
48
+ else
49
+ paths << file
50
+ end
51
+ next
52
+ end
53
+ raise SignalException.new(1, "Cant find file #{file}") unless File.exists? "#{Dir.pwd}/#{file}"
54
+ end
55
+ paths.map{|p| p.gsub(/^\.\//, '')}
56
+ end
57
+
58
+ def get_files_and_folders(paths)
59
+ files_and_folders = {}
60
+ paths.each do |file|
61
+ if File.exists? file
62
+ if File.directory? file
63
+ Dir.glob("#{file}/**/*").select do |f|
64
+ files_and_folders["#{f}/"] = "folder" if File.directory? f
65
+ files_and_folders[f] = "file" if File.file? f
66
+ end
67
+ files_and_folders["#{file}/"] = "folder"
68
+ else
69
+ files_and_folders[file] = "file"
70
+ end
71
+ next
72
+ end
73
+ raise SignalException.new(1, "Cant find file #{file}") unless File.exists? "#{Dir.pwd}/#{file}"
74
+ end
75
+ return files_and_folders
76
+ end
77
+
78
+ def check_files_sha1(files, resolver, tag)
79
+ conflicts = 0
80
+ files.each do |file|
81
+ next if file.ends_with? '/'
82
+ sha1 = resolver.fetch(file, {}).fetch("sha1", nil)
83
+ conflicts += self.check_file_sha1(file, sha1, tag: tag)
84
+ end
85
+ conflicts
86
+ end
87
+
88
+ def mark_conflicts(results)
89
+ begin
90
+ updated = results["updated_on_server"]
91
+ deleted = results["deleted"]
92
+ resolver = results['resolved_files']
93
+ overall = 0
94
+ overall += self.check_files_sha1(updated, resolver, "conflict")
95
+ overall += self.check_files_sha1(deleted, resolver, "deleted")
96
+ overall
97
+ rescue => e
98
+ 0
99
+ end
100
+ end
101
+
102
+ def cp_ds(relative: false)
103
+ prefix = @dataset.get_dataset["bucket_prefix"]
104
+ batch_size = 10000
105
+ pbar = ProgressBar.create(:title => "Download Progress",
106
+ :progress_mark => '=',
107
+ :format => "%b%i| %c Files downloaded",
108
+ :starting_at => 0,
109
+ :total => nil,
110
+ :autofinish => true)
111
+ parallel_options = {
112
+ in_threads: ParallelThreads,
113
+ in_processes: Cnvrg::CLI::ParallelProcesses,
114
+ isolation: true,
115
+ finish: ->(*args) { pbar.progress += 1 }
116
+ }
117
+ finished = false
118
+ while not finished
119
+ current_batch, marker = @downloader.fetch_files(prefix: prefix, marker: marker, limit: batch_size)
120
+ if marker.blank?
121
+ finished = true
122
+ end
123
+ Parallel.map(current_batch, parallel_options) do |file|
124
+ next if file.end_with? "/"
125
+ cutted_key = relative ? @downloader.cut_prefix(prefix, file) : file
126
+ dest_path = File.join(@dataset.local_path, cutted_key)
127
+ @downloader.download(file, dest_path, decrypt: false)
128
+ file
129
+ end
130
+ end
131
+ end
132
+
133
+ # This is for backwards compatibility only and should be removed in future versions:
134
+ def put_commit(commit_sha1)
135
+ response = Cnvrg::API.request(
136
+ "#{@base_resource}/commit/latest",
137
+ 'PUT',
138
+ {
139
+ commit_sha1: commit_sha1,
140
+ ignore: true # tells the new server to ignore this api call since its coming from the new CLI
141
+ }
142
+ )
143
+ if response.present?
144
+ msg = response['result']
145
+ else
146
+ msg = "Can't save changes in the dataset"
147
+ end
148
+
149
+ Cnvrg::Result.new(Cnvrg::CLI.is_response_success(response, false), msg)
150
+ end
151
+
152
+ def create_progressbar(title, total)
153
+ return ProgressBar.create(
154
+ :title => title,
155
+ :progress_mark => '=',
156
+ :format => "%b>>%i| %p%% %t",
157
+ :starting_at => 0,
158
+ :total => total,
159
+ :autofinish => true
160
+ )
161
+ end
162
+
163
+
164
+ def upload_multiple_files(commit_sha1, tree, threads: ParallelThreads, force: false, new_branch: false, prefix: '', partial_commit: nil, total: nil)
165
+ begin
166
+ Cnvrg::Logger.log_info("Sending Upload Files request")
167
+ refresh_storage_token
168
+ error = nil
169
+ upload_resp = nil
170
+ 10.times do
171
+ upload_resp = Cnvrg::API.request(@base_resource + "upload_files", 'POST_JSON', {commit_sha1: commit_sha1, tree: tree, force: force, override: force, is_branch: new_branch, partial_commit: partial_commit})
172
+ if Cnvrg::CLI.is_response_success(upload_resp, false)
173
+ error = nil
174
+ break
175
+ end
176
+ error = upload_resp
177
+ Cnvrg::Logger.log_method(bind: binding)
178
+ Cnvrg::Logger.log_info("Got an error message from server, #{upload_resp.try(:fetch, "message")}, trying again")
179
+ end
180
+ raise Exception.new("Can't upload data files: #{error["message"]}") if error.present?
181
+
182
+ Cnvrg::Logger.log_info("Uploading files")
183
+ results = upload_resp['result'].with_indifferent_access
184
+
185
+ if results['files'].blank?
186
+ return 0, []
187
+ end
188
+
189
+ if @temp_upload_progressbar.blank?
190
+ @temp_upload_progressbar = ProgressBar.create(:title => "Upload Progress",
191
+ :progress_mark => '=',
192
+ :format => "%b>>%i| %p%% %t",
193
+ :starting_at => 0,
194
+ :total => total,
195
+ :autofinish => true)
196
+ end
197
+
198
+ files = results['files']
199
+
200
+ progress_semaphore = Mutex.new
201
+ upload_error_files = []
202
+ @temp_upload_progressbar.progress += tree.keys.length - files.length if @temp_upload_progressbar.present?
203
+ Parallel.map((files.keys), in_threads: threads) do |k|
204
+ o = tree[k].merge(files[k])
205
+ success = upload_single_file(nil, o)
206
+ if not success
207
+ upload_error_files << {absolute_path: o[:absolute_path]}
208
+ files.except!(k)
209
+ tree.except!(k)
210
+ Cnvrg::Logger.log_error_message("Error while upload single file #{o["path"]}")
211
+ end
212
+ progress_semaphore.synchronize { @temp_upload_progressbar.progress += 1 if @temp_upload_progressbar.present? }
213
+ end
214
+
215
+ blob_ids = files.values.map {|f| f['bv_id']}
216
+ if blob_ids.present?
217
+ dirs = tree.keys.select {|k| tree[k].nil?} || []
218
+ Cnvrg::Logger.info("Sending Upload files save")
219
+ upload_resp = Cnvrg::API.request(@base_resource + "upload_files_save", "POST", {commit: commit_sha1, blob_ids: blob_ids, dirs: dirs})
220
+ unless Cnvrg::CLI.is_response_success(upload_resp, false)
221
+ Cnvrg::Logger.log_method(bind: binding)
222
+ raise Exception.new("Got an error message from server, #{upload_resp.try(:fetch, "message")}")
223
+ end
224
+ end
225
+ Cnvrg::Logger.log_info("Upload Success")
226
+ return files.try(:keys).try(:length), upload_error_files
227
+ rescue => e
228
+ Cnvrg::Logger.log_method(bind: binding)
229
+ Cnvrg::Logger.log_error(e)
230
+ raise e
231
+ end
232
+ end
233
+
234
+ def delete_multiple_files(commit_sha1, regex_list)
235
+ begin
236
+ Cnvrg::Logger.log_info("Sending Delete Files request")
237
+ resp = Cnvrg::API.request(
238
+ @base_resource + "delete_files",
239
+ 'POST_JSON',
240
+ {
241
+ commit_sha1: commit_sha1,
242
+ regex_list: regex_list,
243
+ }
244
+ )
245
+ unless Cnvrg::CLI.is_response_success(resp, false)
246
+ Cnvrg::Logger.log_method(bind: binding)
247
+ raise Exception.new("Got an error message from server, #{resp.try(:fetch, "message")}")
248
+ end
249
+ Cnvrg::Logger.log_info("Delete Files request Successful")
250
+ return resp["files"], resp["folders"], resp["job_id"]
251
+ rescue => e
252
+ Cnvrg::Logger.log_method(bind: binding)
253
+ Cnvrg::Logger.log_error(e)
254
+ raise e
255
+ end
256
+ end
257
+
258
+ def delete_file_chunk(commit_sha1, regex_list, chunk_size, offset)
259
+ begin
260
+ resp = Cnvrg::API.request(
261
+ @base_resource + "delete_files_by_chunk",
262
+ 'POST_JSON',
263
+ {
264
+ commit_sha1: commit_sha1,
265
+ regex_list: regex_list,
266
+ chunk_size: chunk_size,
267
+ offset: offset
268
+ }
269
+ )
270
+ unless Cnvrg::CLI.is_response_success(resp, false)
271
+ Cnvrg::Logger.log_method(bind: binding)
272
+ raise Exception.new("Got an error message from server, #{resp.try(:fetch, "message")}")
273
+ end
274
+ return resp["total_changes"]
275
+ rescue => e
276
+ Cnvrg::Logger.log_method(bind: binding)
277
+ Cnvrg::Logger.log_error(e)
278
+ raise e
279
+ end
280
+ end
281
+
282
+ def get_delete_progress(commit_sha1, job_id)
283
+ begin
284
+ resp = Cnvrg::API.request(
285
+ @base_resource + "get_delete_progress",
286
+ 'POST_JSON',
287
+ {
288
+ commit_sha1: commit_sha1,
289
+ job_id: job_id
290
+ }
291
+ )
292
+ unless Cnvrg::CLI.is_response_success(resp, false)
293
+ Cnvrg::Logger.log_method(bind: binding)
294
+ raise Exception.new("Got an error message from server, #{resp.try(:fetch, "message")}")
295
+ end
296
+ return resp["total_deleted"]
297
+ rescue => e
298
+ Cnvrg::Logger.log_method(bind: binding)
299
+ Cnvrg::Logger.log_error(e)
300
+ raise e
301
+ end
302
+ end
303
+
304
+ def request_upload_files(commit_sha1, tree, override, new_branch, partial_commit)
305
+ retry_count = 0
306
+ loop do
307
+ upload_resp = Cnvrg::API.request(@base_resource + "upload_files", 'POST_JSON', {
308
+ commit_sha1: commit_sha1,
309
+ tree: tree,
310
+ override: override,
311
+ force: override,
312
+ is_branch: new_branch,
313
+ partial_commit: partial_commit
314
+ })
315
+ if not (Cnvrg::CLI.is_response_success(upload_resp, false))
316
+ #Cnvrg::Logger.log_method(bind: binding)
317
+ retry_count += 1
318
+
319
+ puts "Failed request upload files: #{Time.current}"
320
+ puts upload_resp
321
+
322
+ if retry_count > 5
323
+ raise Exception.new("Got an error message from server, #{upload_resp.try(:fetch, "message")}")
324
+ end
325
+ sleep 5
326
+ next
327
+ end
328
+ return upload_resp['result'].with_indifferent_access
329
+ end
330
+
331
+ end
332
+
333
+ def upload_multiple_files_optimized(files, commit_sha1, threads: 15, chunk_size: 1000, override: false, new_branch: false, prefix: '', partial_commit: nil)
334
+ cli = CLI.new
335
+ cli.log_message("Using #{threads} threads with chunk size of #{chunk_size}.", Thor::Shell::Color::GREEN)
336
+
337
+ progressbar = create_progressbar("Upload Progress", files.size)
338
+ cli = CLI.new
339
+
340
+ # Vars to handle the parallelism
341
+ progress_mutex = Mutex.new
342
+ file_queue = Queue.new
343
+ progress_queue = Queue.new
344
+ worker_threads = []
345
+
346
+ # Vars to keep track of uploaded files and directories
347
+ dirs = []
348
+ uploaded_files = []
349
+
350
+ begin
351
+ # Init working threads that handle the upload of the files:
352
+ threads.times do |i|
353
+ worker_threads[i] = Thread.new do
354
+ # wait for file_queue.close to break the loop
355
+ while file = file_queue.deq
356
+ success = upload_single_file(cli, file)
357
+ file[:success] = success
358
+ if not success
359
+ cli.log_message("Error while uploading file: #{file[:absolute_path]}", Thor::Shell::Color::RED)
360
+ Cnvrg::Logger.log_error_message("Error while upload single file #{file["path"]}")
361
+ end
362
+ progress_queue << file
363
+ end
364
+ end
365
+ end
366
+
367
+ # init the thread that handles the file upload progress and saving them in the server
368
+ progress_thread = Thread.new do
369
+ loop do
370
+ file = progress_queue.deq(non_block: true) rescue nil # to prevent deadlocks
371
+ unless file.nil?
372
+ progress_mutex.synchronize {
373
+ progressbar.progress += 1
374
+ uploaded_files.append(file) if file[:success]
375
+ }
376
+
377
+ if uploaded_files.size == chunk_size or progressbar.finished?
378
+ refresh_storage_token
379
+ # puts "progress: #{progress_queue.length}"
380
+ # puts "files: #{file_queue.length}"
381
+ Cnvrg::Logger.info("Sending Upload files save")
382
+ blob_ids = uploaded_files.map {|f| f['bv_id']}
383
+ upload_resp = Cnvrg::API.request(@base_resource + "upload_files_save", "POST", {commit: commit_sha1, blob_ids: blob_ids, dirs: dirs})
384
+ unless Cnvrg::CLI.is_response_success(upload_resp, false)
385
+ Cnvrg::Logger.log_method(bind: binding)
386
+ raise Exception.new("Got an error message from server, #{upload_resp.try(:fetch, "message")}")
387
+ end
388
+ # cli.log_message("Saved file chunk to server", Thor::Shell::Color::GREEN)
389
+ uploaded_files = []
390
+ dirs = []
391
+ end
392
+ else
393
+ sleep(0.1)
394
+ end
395
+
396
+ if progressbar.finished?
397
+ # puts "finished"
398
+ file_queue.close()
399
+ progress_queue.close()
400
+ Thread.exit
401
+ end
402
+ end
403
+ end
404
+
405
+ file_chunks = files.each_slice(chunk_size).to_a
406
+ # Fetch the required files from the server:
407
+ Parallel.map((file_chunks), in_threads: 10) do |files_chunk|
408
+
409
+ tree = @dataset.generate_chunked_idx(files_chunk, prefix: prefix, threads: threads)
410
+ results = request_upload_files(commit_sha1, tree, override, new_branch, partial_commit)
411
+
412
+ # puts "Got #{results['files'].size} files to upload from #{files_chunk.size} files"
413
+
414
+ if results['files'].blank?
415
+ progress_mutex.synchronize { progressbar.progress += tree.keys.length }
416
+ next
417
+ end
418
+
419
+ # Handle directories:
420
+ new_dirs = tree.keys.select {|k| tree[k].nil?}
421
+ dirs += new_dirs
422
+
423
+ files_to_upload = results['files']
424
+ progress_mutex.synchronize {
425
+ progressbar.progress += tree.keys.length - files_to_upload.length
426
+ }
427
+
428
+ files_to_upload.keys.each do |key|
429
+ while file_queue.size > 5000
430
+ sleep(0.1)
431
+ end
432
+ file_queue.push tree[key].merge(files_to_upload[key])
433
+ end
434
+ end
435
+
436
+ progress_thread.join()
437
+ worker_threads.each(&:join)
438
+
439
+ rescue => e
440
+ puts e
441
+ Cnvrg::Logger.log_method(bind: binding)
442
+ Cnvrg::Logger.log_error(e)
443
+ raise e
444
+ end
445
+ end
446
+
447
+ def upload_single_file(cli, file)
448
+ success = false
449
+ begin
450
+ file = file.as_json
451
+ Cnvrg::Logger.log_info("Uploading #{file["absolute_path"]}")
452
+ @downloader.safe_upload(file["path"], file["absolute_path"])
453
+ success = true
454
+ Cnvrg::Logger.log_info("#{file["absolute_path"]} uploaded.")
455
+ rescue => e
456
+ Cnvrg::Logger.log_error_message("Error while upload single file #{file["path"]}")
457
+ Cnvrg::Logger.log_error(e)
458
+ end
459
+ success
460
+ end
461
+
462
+ def upload_file(absolute_path, relative_path, commit_sha1)
463
+ file_name = File.basename relative_path
464
+ file_size = File.size(absolute_path).to_f
465
+ mime_type = MimeMagic.by_path(absolute_path)
466
+ content_type = !(mime_type.nil? or mime_type.text?) ? mime_type.type : "text/plain"
467
+ sha1 = OpenSSL::Digest::SHA1.file(absolute_path).hexdigest
468
+ if (absolute_path.include? "_tags.yml" or absolute_path.include? "_tags.yaml")
469
+ is_valid = false
470
+ begin
471
+ content = open(absolute_path).read()
472
+ hash = YAML.load(open(absolute_path).read())
473
+ # if level 1 keys count is 1
474
+ if hash.keys.count == 1
475
+ if hash["tags"].present?
476
+ is_valid = true
477
+ elsif hash[hash.keys.first].class != Hash
478
+ is_valid = true
479
+ end
480
+ # if level 1 keys count is greater than 1
481
+ elsif hash.keys.count > 1
482
+ if hash["tags"].present? and hash["tags"].class == Hash
483
+ is_valid = false
484
+ else
485
+ is_valid = true
486
+ end
487
+ end
488
+ rescue
489
+ is_valid = false
490
+ end
491
+
492
+ if is_valid
493
+ upload_resp = Cnvrg::API.request(@base_resource + "upload_file", 'POST_FILE', {absolute_path: absolute_path, relative_path: relative_path,
494
+ commit_sha1: commit_sha1, file_name: file_name,
495
+ file_size: file_size, file_content_type: content_type, sha1: sha1, content: content})
496
+ else
497
+ puts("#{absolute_path} is invalid")
498
+ puts("Please check yaml structure.")
499
+ end
500
+ else
501
+ upload_resp = Cnvrg::API.request(@base_resource + "upload_file", 'POST_FILE', {absolute_path: absolute_path, relative_path: relative_path,
502
+ commit_sha1: commit_sha1, file_name: file_name,
503
+ file_size: file_size, file_content_type: content_type, sha1: sha1})
504
+ puts upload_resp
505
+
506
+ end
507
+
508
+ if Cnvrg::CLI.is_response_success(upload_resp, false)
509
+ s3_res = upload_large_files_s3(upload_resp, absolute_path)
510
+
511
+ return s3_res
512
+ end
513
+ end
514
+ def upload_tar_file(absolute_path, relative_path, commit_sha1)
515
+ begin
516
+ file_name = File.basename relative_path
517
+ file_size = File.size(absolute_path).to_f
518
+ mime_type = MimeMagic.by_path(absolute_path)
519
+ content_type = !(mime_type.nil? or mime_type.text?) ? mime_type.type : "text/plain"
520
+ begin
521
+ chunked_bytes = [100, (file_size*0.01)].min
522
+ total_yanked = ""
523
+ open(absolute_path, "rb") do |f|
524
+ total_yanked = f.read(chunked_bytes)
525
+ end
526
+ if !total_yanked.empty?
527
+ sha1 = OpenSSL::Digest::SHA1.hexdigest(total_yanked)
528
+ else
529
+ sha1 = OpenSSL::Digest::SHA1.file(absolute_path).hexdigest
530
+ end
531
+ rescue
532
+ sha1 = OpenSSL::Digest::SHA1.file(absolute_path).hexdigest
533
+ end
534
+
535
+ upload_resp = Cnvrg::API.request(@base_resource + "upload_tar_file", 'POST_FILE', {absolute_path: absolute_path, relative_path: relative_path,
536
+ commit_sha1: commit_sha1, file_name: file_name,
537
+ file_size: file_size, file_content_type: content_type, sha1: sha1,
538
+ new_version:true})
539
+ if Cnvrg::CLI.is_response_success(upload_resp, false)
540
+ path = upload_resp["result"]["path"]
541
+ s3_res = upload_large_files_s3(upload_resp, absolute_path)
542
+ if s3_res
543
+ # Cnvrg::API.request(@base_resource + "update_s3", 'POST', {path: path, commit_id: upload_resp["result"]["commit_id"],
544
+ # blob_id: upload_resp["result"]["id"]})
545
+ return true
546
+ end
547
+ else
548
+ return false
549
+ end
550
+ rescue => e
551
+ puts e.message
552
+ return false
553
+ end
554
+ end
555
+
556
+
557
+ def upload_log_file(absolute_path, relative_path, log_date)
558
+ file_name = File.basename relative_path
559
+ file_size = File.size(absolute_path).to_f
560
+ content_type = "text/x-log"
561
+ upload_resp = Cnvrg::API.request("/users/#{@owner}/" + "upload_cli_log", 'POST_FILE', {absolute_path: absolute_path, relative_path: relative_path,
562
+ file_name: file_name, log_date: log_date,
563
+ file_size: file_size, file_content_type: content_type})
564
+ if Cnvrg::CLI.is_response_success(upload_resp, false)
565
+ path = upload_resp["result"]["path"]
566
+ s3_res = upload_small_files_s3(path, absolute_path, "text/plain")
567
+ end
568
+ if s3_res
569
+ return true
570
+ end
571
+ return false
572
+
573
+ end
574
+ def upload_data_log_file(absolute_path, relative_path,data_commit_sha)
575
+ file_name = File.basename relative_path
576
+ file_size = File.size(absolute_path).to_f
577
+ content_type = "text/x-log"
578
+ upload_resp = Cnvrg::API.request("/users/#{@owner}/" + "upload_data_log", 'POST_FILE', {absolute_path: absolute_path, relative_path: relative_path,
579
+ file_name: file_name, log_date: Time.now,
580
+ file_size: file_size, file_content_type: content_type,
581
+ data_commit_sha1:data_commit_sha})
582
+ if Cnvrg::CLI.is_response_success(upload_resp, false)
583
+ path = upload_resp["result"]["path"]
584
+ s3_res = upload_small_files_s3(path, absolute_path, "text/plain")
585
+ end
586
+ if s3_res
587
+ return true
588
+ end
589
+ return false
590
+
591
+ end
592
+
593
+
594
+ def upload_exec_file(absolute_path, image_name, commit_id)
595
+ file_name = File.basename absolute_path
596
+ file_size = File.size(absolute_path).to_f
597
+ content_type = "application/zip"
598
+ begin
599
+ upload_resp = Cnvrg::API.request("users/#{@owner}/images/" + "upload_config", 'POST_FILE', {relative_path: absolute_path,
600
+ file_name: file_name,
601
+ image_name: image_name,
602
+ file_size: file_size,
603
+ file_content_type: content_type,
604
+ project_slug: @project_slug,
605
+ commit_id: commit_id})
606
+ # puts upload_resp
607
+ if Cnvrg::CLI.is_response_success(upload_resp, false)
608
+ if upload_resp["result"]["image"] == -1
609
+ return -1
610
+ end
611
+ path = upload_resp["result"]["path"]
612
+ s3_res = upload_small_files_s3(path, absolute_path, content_type)
613
+
614
+ end
615
+ if s3_res
616
+ return upload_resp["result"]["id"]
617
+ end
618
+ return false
619
+ rescue SignalException
620
+
621
+ say "\nAborting"
622
+ exit(1)
623
+ end
624
+
625
+ end
626
+
627
+
628
+ def upload_image(absolute_path, image_name, owner, is_public, is_base, dpkg, libraries, bash, message, commit_id)
629
+ file_name = File.basename absolute_path
630
+ file_size = File.size(absolute_path).to_f
631
+ if is_base
632
+
633
+ content_type = "application/zip"
634
+ else
635
+ content_type = "application/gzip"
636
+ end
637
+ begin
638
+ upload_resp = Cnvrg::API.request("users/#{owner}/images/" + "upload_cnvrg", 'POST_FILE', {relative_path: absolute_path,
639
+ file_name: file_name,
640
+ image_name: image_name,
641
+ file_size: file_size,
642
+ file_content_type: content_type,
643
+ is_public: is_public,
644
+ project_slug: @project_slug,
645
+ commit_id: commit_id,
646
+ dpkg: dpkg,
647
+ py2: libraries,
648
+ py3: libraries,
649
+ bash_history: bash,
650
+ commit_message: message,
651
+ is_base: is_base})
652
+ # puts upload_resp
653
+ if Cnvrg::CLI.is_response_success(upload_resp, false)
654
+ path = upload_resp["result"]["path"]
655
+ s3_res = upload_small_files_s3(path, absolute_path, content_type)
656
+ if s3_res
657
+ commit_resp = Cnvrg::API.request("users/#{owner}/images/#{upload_resp["result"]["id"]}/" + "commit", 'GET')
658
+ if Cnvrg::CLI.is_response_success(commit_resp, false)
659
+ return commit_resp["result"]["image"]
660
+ else
661
+ return false
662
+ end
663
+
664
+ end
665
+ end
666
+ return false
667
+ rescue => e
668
+ end
669
+
670
+ end
671
+
672
+ def upload_cnvrg_image(absolute_path, image_name,secret)
673
+ file_name = File.basename relative_path
674
+ file_size = File.size(absolute_path).to_f
675
+ mime_type = MimeMagic.by_path(absolute_path)
676
+ content_type = !(mime_type.nil? or mime_type.text?) ? mime_type.type : "text/plain"
677
+ upload_resp = Cnvrg::API.request("images/#{image_name}/upload_file", 'POST_FILE', {absolute_path: absolute_path, relative_path: absolute_path,
678
+ file_name: file_name,
679
+ file_size: file_size, file_content_type: content_type,
680
+ secret: secret})
681
+ if Cnvrg::CLI.is_response_success(upload_resp, false)
682
+ path = upload_resp["result"]["path"]
683
+ s3_res = upload_large_files_s3(upload_resp, absolute_path)
684
+ if s3_res
685
+ Cnvrg::API.request(@base_resource + "update_s3", 'POST', {path: path, commit_id: upload_resp["result"]["commit_id"],
686
+ blob_id: upload_resp["result"]["id"]})
687
+ return true
688
+ end
689
+ end
690
+ return false
691
+
692
+ end
693
+
694
+ def download_image(file_path_to_store, image_slug, owner)
695
+
696
+
697
+ download_resp = Cnvrg::API.request("users/#{owner}/images/#{image_slug}/" + "download", 'GET')
698
+ path = download_resp["result"]["path"]
699
+
700
+ if Cnvrg::CLI.is_response_success(download_resp, false)
701
+ begin
702
+ open(file_path_to_store, 'w+') do |file|
703
+ file << open(path).read
704
+ end
705
+
706
+ return true
707
+ rescue => e
708
+ return false
709
+ end
710
+
711
+ return true
712
+ else
713
+ return false
714
+ end
715
+
716
+
717
+ end
718
+
719
+ def upload_large_files_s3(upload_resp, file_path)
720
+ begin
721
+ sts_path = upload_resp["result"]["path_sts"]
722
+
723
+ retries = 0
724
+ success= false
725
+ while !success and retries < 20
726
+ begin
727
+ if !Helpers.is_verify_ssl
728
+ body = open(sts_path, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
729
+ else
730
+ body = open(sts_path).read
731
+ end
732
+ success = true
733
+ rescue => e
734
+ retries +=1
735
+ sleep(5)
736
+
737
+ end
738
+ end
739
+ if !success
740
+ return false
741
+ end
742
+ split = body.split("\n")
743
+ key = split[0]
744
+ iv = split[1]
745
+ is_s3 = upload_resp["result"]["is_s3"]
746
+ access = Cnvrg::Helpers.decrypt(key, iv, upload_resp["result"]["sts_a"])
747
+
748
+ secret = Cnvrg::Helpers.decrypt(key,iv, upload_resp["result"]["sts_s"])
749
+
750
+ session = Cnvrg::Helpers.decrypt(key,iv, upload_resp["result"]["sts_st"])
751
+ region = Cnvrg::Helpers.decrypt(key,iv, upload_resp["result"]["region"])
752
+
753
+ bucket = Cnvrg::Helpers.decrypt(key,iv, upload_resp["result"]["bucket"])
754
+ server_side_encryption =upload_resp["result"]["server_side_encryption"]
755
+ use_accelerate_endpoint = false
756
+ if is_s3 or is_s3.nil?
757
+
758
+ use_accelerate_endpoint =true
759
+ client = Aws::S3::Client.new(
760
+ :access_key_id =>access,
761
+ :secret_access_key => secret,
762
+ :session_token => session,
763
+ :region => region,
764
+ :http_open_timeout => 60, :retry_limit => 20)
765
+ else
766
+ endpoint = Cnvrg::Helpers.decrypt(key,iv, upload_resp["result"]["endpoint"])
767
+ use_accelerate_endpoint = false
768
+ client = Aws::S3::Client.new(
769
+ :access_key_id =>access,
770
+ :secret_access_key => secret,
771
+ :region => region,
772
+ :endpoint=> endpoint,:force_path_style=> true,:ssl_verify_peer=>false,
773
+ :http_open_timeout => 60, :retry_limit => 20)
774
+ end
775
+
776
+
777
+ if !server_side_encryption
778
+ options = {:use_accelerate_endpoint => use_accelerate_endpoint}
779
+ else
780
+ options = {:use_accelerate_endpoint => use_accelerate_endpoint, :server_side_encryption => server_side_encryption}
781
+ end
782
+
783
+
784
+
785
+
786
+ s3 = Aws::S3::Resource.new(client: client)
787
+
788
+ resp = s3.bucket(bucket).
789
+ object(upload_resp["result"]["path"]+"/"+File.basename(file_path)).
790
+ upload_file(file_path,options)
791
+
792
+
793
+ return resp
794
+
795
+ rescue => e
796
+ puts e.message
797
+ return false
798
+
799
+ end
800
+ return true
801
+
802
+ end
803
+
804
+
805
+ def upload_small_files_s3(url_path, file_path, content_type)
806
+ url = URI.parse(url_path)
807
+ file = File.open(file_path, "rb")
808
+ body = file.read
809
+ begin
810
+ Net::HTTP.start(url.host) do |http|
811
+ http.send_request("PUT", url.request_uri, body, {
812
+ "content-type" => content_type,
813
+ })
814
+ end
815
+ return true
816
+ rescue Interrupt
817
+ return false
818
+ rescue
819
+ return false
820
+ end
821
+ end
822
+
823
+ def upload_url(file_path)
824
+ response = Cnvrg::API.request(@base_resource + "upload_url", 'POST', {file_s3_path: file_path})
825
+ if Cnvrg::CLI.is_response_success(response, false)
826
+ return response
827
+ else
828
+ return nil
829
+ end
830
+
831
+ end
832
+
833
+ def delete_file(absolute_path, relative_path, commit_sha1)
834
+ response = Cnvrg::API.request(@base_resource + "delete_file", 'DELETE', {absolute_path: absolute_path, relative_path: relative_path, commit_sha1: commit_sha1})
835
+ return Cnvrg::CLI.is_response_success(response, false)
836
+ end
837
+
838
+ def delete_dir(absolute_path, relative_path, commit_sha1)
839
+ response = Cnvrg::API.request(@base_resource + "delete_dir", 'DELETE', {absolute_path: absolute_path, relative_path: relative_path, commit_sha1: commit_sha1})
840
+ return Cnvrg::CLI.is_response_success(response, false)
841
+ end
842
+
843
+ def create_dir(absolute_path, relative_path, commit_sha1)
844
+ response = Cnvrg::API.request(@base_resource + "create_dir", 'POST', {absolute_path: absolute_path, relative_path: relative_path, commit_sha1: commit_sha1})
845
+ return Cnvrg::CLI.is_response_success(response, false)
846
+ end
847
+ def download_list_files_in_query(response, dataset_home)
848
+ sts_path = response["path_sts"]
849
+ if !Helpers.is_verify_ssl
850
+ body = open(sts_path, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
851
+ else
852
+ body = open(sts_path).read
853
+ end
854
+ split = body.split("\n")
855
+ key = split[0]
856
+ iv = split[1]
857
+
858
+ access = Cnvrg::Helpers.decrypt(key, iv, response["sts_a"])
859
+
860
+ secret = Cnvrg::Helpers.decrypt(key,iv, response["sts_s"])
861
+
862
+ session = Cnvrg::Helpers.decrypt(key,iv, response["sts_st"])
863
+ region = Cnvrg::Helpers.decrypt(key,iv, response["region"])
864
+
865
+ bucket = Cnvrg::Helpers.decrypt(key,iv, response["bucket"])
866
+ is_s3 = response["is_s3"]
867
+ if is_s3 or is_s3.nil?
868
+ client = Aws::S3::Client.new(
869
+ :access_key_id =>access,
870
+ :secret_access_key => secret,
871
+ :session_token => session,
872
+ :region => region,
873
+ :http_open_timeout => 60, :retry_limit => 20)
874
+ else
875
+ endpoint = Cnvrg::Helpers.decrypt(key,iv, response["endpoint_url"])
876
+ client = Aws::S3::Client.new(
877
+ :access_key_id =>access,
878
+ :secret_access_key => secret,
879
+ :region => region,
880
+ :endpoint=> endpoint,:force_path_style=> true,:ssl_verify_peer=>false,
881
+ :http_open_timeout => 60, :retry_limit => 20)
882
+ end
883
+ list_files = response["files"]
884
+ parallel_options = {
885
+ :progress => {
886
+ :title => "Download Progress",
887
+ :progress_mark => '=',
888
+ :format => "%b>>%i| %p%% %t",
889
+ :starting_at => 0,
890
+ :total => list_files.size,
891
+ :autofinish => true
892
+ },
893
+ in_threads: ParallelThreads
894
+ }
895
+ download_count = 0
896
+ Parallel.map((list_files), parallel_options) do |f|
897
+ file_key = Cnvrg::Helpers.decrypt(key,iv, f["path"])
898
+ begin
899
+ begin
900
+ dir = File.dirname f["fullpath"]
901
+ FileUtils.mkdir_p(dataset_home+"/"+ dir) unless File.exist? (dataset_home+"/"+ dir)
902
+ end
903
+
904
+ File.open(dataset_home+"/"+f["fullpath"], 'w+') do |file|
905
+ resp = client.get_object({bucket:bucket,
906
+ key:file_key}, target: file)
907
+ end
908
+ download_count += 1
909
+ rescue
910
+ end
911
+
912
+ end
913
+ if download_count == list_files.size
914
+ return true
915
+ else
916
+ return false
917
+ end
918
+
919
+
920
+
921
+
922
+ end
923
+
924
+
925
+ def download_file_s3(absolute_path, relative_path, project_home, conflict=false, commit_sha1=nil, as_link=false)
926
+ begin
927
+ res = Cnvrg::API.request(@base_resource + "download_file", 'POST', {absolute_path: absolute_path, relative_path: relative_path, commit_sha1: commit_sha1 ,new_version:true, as_link:as_link})
928
+ Cnvrg::CLI.is_response_success(res, false)
929
+ if res["result"]
930
+ file_url = res["result"]["file_url"]
931
+
932
+ if as_link
933
+ return res["result"]
934
+ end
935
+ # begin
936
+ # if !Helpers.is_verify_ssl
937
+ # tempfile = Down.download(file_url,open_timeout: 60,ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE )
938
+ #
939
+ # else
940
+ # tempfile = Down.download(file_url,open_timeout: 60)
941
+ #
942
+ # end
943
+ #
944
+ # FileUtils.move(tempfile.path, project_home+"/"+ absolute_path)
945
+ # return true
946
+ # rescue
947
+ #
948
+ # end
949
+ download_resp = res
950
+ filename = download_resp["result"]["filename"]
951
+
952
+ absolute_path += ".conflict" if conflict
953
+ sts_path = download_resp["result"]["path_sts"]
954
+ retries = 0
955
+ success= false
956
+ while !success and retries < 20
957
+ begin
958
+ if !Helpers.is_verify_ssl
959
+ body = open(sts_path, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
960
+ else
961
+ body = open(sts_path).read
962
+ end
963
+ success = true
964
+ rescue => e
965
+ retries +=1
966
+ sleep(5)
967
+
968
+ end
969
+ end
970
+ if !success
971
+ return false
972
+ end
973
+ split = body.split("\n")
974
+ key = split[0]
975
+ iv = split[1]
976
+
977
+ access = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["sts_a"])
978
+
979
+ secret = Cnvrg::Helpers.decrypt(key,iv, download_resp["result"]["sts_s"])
980
+
981
+ session = Cnvrg::Helpers.decrypt(key,iv, download_resp["result"]["sts_st"])
982
+ region = Cnvrg::Helpers.decrypt(key,iv, download_resp["result"]["region"])
983
+
984
+ bucket = Cnvrg::Helpers.decrypt(key,iv, download_resp["result"]["bucket"])
985
+ file_key = Cnvrg::Helpers.decrypt(key,iv, download_resp["result"]["key"])
986
+
987
+ is_s3 = download_resp["result"]["is_s3"]
988
+ if is_s3 or is_s3.nil?
989
+ client = Aws::S3::Client.new(
990
+ :access_key_id =>access,
991
+ :secret_access_key => secret,
992
+ :session_token => session,
993
+ :region => region,
994
+ :http_open_timeout => 60, :retry_limit => 20)
995
+ else
996
+ endpoint = Cnvrg::Helpers.decrypt(key,iv, download_resp["result"]["endpoint_url"])
997
+ client = Aws::S3::Client.new(
998
+ :access_key_id =>access,
999
+ :secret_access_key => secret,
1000
+ :region => region,
1001
+ :endpoint=> endpoint,:force_path_style=> true,:ssl_verify_peer=>false,
1002
+ :http_open_timeout => 60, :retry_limit => 20)
1003
+ end
1004
+
1005
+ File.open(project_home+"/"+absolute_path, 'w+') do |file|
1006
+ resp = client.get_object({bucket:bucket,
1007
+ key:file_key}, target: file)
1008
+ end
1009
+ return true
1010
+ end
1011
+
1012
+ rescue => e
1013
+ return false
1014
+
1015
+ end
1016
+ end
1017
+
1018
+ def download_data_file(commit_sha1, dataset_home)
1019
+ begin
1020
+ res = Cnvrg::API.request(@base_resource + "download_data_file", 'POST', {commit_sha1: commit_sha1,new_version:true})
1021
+ Cnvrg::CLI.is_response_success(res, false)
1022
+ if res["result"]
1023
+ download_resp = res
1024
+ filename = download_resp["result"]["filename"]
1025
+
1026
+ sts_path = download_resp["result"]["path_sts"]
1027
+ if !Helpers.is_verify_ssl
1028
+ body = open(sts_path, {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
1029
+ else
1030
+ body = open(sts_path).read
1031
+ end
1032
+ split = body.split("\n")
1033
+ key = split[0]
1034
+ iv = split[1]
1035
+
1036
+
1037
+ access = Cnvrg::Helpers.decrypt(key, iv, download_resp["result"]["sts_a"])
1038
+
1039
+ secret = Cnvrg::Helpers.decrypt(key,iv, download_resp["result"]["sts_s"])
1040
+
1041
+ session = Cnvrg::Helpers.decrypt(key,iv, download_resp["result"]["sts_st"])
1042
+ region = Cnvrg::Helpers.decrypt(key,iv, download_resp["result"]["region"])
1043
+
1044
+ bucket = Cnvrg::Helpers.decrypt(key,iv, download_resp["result"]["bucket"])
1045
+ file_key = Cnvrg::Helpers.decrypt(key,iv, download_resp["result"]["key"])
1046
+
1047
+ is_s3 = download_resp["result"]["is_s3"]
1048
+ if is_s3 or is_s3.nil?
1049
+ client = Aws::S3::Client.new(
1050
+ :access_key_id =>access,
1051
+ :secret_access_key => secret,
1052
+ :session_token => session,
1053
+ :region => region,
1054
+ :http_open_timeout => 60, :retry_limit => 20)
1055
+ else
1056
+ endpoint = Cnvrg::Helpers.decrypt(key,iv, download_resp["result"]["endpoint_url"])
1057
+ client = Aws::S3::Client.new(
1058
+ :access_key_id =>access,
1059
+ :secret_access_key => secret,
1060
+ :region => region,
1061
+ :endpoint=> endpoint,:force_path_style=> true,:ssl_verify_peer=>false,
1062
+ :http_open_timeout => 60, :retry_limit => 20)
1063
+ end
1064
+
1065
+
1066
+ File.open(dataset_home+"/"+filename, 'w+') do |file|
1067
+ resp = client.get_object({bucket: bucket,
1068
+ key: file_key }, target: file)
1069
+ end
1070
+ return filename
1071
+ end
1072
+
1073
+ rescue => e
1074
+ return false
1075
+
1076
+ end
1077
+ end
1078
+
1079
+ def download_file(absolute_path, relative_path, project_home, conflict=false)
1080
+ res = Cnvrg::API.request(@base_resource + "download_file", 'POST', {absolute_path: absolute_path, relative_path: relative_path})
1081
+ Cnvrg::CLI.is_response_success(res, false)
1082
+ if res["result"]
1083
+ res = res["result"]
1084
+ return false if res["link"].empty? or res["filename"].empty?
1085
+ filename = res["filename"]
1086
+ file_location = absolute_path.gsub(/#{filename}\/?$/, "")
1087
+
1088
+ FileUtils.mkdir_p project_home + "/" + file_location
1089
+ filename += ".conflict" if conflict
1090
+
1091
+ File.open("#{project_home}/#{file_location}/#{filename}", "w+") do |file|
1092
+ file.write open(res["link"]).read
1093
+ end
1094
+ else
1095
+ return false
1096
+ end
1097
+ return true
1098
+ end
1099
+
1100
+ def delete_commit_files_local(deleted)
1101
+ begin
1102
+ FileUtils.rm_rf(deleted) unless (deleted.nil? or deleted.empty?)
1103
+ return Cnvrg::Result.new(true, '')
1104
+ rescue => e
1105
+ return Cnvrg::Result.new(false, '')
1106
+ end
1107
+ end
1108
+
1109
+ def download_dir(dataset_home, absolute_path)
1110
+ FileUtils.mkdir_p("#{dataset_home}/#{absolute_path}")
1111
+ end
1112
+
1113
+ def revoke_download_dir(absolute_path)
1114
+ puts FileUtils.rmtree("#{absolute_path}")
1115
+ end
1116
+
1117
+ def revoke_download_file(absolute_path, filename, conflict=false)
1118
+ begin
1119
+ file_location = absolute_path.gsub(/#{filename}\/?$/, "")
1120
+
1121
+ filename += ".conflict" if conflict
1122
+ FileUtils.remove("#{file_location}/#{filename}")
1123
+ return true
1124
+ rescue
1125
+ return false
1126
+ end
1127
+ end
1128
+
1129
+ def revoke_download(tar_files, extracted_files)
1130
+ begin
1131
+ FileUtils.rm_rf(tar_files) unless (tar_files.nil? or tar_files.empty?)
1132
+ FileUtils.rm_rf(extracted_files) unless (extracted_files.nil? or extracted_files.empty?)
1133
+ rescue => e
1134
+ return false
1135
+ end
1136
+ return true
1137
+ end
1138
+
1139
+ def delete_commit(commit_sha1)
1140
+ response = Cnvrg::API.request("#{base_resource}/commit/#{commit_sha1}", 'DELETE')
1141
+ Cnvrg::CLI.is_response_success(response, true)
1142
+ return response
1143
+ end
1144
+
1145
+ def get_commit(commit_sha1)
1146
+ response = Cnvrg::API.request("#{base_resource}/commit/#{commit_sha1}", 'GET')
1147
+ Cnvrg::CLI.is_response_success(response, true)
1148
+ return response
1149
+ end
1150
+
1151
+ def start_commit(new_branch, force=false, chunks: 0, dataset: @dataset, message:nil)
1152
+ #if we are pushing with force or to branch we dont need to send current/next commit cause we want to
1153
+ # create a new commit.
1154
+ idx = {}
1155
+ commit = idx[:commit]
1156
+ next_commit = idx[:next_commit]
1157
+ response = Cnvrg::API.request(
1158
+ "#{base_resource}/commit/start",
1159
+ 'POST',
1160
+ {
1161
+ dataset_slug: @dataset_slug,
1162
+ new_branch: new_branch,
1163
+ force:force,
1164
+ username: @owner,
1165
+ current_commit: commit,
1166
+ next_commit: next_commit,
1167
+ total_chunks: chunks,
1168
+ message: message
1169
+ }
1170
+ )
1171
+ Cnvrg::CLI.is_response_success(response, true)
1172
+ response
1173
+ rescue => e
1174
+ false
1175
+ end
1176
+
1177
+ def end_commit(commit_sha1, force, success: true, uploaded_files: 0, commit_type: nil)
1178
+ begin
1179
+ response = Cnvrg::API.request(
1180
+ "#{base_resource}/commit/end",
1181
+ 'POST',
1182
+ {
1183
+ commit_sha1: commit_sha1,
1184
+ force:force,
1185
+ success: success,
1186
+ uploaded_files: uploaded_files,
1187
+ commit_type: commit_type
1188
+ }
1189
+ )
1190
+ Cnvrg::CLI.is_response_success(response, true)
1191
+ return response
1192
+ rescue => e
1193
+ return false
1194
+ end
1195
+ end
1196
+
1197
+ def end_commit_tar(commit_sha1, cur_idx)
1198
+ response = Cnvrg::API.request("#{base_resource}/commit/end_tar", 'POST', {commit_sha1: commit_sha1, idx: cur_idx})
1199
+ return response
1200
+ end
1201
+
1202
+ def rollback_commit(commit_sha1)
1203
+ response = Cnvrg::API.request("#{base_resource}/commit/rollback", 'POST', {commit_sha1: commit_sha1})
1204
+ Cnvrg::CLI.is_response_success(response, false)
1205
+ end
1206
+
1207
+ def clone_in_chunks(commit: 'latest', chunk_size: 1000)
1208
+ begin
1209
+
1210
+ end
1211
+ end
1212
+
1213
+ def get_trees(commit: "latest")
1214
+ response = Cnvrg::API.request("#{@base_resource}/clone_trees", 'POST',{commit: commit})
1215
+ return nil unless Cnvrg::CLI.is_response_success(response, false)
1216
+ response['result']['files']
1217
+ end
1218
+
1219
+ def get_clone_chunk(latest_id: nil, chunk_size: 1000, commit: 'latest')
1220
+ response = Cnvrg::API.request("#{@base_resource}/clone_chunk", 'POST',{commit: commit, chunk_size: chunk_size, latest_id: latest_id})
1221
+ unless Cnvrg::CLI.is_response_success(response, false)
1222
+ Cnvrg::Logger.log_info("#{{commit: commit, chunk_size: chunk_size, latest_id: latest_id}}")
1223
+ return nil
1224
+ end
1225
+ response['result']['files']
1226
+ end
1227
+
1228
+ def download_files_in_chunks(files, chunk_size: 1000, conflict: false, commit: 'latest', progress: nil)
1229
+ begin
1230
+ files.each_slice(chunk_size).each do |files|
1231
+ download_files_chunk(files, conflict: conflict, progress: progress)
1232
+ end
1233
+ return Cnvrg::Result.new(true, "Download Completed")
1234
+ rescue Exception => e
1235
+ return Cnvrg::Result.new(false, "Can`t download files")
1236
+ end
1237
+ end
1238
+
1239
+ def download_files_chunk(files, conflict: false, progress: nil)
1240
+ (1..5).each do |i|
1241
+ response = Cnvrg::API.request("users/#{@owner}/datasets/#{@dataset_slug}/download_multi", 'POST', {files: files})
1242
+ next unless Cnvrg::CLI.is_response_success(response, false) #trying to api request 5 times.
1243
+ files_to_download = response['files']
1244
+ data_home = "#{Dir.pwd}/#{response['name']}"
1245
+ res = download_multiple_files_s3(files_to_download, data_home, conflict: conflict, read_only: false, progressbar: progress)
1246
+ next unless res.is_success? #try again..
1247
+ return files_to_download['keys'].length
1248
+ end
1249
+ end
1250
+
1251
+ def download_multiple_chunks(commit, chunk_size=1000, progress: nil)
1252
+ begin
1253
+ last_chunk_size = chunk_size
1254
+ q = { commit: commit, chunk_size: chunk_size}
1255
+ overall = 0
1256
+ while last_chunk_size > 0
1257
+ response = Cnvrg::API.request("users/#{@owner}/datasets/#{@dataset_slug}/clone", 'POST', q)
1258
+ if Cnvrg::CLI.is_response_success(response, false)
1259
+ files = response['files']
1260
+ data_home = "#{Dir.pwd}/#{response['name']}"
1261
+ last_chunk_size = files['keys'].length
1262
+ break if last_chunk_size == 0
1263
+ res = download_multiple_files_s3(files, data_home, read_only: false, progressbar: progress)
1264
+ overall += last_chunk_size
1265
+ q[:latest] = files['latest']
1266
+ else
1267
+ last_chunk_size = 0
1268
+ end
1269
+ end
1270
+ Cnvrg::Result.new(true, "Cloned #{overall} files!")
1271
+ rescue => e
1272
+ Cnvrg::Result.new(false, "Cant download chunk", e.message, e.backtrace)
1273
+
1274
+ end
1275
+ end
1276
+
1277
+ def last_valid_commit()
1278
+ begin
1279
+ response = Cnvrg::API.request("#{base_resource}/last_valid_commit", 'GET')
1280
+ Cnvrg::CLI.is_response_success(response, true)
1281
+ return response
1282
+ rescue => e
1283
+ return false
1284
+ end
1285
+ end
1286
+
1287
+ def download_multiple_files_s3(files, project_home, conflict: false, progressbar: nil, read_only:false, flatten: false)
1288
+ begin
1289
+ refresh_storage_token
1290
+ parallel_options = {
1291
+ in_threads: ParallelThreads,
1292
+ isolation: true
1293
+ }
1294
+ Parallel.map(files["keys"], parallel_options) do |f|
1295
+ begin
1296
+ file_path = f['name']
1297
+ file_path = File.basename(f['name']) if flatten
1298
+ local_path = @dataset.local_path + '/' + file_path
1299
+ Cnvrg::Logger.log_info("Downloading #{local_path}")
1300
+ progressbar.progress += 1 if progressbar.present?
1301
+ if local_path.end_with? "/"
1302
+ @downloader.mkdir(local_path, recursive: true)
1303
+ next
1304
+ end
1305
+ # blob
1306
+ local_path = "#{local_path}.conflict" if conflict
1307
+ storage_path = f["path"]
1308
+ # if File.exists? local_path
1309
+ # Cnvrg::Logger.log_info("Trying to download #{local_path} but its already exists, skipping..")
1310
+ # next
1311
+ # end
1312
+ resp = @downloader.download(storage_path, local_path)
1313
+ Cnvrg::Logger.log_info("Download #{local_path} success resp: #{resp}")
1314
+ rescue => e
1315
+ Cnvrg::Logger.log_error(e)
1316
+ end
1317
+ end
1318
+ return Cnvrg::Result.new(true,"Downloaded successfully")
1319
+ rescue => e
1320
+ Cnvrg::Logger.log_error(e)
1321
+ return Cnvrg::Result.new(false,"Could not download some files", e.message, e.backtrace)
1322
+ end
1323
+ end
1324
+ end
1325
+ end