cnvrg 1.5.9.1 → 1.5.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a983ee8a4491253e98fa4704ba878788639792c5975b8cd4efbaf2b7292f978a
4
- data.tar.gz: 23aaaa8dcd6b9d476c4585a9240106a7460035e9d735297b60160d9784247870
3
+ metadata.gz: 15c9e9bdcf068b1bcba64ac65c5589ea53d39478cb50e251f4d956eab7e5a40a
4
+ data.tar.gz: d4b7bd60ace357d13f502771c260c039de02bf4c6b7894510e2db52b6026dc38
5
5
  SHA512:
6
- metadata.gz: 169f0fe0cfc5d26ca600c4d07a0efb6df74490b1ac89a2c0ff3a9dd385e0639cf82d9ece70705383a66a9af0cd8b245d8a6981b493aa126a4f299a9778ff3762
7
- data.tar.gz: 8eaecd67497635a7e6ee1aff41f22a2b2f66faf7a211feed8d90d71c9e9d822a9dc7466042082a31f770dd3b6b743c237d41f7b6c650fc3fd0388d068e26a882
6
+ metadata.gz: fb8813704368baf2e80422248d948b29bc4189dd703c77f670b3056b446cffdf8867edcd552003eb40cc21fac0b80257faded1e18faeca912733f50bf1aa711b
7
+ data.tar.gz: f51367399df0f4a8faa3a1d6e7f160b77050c6f4a9eba88ea5963baeaae7eb7f07dde7e06c297c8003c0b0114dcfe6fcce4a3ff8011e5db319188f2789d7a13e
@@ -29,6 +29,7 @@ require 'cnvrg/project'
29
29
  require 'cnvrg/files'
30
30
  require 'cnvrg/experiment'
31
31
  require 'cnvrg/Images'
32
+ require 'cnvrg/image'
32
33
  require 'cnvrg/dataset'
33
34
  require 'cnvrg/datafiles'
34
35
  require 'cnvrg/data'
@@ -40,6 +41,7 @@ require 'cnvrg/org_helpers'
40
41
  require 'cnvrg/cli/subcommand'
41
42
  require 'cnvrg/cli/flow'
42
43
  require 'cnvrg/cli/task'
44
+ require 'cnvrg/image_cli'
43
45
  require 'cnvrg/helpers/executer'
44
46
  require 'cnvrg/downloader/client'
45
47
  require 'cnvrg/downloader/clients/s3_client'
@@ -160,7 +162,7 @@ module Cnvrg
160
162
 
161
163
  class << self
162
164
  # Hackery.Take the run method away from Thor so that we can redefine it.
163
-
165
+
164
166
  def is_thor_reserved_word?(word, type)
165
167
  return false if word == "run"
166
168
  super
@@ -172,7 +174,11 @@ module Cnvrg
172
174
  desc "job", "manage running jobs", :hide => false
173
175
  subcommand "job", JobCli
174
176
 
175
- desc "flow", "mange project flows", :hide => true
177
+ desc "image [COMMAND]", "build existing images", :hide => true
178
+ subcommand "image", ImageCli
179
+
180
+
181
+ desc "flow", "mange project flows", :hide => true
176
182
  subcommand "flow", Cnvrg::Commands::Flow
177
183
 
178
184
 
@@ -855,7 +861,7 @@ module Cnvrg
855
861
  method_option :read, :type => :boolean, :aliases => ["-r", "--read"], :default => false
856
862
  method_option :remote, :type => :boolean, :aliases => ["-h", "--remote"], :default => false
857
863
 
858
- def clone_data(dataset_url,only_tree=false,commit=nil,query=nil,read=false,remote=false)
864
+ def clone_data(dataset_url,only_tree=false,commit=nil,query=nil,read=false,remote=false, relative: false)
859
865
  begin
860
866
  verify_logged_in(false)
861
867
  log_start(__method__, args, options)
@@ -885,8 +891,9 @@ module Cnvrg
885
891
  @files = Cnvrg::Datafiles.new(owner, slug, dataset: @dataset)
886
892
  log_message("Downloading files", Thor::Shell::Color::BLUE)
887
893
  if @dataset.softlinked?
