cnvrg 1.2.7 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,33 @@
1
+ module Cnvrg
2
+ class JobCli < SubCommandBase
3
+
4
+ desc 'log', description: '', hide: true
5
+ method_option :level, :type => :string, :aliases => ["-l", "--level"], :default => 'info'
6
+ method_option :step, :type => :string, :aliases => ["-s", "--step"], :default => nil
7
+ def log(*logs)
8
+ Cnvrg::CLI.new.log_start(__method__, args, options)
9
+ @project = Project.new(owner: ENV['CNVRG_OWNER'], slug: ENV['CNVRG_PROJECT'])
10
+ @project.job_log(logs, level: options['level'], step: options['step'])
11
+ end
12
+
13
+
14
+ desc 'start', description: '', hide: true
15
+ def start(*logs)
16
+ cli = Cnvrg::CLI.new
17
+ cli.log_start(__method__, args, options)
18
+ @project = Project.new(nil, owner: ENV['CNVRG_OWNER'], slug: ENV['CNVRG_PROJECT'])
19
+ @executer = Helpers::Executer.new(project: @project, job_type: ENV['CNVRG_JOB_TYPE'], job_id: ENV['CNVRG_JOB_ID'])
20
+ commands = @executer.fetch_commands
21
+ @executer.execute_cmds(commands)
22
+ end
23
+
24
+ desc 'requirements', description: '', hide: true
25
+ def requirements
26
+ cli = Cnvrg::CLI.new
27
+ cli.log_start(__method__, args, options)
28
+ project_dir = cli.get_project_home
29
+ @project = Project.new(project_dir, owner: ENV['CNVRG_OWNER'], slug: ENV['CNVRG_PROJECT'])
30
+ end
31
+
32
+ end
33
+ end
@@ -7,11 +7,11 @@ module Cnvrg
7
7
  IDXParallelThreads ||= Cnvrg::Helpers.parallel_threads
8
8
 
9
9
 
10
- def initialize(project_home)
10
+ def initialize(project_home=nil, slug: nil, owner: nil)
11
11
  begin
12
12
  @local_path = project_home
13
13
  @working_dir = project_home
14
- config = YAML.load_file(project_home + "/.cnvrg/config.yml")
14
+ config = YAML.load_file(project_home + "/.cnvrg/config.yml") rescue {owner: owner, project_slug: slug}
15
15
  @title = config[:project_name]
16
16
  @slug = config[:project_slug]
17
17
  @owner = config[:owner]
@@ -126,7 +126,7 @@ module Cnvrg
126
126
 
127
127
  # Create project
128
128
 
129
- def self.create(project_name, clean, with_docker = false)
129
+ def self.create(project_name, clean, with_docker = false, bucket: nil)
130
130
  if clean
131
131
  list_dirs = [project_name, project_name + "/.cnvrg"]
132
132
  else
@@ -154,7 +154,7 @@ module Cnvrg
154
154
  begin
155
155
 
156
156
  owner = Cnvrg::CLI.get_owner()
157
- response = Cnvrg::API.request("cli/create_project", 'POST', {title: project_name, owner: owner, is_docker: with_docker})
157
+ response = Cnvrg::API.request("cli/create_project", 'POST', {title: project_name, owner: owner, is_docker: with_docker, bucket: bucket})
158
158
  Cnvrg::CLI.is_response_success(response)
159
159
  response = JSON.parse response["result"]
160
160
  project_slug = response["slug"]
@@ -177,7 +177,7 @@ module Cnvrg
177
177
  return true
178
178
  end
179
179
 
180
- def self.link(owner, project_name, docker = false, git = false)
180
+ def self.link(owner, project_name, docker = false, git = false, bucket: nil)
181
181
  ignore_exits = File.exist? ".cnvrgignore"
182
182
  list_dirs = [".cnvrg"
183
183
  ]
@@ -192,7 +192,7 @@ module Cnvrg
192
192
  cnvrgreadme = Helpers.readme_content
193
193
  cnvrgignore = Helpers.cnvrgignore_content
194
194
  begin
