cnvrg 1.2.7 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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