888
- @files.cp_ds
889
- Cnvrg::CLI.log_message("Clone finished successfully", Thor::Shell::Color::GREEN)
894
+ @files.cp_ds(relative)
895
+ @executer.set_dataset_status(dataset: @dataset.slug, status: "cloned") if @executer
896
+ log_message("#{check} Clone finished successfully", Thor::Shell::Color::GREEN)
890
897
  @dataset.write_success
891
898
  return
892
899
  end
@@ -907,7 +914,7 @@ module Cnvrg
907
914
  :total => files_count,
908
915
  :autofinish => true)
909
916
 
910
-
917
+
911
918
  while files['keys'].length > 0
912
919
  Cnvrg::Logger.log_info("download multiple files, #{downloaded_files.size} files downloaded")
913
920
  @files.download_multiple_files_s3(files, @dataset.local_path, progressbar: progressbar, read_only: read)
@@ -1745,6 +1752,10 @@ module Cnvrg
1745
1752
 
1746
1753
  clone_resp = Project.clone_dir_remote(slug, owner, slug,true)
1747
1754
  idx_status = Project.new(get_project_home).generate_idx
1755
+ @executer = Cnvrg::Helpers::Executer.get_executer
1756
+ if @executer.present?
1757
+ @executer.update_git_commit
1758
+ end
1748
1759
  end
1749
1760
 
1750
1761
 
@@ -2342,17 +2353,18 @@ module Cnvrg
2342
2353
  end
2343
2354
  end
2344
2355
  rescue => e
2356
+ error_message = "Error occured, #{e.message}\nAborting"
2345
2357
  if e.is_a? SignalException
2346
2358
  say "\nAborting", Thor::Shell::Color::BLUE
2347
2359
  say "\nRolling back all changes", Thor::Shell::Color::BLUE
2348
2360
  else
2349
- log_message("Error occurred, \nAborting", Thor::Shell::Color::RED)
2361
+ log_message(error_message, Thor::Shell::Color::RED)
2350
2362
  log_error(e)
2351
2363
  end
2352
2364
  @files.rollback_commit(commit_sha1) unless commit_sha1.nil?
2353
2365
  print_res = {
2354
2366
  'success' => "false",
2355
- 'message' => 'couldn\'t commit changes, Rolling Back all changes.'
2367
+ 'message' => error_message
2356
2368
  }
2357
2369
  puts "\n"
2358
2370
  puts JSON[print_res] if return_id
@@ -2465,7 +2477,7 @@ module Cnvrg
2465
2477
  :total => update_total,
2466
2478
  :autofinish => true)
2467
2479
  conflicts = @files.mark_conflicts(result)
2468
-
2480
+
2469
2481
  log_message("Found some conflicts, check .conflict files.", Thor::Shell::Color::BLUE) if conflicts > 0
2470
2482
  update_res = @files.download_files_in_chunks(result["updated_on_server"], progress: progressbar) if result["updated_on_server"].present?
2471
2483
  added_res = @files.download_files_in_chunks(result["added"], progress: progressbar) if result["added"].present?
@@ -2492,7 +2504,7 @@ module Cnvrg
2492
2504
  else
2493
2505
  log_message("#{check} Downloaded changes successfully", Thor::Shell::Color::GREEN, ((sync or options["sync"]) ? false : true))
2494
2506
  end
2495
- return true
2507
+ return true
2496
2508
  end
2497
2509
  rescue SignalException => e
2498
2510
  Cnvrg::Logger.log_error(e)
@@ -90,15 +90,17 @@ module Cnvrg
90
90
  method_option :query, :type => :string, :aliases => ["-q", "--query"], :default => nil
91
91
  method_option :read, :type => :boolean, :aliases => ["-r", "--read"], :default => false
92
92
  method_option :remote, :type => :boolean, :aliases => ["-h", "--remote"], :default => false
93
+ method_option :relative, :type => :boolean, :aliases => ["-rel", "--relative"], :default => false
93
94
 
94
95
  def clone(dataset_url)
96
+ #test
95
97
  cli = Cnvrg::CLI.new()
96
98
  only_tree =options[:only_tree]
97
99
  commit =options[:commit]
98
100
  query =options[:query]
99
101
  read = options[:read]
100
102
  remote = options[:remote]