195
- response = Cnvrg::API.request("cli/create_project", 'POST', {title: project_name, owner: owner, is_docker: docker})
195
+ response = Cnvrg::API.request("cli/create_project", 'POST', {title: project_name, owner: owner, is_docker: docker, bucket: bucket})
196
196
  Cnvrg::CLI.is_response_success(response)
197
197
  response = JSON.parse response["result"]
198
198
  project_slug = response["slug"]
@@ -324,6 +324,30 @@ module Cnvrg
324
324
  YAML.load_file(@working_dir + "/.cnvrg/config.yml") rescue {}
325
325
  end
326
326
 
327
+ def get_storage_client
328
+ response = Cnvrg::API.request("users/#{@owner}/projects/#{@slug}/client", 'GET')
329
+ if Cnvrg::CLI.is_response_success(response, false)
330
+ client_params = response['client']
331
+ else
332
+ client_params = get_storage_client_fallback
333
+ end
334
+ Cnvrg::Downloader::Client.factory(client_params)
335
+ end
336
+
337
+ def get_storage_client_fallback
338
+ response = Cnvrg::API.request("users/#{@owner}/projects/#{@slug}/download_files", "POST", {files: [], commit: get_latest_commit})
339
+ raise StandardError.new("Can't find project credentials") unless Cnvrg::CLI.is_response_success(response, false)
340
+ files = response['result']
341
+ storage = files['is_s3'] ? 's3' : 'minio'
342
+ files['storage'] = storage
343
+ files
344
+ end
345
+
346
+ def get_latest_commit
347
+ resp = clone(0, '')
348
+ resp['result']['commit']
349
+ end
350
+
327
351
  def set_config(config)
328
352
  slug = config[:project_slug] rescue nil
329
353
  owner = config[:owner] rescue nil
@@ -631,6 +655,21 @@ module Cnvrg
631
655
  self.set_config(config)
632
656
  end
633
657
 
658
+ def job_log(logs, level: 'info', step: nil, job_type: nil, job_id: nil)
659
+ job_type ||= ENV['CNVRG_JOB_TYPE']
660
+ job_id ||= ENV['CNVRG_JOB_ID']
661
+ logs = [logs].flatten
662
+ if job_type.blank? or job_id.blank?
663
+ raise StandardError.new("Cant find job env variables")
664
+ end
665
+ Cnvrg::API.request("users/#{@owner}/projects/#{@slug}/jobs/#{job_type.underscore}/#{job_id}/log", "POST", {job_type: job_type, job_id: job_id, logs: logs, log_level: level, step: step, timestamp: Time.now})
666
+ end
667
+
668
+
669
+ def job_commands
670
+ job_type, job_id = ENV['CNVRG_JOB_TYPE'], ENV['CNVRG_JOB_ID']
671
+ resp = Cnvrg::API.request("users/#{@owner}/projects/#{@slug}/jobs/#{job_type.underscore}/#{job_id}/commands", "GET")
672
+ end
634
673
 
635
674
  def spot_will_terminate
636
675
  restart = false