101
- cli.clone_data(dataset_url, only_tree=only_tree,commit=commit, query=query, read=read, remote=remote)
103
+ cli.clone_data(dataset_url, only_tree=only_tree,commit=commit, query=query, read=read, remote=remote, relative: options[:relative])
102
104
  end
103
105
 
104
106
  desc 'data verify DATASETS_TITLES', 'verify datasets', :hide => true
@@ -70,9 +70,9 @@ module Cnvrg
70
70
  end
71
71
  end
72
72
 
73
- def cp_ds
73
+ def cp_ds(relative: false)
74
74
  prefix = @dataset.get_dataset["bucket_prefix"]
75
- current_batch = @downloader.fetch_files(prefix: prefix, limit: 500)
75
+ batch_size = 10000
76
76
  pbar = ProgressBar.create(:title => "Download Progress",
77
77
  :progress_mark => '=',
78
78
  :format => "%b%i| %c Files downloaded",
@@ -83,19 +83,21 @@ module Cnvrg
83
83
  in_threads: ParallelThreads,
84
84
  in_processes: Cnvrg::CLI::ParallelProcesses,
85
85
  isolation: true,
86
- finish: ->(*args) {pbar.progress += 1}
86
+ finish: ->(*args) { pbar.progress += 1 }
87
87
  }
88
- while current_batch.size > 0
88
+ finished = false
89
+ while not finished
90
+ current_batch, marker = @downloader.fetch_files(prefix: prefix, marker: marker, limit: batch_size)
91
+ if marker.blank?
92
+ finished = true
93
+ end
89
94
  Parallel.map(current_batch, parallel_options) do |file|
90
- #current_batch.map do |file|
91
95
  next if file.end_with? "/"
92
- cutted_key = Cnvrg::Downloader::Clients::S3Client.cut_prefix(prefix, file)
96
+ cutted_key = relative ? @downloader.cut_prefix(prefix, file) : file
93
97
  dest_path = File.join(@dataset.local_path, cutted_key)
94
98
  @downloader.download(file, dest_path, decrypt: false)
95
99
  file
96
100
  end
97
- marker = current_batch.last
98
- current_batch = @downloader.fetch_files(prefix: prefix, marker: marker, limit: 500)
99
101
  end
100
102
  end
101
103
 
@@ -9,6 +9,7 @@ module Cnvrg
9
9
 
10
10
  def initialize(project_home = '', dataset_url: '')
11
11
  begin
12
+ @info = {}
12
13
  if project_home.present?
13
14
  @local_path = project_home
14
15
  @working_dir = project_home
@@ -28,6 +29,10 @@ module Cnvrg
28
29
  end
29
30
  end
30
31
 
32
+ def soft_linked?
33
+ @dataset_call["dataset_type"] == "soft_link_dataset"
34
+ end
35
+
31
36
  def init_home(remote: false)
32
37
  dataset_home = File.join(Dir.pwd, @slug)
33
38
  if Dir.exists? dataset_home
@@ -17,6 +17,10 @@ module Cnvrg
17
17
  sts.split("\n")
18
18
  end
19
19
 
20
+ def cut_prefix(prefix, file)
21
+ file.gsub(prefix, '').gsub(/^\/*/, '')
22
+ end
23
+
20
24
  def download(storage_path, local_path)
21
25
  ### need to be implemented..
22
26
  end
@@ -23,6 +23,13 @@ module Cnvrg
23
23
  client.create_block_blob(@container, storage_path, File.open(local_path, "rb"))
24
24
  end
25
25
 
26
+ def fetch_files(prefix: nil, marker: nil, limit: 10000)
27
+ blobs = client.list_blobs(@container, prefix: prefix, max_results: limit, marker: marker)
28
+ next_marker = blobs.continuation_token
29
+ files = blobs.map{|x| x.name}
30
+ [files, next_marker]
31
+ end
32
+
26
33
 
27
34
  private
28
35
  def client
@@ -61,11 +61,6 @@ module Cnvrg
61
61
  batch_files.to_a.map(&:key)
62
62
  end
63
63
 
64
- def self.cut_prefix(prefix, file)
65
- file.gsub(prefix, '').gsub(/^\/*/, '')
66
- end
67
-
68
-
69
64
  private
70
65
  def aws_client
71
66
  Aws::S3::Client.new(@options)
@@ -88,16 +88,22 @@ module Cnvrg
88
88
  # resolve bucket
89
89
  res = resp['result']
90
90
  files = res['files']
91
+
91
92
  #upload files
92
- # files.keys.map do |file|
93
- Parallel.map(files.keys, self.get_upload_options) do |file|
94
- resp = Cnvrg::Helpers.try_until_success{self.upload_single_file(files[file].merge(files_list[file]))}
95
- raise SignalException.new("Cant upload #{file}") unless resp
93
+ blob_ids = Parallel.map(files.keys, self.get_upload_options) do |file|
94
+ begin
95
+ Cnvrg::Helpers.try_until_success{self.upload_single_file(files[file].merge(files_list[file]))}
96
+ rescue => e
97
+ Cnvrg::CLI.log_message("Failed to upload #{file}: #{e.message}", 'red')
98
+ Cnvrg::Logger.log_error(e)
99
+ Cnvrg::Logger.log_method(bind: binding)
100
+ raise e
101
+ end
96
102
  progress.progress += 1 if progress.present?
103
+ files[file]["bv_id"]
97
104
  end
98
105
 
99
106
  #save files on the server.
100
- blob_ids = files.values.map {|f| f['bv_id']}
101
107
  resp = Cnvrg::API.request(@base_resource + "upload_files_save", 'POST', {blob_ids: blob_ids, commit: commit_sha1})
102
108
  unless Cnvrg::CLI.is_response_success(resp, false)
103
109
  raise SignalException.new("Cant save uploaded files to the server.")
@@ -33,22 +33,20 @@ module Cnvrg
33
33
  end
34
34
  end
35
35
 
36
- def try_until_success(tries: 5)
37
- (0..tries).each do |i|
36
+ def try_until_success(tries: 3)
37
+ exception = nil
38
+ tries.times do |i|
38
39
  begin
39
40
  yield
40
41
  return true
41
- rescue Exception => e
42
- Cnvrg::Logger.log_info("Error while trying for the #{i} time")
43
- Cnvrg::Logger.log_error(e)
44
- sleep(5)
45
42
  rescue => e
46
43
  Cnvrg::Logger.log_info("Error while trying for the #{i} time")
47
44
  Cnvrg::Logger.log_error(e)
48
- sleep(5)
45
+ sleep(1)
46
+ exception = e
49
47
  end
50
48
  end
51
- raise StandardError.new("Failed")
49
+ raise exception
52
50
  end
53
51
 
54
52
  def get_config
@@ -1,5 +1,6 @@
1
1
  class Cnvrg::Helpers::Executer
2
- def initialize(project: nil, job_type: nil, job_id: nil)
2
+ def initialize(project: nil, job_type: nil, job_id: nil, image: nil)
3
+ @image = image
3
4
  @project = project || Cnvrg::Project.new(owner: ENV['CNVRG_OWNER'], slug: ENV['CNVRG_PROJECT'])
4
5
  @job_type = job_type || ENV['CNVRG_JOB_TYPE']
5
6
  @job_id = job_id || ENV['CNVRG_JOB_ID']
@@ -69,7 +70,7 @@ class Cnvrg::Helpers::Executer
69
70
  if command[:type] == "file_exists"
70
71
  puts "Looking for file #{command[:file]}"
71
72
  else
72
- puts "Execute #{command[:command]}"
73
+ puts "Execute #{command[:command]}" unless command[:no_stdout]
73
74
  end
74
75
  execute(command)
75
76
  end
@@ -81,6 +82,13 @@ class Cnvrg::Helpers::Executer
81
82
  commands.map{|k| k.with_indifferent_access}
82
83
  end
83
84
 
85
+
86
+ def update_git_commit
87
+ git_commit = `git rev-parse --verify HEAD`
88
+ return if git_commit.blank?
89
+ Cnvrg::API.request("#{base_url}/update_git_commit", "POST", {git_commit: git_commit.strip!})
90
+ end
91
+
84
92
  def set_dataset_status(dataset: nil, status: nil)
85
93
  Cnvrg::API.request("#{base_url}/datasets/#{dataset}", "PUT", {status: status})
86
94
  end