@@ -0,0 +1,128 @@
1
+ module Cnvrg
2
+ class Storage
3
+ def initialize(dataset: nil, project: nil, root_path: nil)
4
+ @element = dataset || project
5
+ @root_path = root_path
6
+ @client = @element.get_storage_client
7
+ end
8
+
9
+ def log_error(action: nil, error: '')
10
+ "[#{Time.now}] (#{action || 'default'}) #{error}"
11
+ end
12
+
13
+
14
+ def get_chunks_size
15
+ (ENV['CNVRG_STORAGE_CHUNK_SIZE'] || 10).to_i
16
+ end
17
+
18
+ def init_progress_bar(size: nil, title: "Download Progress")
19
+ @progressbar = ProgressBar.create(:title => title,
20
+ :progress_mark => '=',
21
+ :format => "%b>>%i| %p%% %t",
22
+ :starting_at => 0,
23
+ :total => size,
24
+ :autofinish => true)
25
+ end
26
+
27
+ def make_progress(size: 1)
28
+ @progressbar.progress += size
29
+ end
30
+
31
+
32
+ def clone(commit: nil)
33
+ files_generator = Proc.new do |params|
34
+ @element.get_clone_chunk(commit: commit, chunk_size: params[:limit], offset: params[:offset])
35
+ end
36
+ action = Proc.new do |storage, local|
37
+ @client.download(storage, local)
38
+ end
39
+
40
+ @stats = @element.get_stats
41
+ progress = {size: @stats['commit_size'], title: "Clone Progress"}
42
+
43
+ storage_action(files_generator: files_generator, action: action, progress: progress)
44
+ end
45
+
46
+ def upload_files(commit: nil)
47
+
48
+ end
49
+
50
+ def upload_files(files_generator, progress: {size: 0, title: ''})
51
+ init_progress_bar(progress)
52
+ @storage_errors = []
53
+ @finished = false
54
+ @files = Queue.new
55
+ t = Thread.new{file_gen_thread(files_generator)}
56
+ do_parallel{|file| self.upload_files_thread(file); self.make_progress(size: file['size'])}
57
+ t.join
58
+ handle_errors
59
+ end
60
+
61
+ def file_gen_upload_thread(files_generator)
62
+ while true
63
+ files = files_generator
64
+ files.each{|f| @files.push(f)}
65
+ break if files.blank?
66
+ end
67
+ @finished = true
68
+ end
69
+
70
+ def storage_action(files_generator: nil, action: nil, progress: {size: 0, title: ''})
71
+ ### the generator files should have {path (encrypted), name, size}
72
+ init_progress_bar(progress)
73
+ @storage_errors = []
74
+ @finished = false
75
+ @files = Queue.new
76
+ t = Thread.new{file_gen_thread(files_generator)}
77
+ do_parallel do |file|
78
+ self.download_file_thread(file) do |local, storage|
79
+ action.call(local, storage)
80
+ end
81
+ self.make_progress(size: file['size'])
82
+ end
83
+ t.join
84
+ handle_errors
85
+ end
86
+
87
+ def file_gen_thread(file_gen)
88
+ offset = 0
89
+ chunk_size = get_chunks_size
90
+ while true
91
+ files = file_gen.call(limit: chunk_size, offset: offset)
92
+ break if files.blank?
93
+ files.each{|f| @files.push(f)}
94
+ offset += files.size
95
+ end
96
+ @finished = true
97
+ end
98
+
99
+ def handle_errors
100
+ if @storage_errors.present?
101
+ File.open(@element.working_dir + "/.cnvrg/errors.yml", "w+"){|f| f.write @storage_errors.to_yaml}
102
+ end
103
+ end
104
+
105
+ def do_parallel
106
+ Parallel.each( -> { @files.empty? ? (@finished ? Parallel::Stop : sleep(1)) : @files.pop }, in_threads: get_chunks_size) do |file|
107
+ if file == 1
108
+ next
109
+ end
110
+ yield(file)
111
+ end
112
+ end
113
+
114
+ def download_file_thread(file)
115
+ return if file.blank?
116
+ local_path = file['name']
117
+ storage_path = file['path']
118
+ (0..5).each do
119
+ begin
120
+ # @client.download(storage_path, "#{@root_path}/#{local_path}")
121
+ break
122
+ rescue => e
123
+ log_error(action: "download #{local_path}", error: e.message)
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -1,4 +1,4 @@
1
1
  module Cnvrg
2
- VERSION = '1.2.7'
2
+ VERSION = '1.3.2'
3
3
  end
4
4
 
metadata CHANGED
@@ -1,30 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cnvrg
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.7
4
+ version: 1.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yochay Ettun
8
8
  - Leah Kolben
9
+ - Omer Shacham
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2019-03-26 00:00:00.000000000 Z
13
+ date: 2019-05-05 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: bundler
16
17
  requirement: !ruby/object:Gem::Requirement
17
18
  requirements:
18
- - - "~>"
19
+ - - ">="
19
20
  - !ruby/object:Gem::Version
20
- version: '1.11'
21
+ version: '0'
21
22
  type: :development
22
23
  prerelease: false
23
24
  version_requirements: !ruby/object:Gem::Requirement
24
25
  requirements:
25
- - - "~>"
26
+ - - ">="
26
27
  - !ruby/object:Gem::Version