@@ -131,12 +139,15 @@ class Cnvrg::Helpers::Executer
131
139
  output = []
132
140
  start_time = Time.now
133
141
  timeout = cmd[:timeout] || 5*60
142
+ exit_status = nil
134
143
  t = Thread.new do
135
144
  PTY.spawn(cmd[:command]) do |stdout, stdin, pid, stderr|
136
145
  begin
137
- stdout.each do |line|
138
- puts line
139
- output << {log: line.strip, timestamp: Time.now}
146
+ if stdout.present?
147
+ stdout.each do |line|
148
+ puts line
149
+ output << {log: line.strip, timestamp: Time.now}
150
+ end
140
151
  end
141
152
  if stderr.present?
142
153
  stderr.each do |line|
@@ -148,16 +159,17 @@ class Cnvrg::Helpers::Executer
148
159
  end
149
160
  ::Process.wait pid
150
161
  end
162
+ exit_status = $?.exitstatus
151
163
  end
152
164
  while t.status
153
165
  if Time.now - start_time > timeout
154
166
  puts "Kill thread because of timeout..."
155
167
  errors << {log: "Timeout", timestamp: Time.now}
156
168
  Thread.kill(t)
169
+ exit_status = -100 ##killed
157
170
  end
158
171
  sleep 1
159
172
  end
160
- exit_status = $?.exitstatus
161
173
  end_time = Time.now
162
174
  [exit_status, merge_log_block(output), merge_log_block(errors), start_time, end_time]
163
175
  end
@@ -185,7 +197,11 @@ class Cnvrg::Helpers::Executer
185
197
 
186
198
 
187
199
  def job_log(logs, level: 'info', step: nil)
188
- @project.job_log(logs, level: level, step: step, job_type: @job_type, job_id: @job_id)
200
+ if @job_type == "image"
201
+ @image.job_log(logs, level: level, step: step)
202
+ else
203
+ @project.job_log(logs, level: level, step: step, job_type: @job_type, job_id: @job_id)
204
+ end
189
205
  end
190
206
 
191
207
  end