27
- version: '1.11'
28
+ version: '0'
28
29
  - !ruby/object:Gem::Dependency
29
30
  name: rake
30
31
  requirement: !ruby/object:Gem::Requirement
@@ -217,6 +218,20 @@ dependencies:
217
218
  - - "~>"
218
219
  - !ruby/object:Gem::Version
219
220
  version: '2'
221
+ - !ruby/object:Gem::Dependency
222
+ name: google-cloud-storage
223
+ requirement: !ruby/object:Gem::Requirement
224
+ requirements:
225
+ - - "~>"
226
+ - !ruby/object:Gem::Version
227
+ version: '1.16'
228
+ type: :runtime
229
+ prerelease: false
230
+ version_requirements: !ruby/object:Gem::Requirement
231
+ requirements:
232
+ - - "~>"
233
+ - !ruby/object:Gem::Version
234
+ version: '1.16'
220
235
  - !ruby/object:Gem::Dependency
221
236
  name: sucker_punch
222
237
  requirement: !ruby/object:Gem::Requirement
@@ -379,18 +394,24 @@ files:
379
394
  - lib/cnvrg/data.rb
380
395
  - lib/cnvrg/datafiles.rb
381
396
  - lib/cnvrg/dataset.rb
397
+ - lib/cnvrg/downloader/client.rb
398
+ - lib/cnvrg/downloader/clients/azure_client.rb
399
+ - lib/cnvrg/downloader/clients/gcp_client.rb
400
+ - lib/cnvrg/downloader/clients/s3_client.rb
382
401
  - lib/cnvrg/experiment.rb
383
402
  - lib/cnvrg/files.rb
384
403
  - lib/cnvrg/flow.rb
385
404
  - lib/cnvrg/helpers.rb
405
+ - lib/cnvrg/helpers/executer.rb
386
406
  - lib/cnvrg/hyper.rb
387
- - lib/cnvrg/job.rb
407
+ - lib/cnvrg/job_cli.rb
388
408
  - lib/cnvrg/logger.rb
389
409
  - lib/cnvrg/org_helpers.rb
390
410
  - lib/cnvrg/project.rb
391
411
  - lib/cnvrg/result.rb
392
412
  - lib/cnvrg/runner.rb
393
413
  - lib/cnvrg/ssh.rb
414
+ - lib/cnvrg/storage.rb
394
415
  - lib/cnvrg/task.rb
395
416
  - lib/cnvrg/version.rb
396
417
  homepage: https://cnvrg.io
@@ -1,40 +0,0 @@
1
- require 'mimemagic'
2
- require 'aws-sdk'
3
- require 'URLcrypt'
4
-
5
- require 'sucker_punch'
6
- module Cnvrg
7
-
8
- class LogJob
9
- include SuckerPunch::Job
10
-
11
- def perform(upload_resp, file_path)
12
- begin
13
- sts_path = upload_resp["result"]["path_sts"]
14
- uri = URI.parse(sts_path)
15
- http_object = Net::HTTP.new(uri.host, uri.port)
16
- http_object.use_ssl = true if uri.scheme == 'https'
17
- request = Net::HTTP::Get.new(sts_path)
18
- body = ""
19
- http_object.start do |http|
20
- response = http.request request
21
- body = response.read_body
22
- end
23
- URLcrypt::key = [body].pack('H*')
24
- s3 = Aws::S3::Resource.new(
25
- :access_key_id => URLcrypt.decrypt(upload_resp["result"]["sts_a"]),
26
- :secret_access_key => URLcrypt.decrypt(upload_resp["result"]["sts_s"]),
27
- :session_token => URLcrypt.decrypt(upload_resp["result"]["sts_st"]),
28
- :region => URLcrypt.decrypt(upload_resp["result"]["region"]))
29
- resp = s3.bucket(URLcrypt.decrypt(upload_resp["result"]["bucket"])).
30
- object(upload_resp["result"]["path"]+"/"+File.basename(file_path)).
31
- upload_file(file_path)
32
- return resp
33
- rescue =>e
34
- return false
35
-
36
- end
37
- return true
38
- end
39
- end
40
- end