@@ -0,0 +1,100 @@
1
+ module Cnvrg
2
+ class Image
3
+ # attr_reader :image_name, :image_tag, :is_docker, :project_slug, :commit_id, :owner, :port, :image_slug
4
+
5
+
6
+ def initialize(image_id)
7
+ begin
8
+ @cli = Cnvrg::CLI.new
9
+ home_dir = File.expand_path('~')
10
+ config = YAML.load_file(home_dir+"/.cnvrg/config.yml")
11
+ @owner = config.to_h[:owner]
12
+ @username = config.to_h[:username]
13
+ @image_id = image_id
14
+ rescue => e
15
+ @owner = ""
16
+ @username = ""
17
+ @cli.log_message("cnvrg is not configured")
18
+ end
19
+ end
20
+
21
+ def build
22
+ image_data = get_image_data
23
+ file_name = "Dockerfile-#{@image_id}"
24
+ File.new(file_name, "w+")
25
+ if image_data["reqs_file_path"].present? and image_data["from_image_name"]
26
+ File.open(file_name, "w+") do |i|
27
+ i.write("FROM #{image_data["from_image_name"]}")
28
+ i.write("ADD requirements.txt requirements.txt")
29
+ i.write("RUN pip3 install -r requirements.txt")
30
+ end
31
+ else
32
+ open(file_name, 'wb') do |file|
33
+ file << open(image_data["docker_file_path"]).read
34
+ end
35
+ end
36
+ command = {:type=>"notify",
37
+ :title=>"docker build",
38
+ :logs=>true,
39
+ :command=>"sudo docker build . -t #{image_data["docker_name"]} -f #{file_name}"}
40
+
41
+ @executer = Helpers::Executer.new(project: @project, job_type: "image", job_id: @image_id, image: self)
42
+ exit_status, output, errors, _, _ = @executer.execute(command)
43
+ all_logs = join_logs(output, errors)
44
+ if exit_status > 0
45
+ raise StandardError.new(all_logs)
46
+ end
47
+ if ENV["CNVRG_IMAGE_BUILD_USERNAME"].present? and ENV["CNVRG_IMAGE_BUILD_PASSWORD"].present?
48
+ command = {:type=>"notify",
49
+ :no_stdout => true,
50
+ :title=>"docker login",
51
+ :logs=>true,
52
+ :command=>"sudo docker login --username=#{ENV["CNVRG_IMAGE_BUILD_USERNAME"]} --password=\"#{ENV["CNVRG_IMAGE_BUILD_PASSWORD"]}\""}
53
+ exit_status, output, errors, _, _ = @executer.execute(command)
54
+ all_logs = join_logs(output, errors)
55
+ if exit_status > 0
56
+ raise StandardError.new(all_logs)
57
+ end
58
+ end
59
+ command = {:type=>"notify",
60
+ :title=>"docker push",
61
+ :logs=>true,
62
+ :command=>"sudo docker push #{image_data["docker_name"]}"}
63
+ exit_status, output, errors, _, _ = @executer.execute(command)
64
+ all_logs = join_logs(output, errors)
65
+ if exit_status > 0
66
+ raise StandardError.new(all_logs)
67
+ end
68
+ post_build_update(true)
69
+ rescue => e
70
+ post_build_update(false, e.message)
71
+ end
72
+
73
+ def get_image_data
74
+ response = Cnvrg::API.request("users/#{@owner}/images/#{@image_id}/image_start_build", 'GET')
75
+ CLI.is_response_success(response)
76
+ return response["image"]
77
+ end
78
+
79
+ def post_build_update(success, message = "")
80
+ response = Cnvrg::API.request("users/#{@owner}/images/#{@image_id}/image_end_build", 'POST', {success: success, message: message})
81
+ CLI.is_response_success(response)
82
+ return response["image"]
83
+ end
84
+
85
+
86
+ def job_log(logs, level: 'info', step: nil, job_type: "image", job_id: @image_id)
87
+ logs = [logs].flatten
88
+ logs.each_slice(10).each do |temp_logs|
89
+ Cnvrg::API.request("users/#{@owner}/images/#{@image_id}/log", "POST", {job_type: job_type, job_id: job_id, logs: temp_logs, log_level: level, step: step, timestamp: Time.now})
90
+ sleep(1)
91
+ end
92
+ end
93
+
94
+
95
+ def join_logs(output, errors)
96
+ output.map{ |o| o[:logs]}.join(" ") + " " + errors.map{ |o| o[:logs]}.join(" ")
97
+ end
98
+
99
+ end
100
+ end
@@ -0,0 +1,25 @@
1
+
2
+ module Cnvrg
3
+ class ImageCli < SubCommandBase
4
+
5
+ desc 'image build --image=IMAGE_ID', 'Build image job', :hide => true
6
+ method_option :image_id, :type => :string, :aliases => ["--image"]
7
+ def build_image_job()
8
+ begin
9
+ @cli = Cnvrg::CLI.new
10
+ @cli.verify_logged_in(false)
11
+ @cli.log_start(__method__, args, options)
12
+ @cli.log_message("build image started", Thor::Shell::Color::BLUE)
13
+ image = Image.new(options["image_id"])
14
+ image.build
15
+ @cli.log_message("Image build completed successfully", Thor::Shell::Color::BLUE)
16
+ rescue => e
17
+ @cli.log_message("Image build completed with an error", Thor::Shell::Color::RED)
18
+ @cli.log_error(e)
19
+ exit(1)
20
+ end
21
+ end
22
+
23
+
24
+ end
25
+ end
@@ -1,4 +1,4 @@
1
1
  module Cnvrg
2
- VERSION = '1.5.9.1'
2
+ VERSION = '1.5.9.2'
3
3
  end
4
4
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cnvrg
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.9.1
4
+ version: 1.5.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yochay Ettun
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-10-21 00:00:00.000000000 Z
13
+ date: 2019-10-24 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -418,6 +418,8 @@ files:
418
418
  - lib/cnvrg/helpers.rb
419
419
  - lib/cnvrg/helpers/executer.rb
420
420
  - lib/cnvrg/hyper.rb
421
+ - lib/cnvrg/image.rb
422
+ - lib/cnvrg/image_cli.rb
421
423
  - lib/cnvrg/job_cli.rb
422
424
  - lib/cnvrg/logger.rb
423
425
  - lib/cnvrg/org_helpers.rb