cnvrg 0.0.11 → 0.0.14

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
  SHA1:
3
- metadata.gz: 745fd9b806d9e5d46b4ba24212e06f5a426447f3
4
- data.tar.gz: c950e20258da5c1243765572b6b7f4c93d0cad1a
3
+ metadata.gz: 27f1b54ab10e9cc75d4c290fa0802c11a148275c
4
+ data.tar.gz: 4e80f1fbb3b2d3c4bd5450708359de08212105a3
5
5
  SHA512:
6
- metadata.gz: f60cd3a8cbb4d9bb6c53beac4faf0b76d5db9db469e4474dabe36787985b7d601a07d0029dcb797b7ede238ec2fa3e96beaaa56497b39fc05380dd05f54981fb
7
- data.tar.gz: 6587fe66cf021518dc9249a3c0eb936ccfb126b51b6b6cc605d1e44b09cbee30b55bb590cc7420bec05951077d63f452bb9a88a7466a78bd1281d51ccd334b1f
6
+ metadata.gz: eb9766dc5c54ad8b5d8e4463178dc0cd696e76c214dd1e8d89d67f23369d68e716647ac253484c65f273352196530626b9e1a35f932b4484226f603c12056079
7
+ data.tar.gz: 009acaba20cd093a9ed713ba96025b65f981616a47d22e63ec6474d4d91677afef99f141b976c78727f193f5524b5587569d1bf6c4948bb9a0cab6866767c81c
data/cnvrg.gemspec CHANGED
@@ -35,7 +35,11 @@ Gem::Specification.new do |spec|
35
35
  spec.add_runtime_dependency 'sucker_punch', '~> 2.0'
36
36
  spec.add_runtime_dependency 'urlcrypt', '~> 0.1.1'
37
37
  spec.add_runtime_dependency 'logstash-logger'
38
+ spec.add_runtime_dependency 'launchy'
38
39
  spec.add_runtime_dependency 'docker-api'
40
+ spec.add_runtime_dependency 'rubyzip'
41
+ spec.add_runtime_dependency 'activesupport'
42
+
39
43
 
40
44
  end
41
45
 
data/lib/cnvrg.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  require 'rubygems'
2
- require 'thor'
3
-
4
2
  require 'cnvrg/version'
5
3
  require 'cnvrg/cli'
4
+ require 'thor'
6
5
 
7
6
 
8
7
  module Cnvrg
@@ -0,0 +1,347 @@
1
+ require 'fileutils'
2
+ require 'cnvrg/files'
3
+ require 'docker'
4
+
5
+ module Cnvrg
6
+ class Images
7
+ attr_reader :image_name, :image_tag, :is_docker, :project_slug, :commit_id, :owner, :port, :image_slug
8
+
9
+
10
+ def initialize(working_dir, image_name="")
11
+ begin
12
+ config = YAML.load_file(working_dir+"/.cnvrg/config.yml")
13
+ idx = YAML.load_file(working_dir + "/.cnvrg/idx.yml")
14
+
15
+ @working_dir = working_dir
16
+ @commit_id =idx[:commit]
17
+ @project_title = config[:project_name]
18
+ @project_slug = config[:project_slug]
19
+ @owner = config[:owner]
20
+ @is_docker = config[:docker]
21
+ if image_name.empty?
22
+ @image_name = config[:image_base]
23
+ @image_tag = config[:image_tag]
24
+ @image_slug = find_image()
25
+
26
+ else
27
+
28
+ @image_name = image_name
29
+ if !@image_name.nil? and !@image_name.empty?
30
+ if image_name.include? ":"
31
+ @image_name = image_name[0, image_name.index(":")]
32
+ @image_tag = image_name[image_name.index(":")+1, image_name.size]
33
+ else
34
+ @image_name = image_name
35
+ @image_tag = "lastest"
36
+ end
37
+
38
+ end
39
+ @image_slug = find_image(false)
40
+ update_image_activity(@commit_id, nil)
41
+ config = {project_name: config[:project_name],
42
+ project_slug: config[:project_slug],
43
+ owner: config[:owner],
44
+ docker: true, image_base: @image_name, image_tag: @image_tag, image_slug: image_slug}
45
+ File.open(working_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
46
+ end
47
+
48
+ rescue => e
49
+ puts e
50
+ end
51
+
52
+ end
53
+
54
+ def is_container_exist()
55
+ config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
56
+ if config[:container].nil?
57
+ return false
58
+ end
59
+ return config[:container]
60
+ end
61
+
62
+ def container_port()
63
+ config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
64
+ if config[:container].nil?
65
+ return false
66
+ else
67
+ return config[:port]
68
+ end
69
+ end
70
+
71
+ def self.image_exist(owner, image_name)
72
+
73
+ image_res = Cnvrg::API.request("users/#{owner}/images/" + "find", 'POST', {image_name: image_name})
74
+
75
+ if Cnvrg::CLI.is_response_success(image_res)
76
+ image= image_res["result"]["image"]
77
+ return image
78
+ else
79
+ return false
80
+
81
+ end
82
+ end
83
+
84
+ def create_custom_image(new_image_name)
85
+ new_image_name = @project_slug+"_"+@commit_id unless !new_image_name.empty?
86
+ python_arr = get_installed_packages("python")
87
+ py = python_arr.join(",") unless python_arr.nil? or python_arr.empty?
88
+ system_arr = get_installed_packages("system")
89
+ sys = system_arr.join(",") unless system_arr.nil? or system_arr.empty?
90
+ bash_history = get_bash_history
91
+ response = Cnvrg::API.request("users/#{@owner}/images/#{@image_slug}/custom", 'POST', {image_slug: @image_slug, libraries: py,
92
+ dpkg: sys, new_image_name: new_image_name})
93
+ if Cnvrg::CLI.is_response_success(response) and !response["result"]["slug"].nil?
94
+ container = get_container()
95
+ update_image(new_image_name+":latest", container, response["result"]["slug"])
96
+ end
97
+
98
+ return response
99
+
100
+ end
101
+
102
+ def update_image(image_name, container, image_slug)
103
+ config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
104
+ @image_name = image_name
105
+ if !@image_name.nil? and !@image_name.empty?
106
+ @image_name = image_name[0, image_name.index(":")]
107
+ @image_tag = image_name[image_name.index(":")+1, image_name.size]
108
+ end
109
+ config = {project_name: config[:project_name],
110
+ project_slug: config[:project_slug],
111
+ owner: config[:owner],
112
+ docker: true, image_base: @image_name, image_tag: @image_tag, container: container.id, image_slug: image_slug}
113
+
114
+ File.open(@working_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
115
+ end
116
+
117
+ def get_container(stop=false)
118
+ begin
119
+ container_id=is_container_exist()
120
+
121
+ if !container_id
122
+ return create_container()
123
+ else
124
+ container = Docker::Container.get(container_id)
125
+ status = container.json["State"]["Status"]
126
+
127
+ if status == "running"
128
+ return container
129
+ else
130
+ if stop
131
+ return false
132
+ end
133
+ res = container.start()
134
+ if res.info["State"]["Status"].eql? "exited" and res.info["State"]["Error"].include? "port is already allocated"
135
+ return create_container()
136
+ end
137
+ return container
138
+ end
139
+ end
140
+ rescue => e
141
+ if e.message.include? "No such container"
142
+
143
+ return create_container()
144
+ else
145
+ return false
146
+ end
147
+ end
148
+
149
+ end
150
+
151
+ def create_container(port=7654, is_remote=false)
152
+ begin
153
+ image_settings = {
154
+ 'Image' => "#{@image_name}:#{@image_tag}",
155
+ 'User' => 'ds',
156
+ 'Cmd' => '/home/ds/run_ipython.sh',
157
+ 'ExposedPorts' => {
158
+ '8888/tcp' => {},
159
+ },
160
+ 'HostConfig' => {
161
+ 'Binds' => ["#{@working_dir}:/home/ds/notebooks"],
162
+ 'PortBindings' => {
163
+ '8888/tcp' => [
164
+ {'HostPort' => "#{port}", 'HostIp' => 'localhost'}
165
+ ],
166
+ },
167
+ },
168
+ }
169
+ # if !is_remote
170
+ # image_settings['HostConfig'].merge!({ 'Binds' => ["#{@working_dir}:/home/ds/notebooks"]})
171
+ # end
172
+ container = Docker::Container.create(image_settings)
173
+ container.start()
174
+ netrc = File.open(File.expand_path('~')+"/.netrc", "rb")
175
+ netrc_content = netrc.read
176
+ container.store_file("/home/ds/.netrc", netrc_content)
177
+ command = ["/bin/bash", "-lc", "sudo chmod 600 /home/ds/.netrc"]
178
+ p = container.exec(command, tty: true)
179
+ command = ["/bin/bash", "-lc", "sudo chown -R ds /home/ds/.netrc"]
180
+ p = container.exec(command, tty: true)
181
+ command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg"]
182
+ container.exec(command, tty: true)
183
+ command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg/tmp"]
184
+ container.exec(command, tty: true)
185
+ config = File.open(File.expand_path('~')+"/.cnvrg/config.yml", "rb")
186
+ config_content = config.read
187
+ container.store_file("/home/ds/.cnvrg/config.yml", config_content)
188
+ command = ["/bin/bash", "-lc", "sudo chown -R ds /home/ds/.cnvrg"]
189
+ container.exec(command, tty: true)
190
+ # Libraries instlled
191
+ save_installed_libraries(container)
192
+ config = {project_name: @project_name,
193
+ project_slug: @project_slug,
194
+ owner: @owner,
195
+ docker: true, image_base: @image_name, image_tag: @image_tag, container: container.id, port: port, image_slug: @image_slug}
196
+
197
+ File.open(@working_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
198
+
199
+
200
+ return container
201
+
202
+
203
+ rescue => e
204
+ if e.message.include? "is not running"
205
+ return create_container(port-1)
206
+ end
207
+ puts e
208
+ return false
209
+ rescue SignalException
210
+
211
+ say "\nAborting", Thor::Shell::Color::RED
212
+ exit(1)
213
+ end
214
+
215
+
216
+ end
217
+
218
+ def save_installed_libraries(container)
219
+ begin
220
+ command = ['/bin/bash', '-lc', '/opt/ds/bin/pip freeze']
221
+ pip = container.exec(command, tty: true)[0]
222
+ command = ["/bin/bash", "-lc", "dpkg -l | grep '^ii' | awk '{print $2\"==\"$3}'"]
223
+ dpkg = container.exec(command, tty: true)[0]
224
+ File.open(@working_dir+"/.cnvrg/pip_base.txt", "w+") { |f| f.write pip }
225
+ File.open(@working_dir+"/.cnvrg/dpkg_base.txt", "w+") { |f| f.write dpkg }
226
+ rescue => e
227
+ puts e
228
+ end
229
+
230
+
231
+ end
232
+
233
+ def remote_notebook(notebook_path, instance_type, kernel)
234
+ response = Cnvrg::API.request("users/#{@owner}/images/#{@image_slug}/remote_notebook", 'POST', {dir: notebook_path,
235
+ project_slug: @project_slug,
236
+ instance_type: instance_type,
237
+ kernel: kernel})
238
+ return response
239
+ end
240
+
241
+ def get_installed_packages(repo)
242
+ container = get_container()
243
+ case repo
244
+ when "python"
245
+ command = ['/bin/bash', '-lc', '/opt/ds/bin/pip freeze']
246
+ when "system"
247
+ command = ["/bin/bash", "-lc", "dpkg -l | grep '^ii' | awk '{print $2\"==\"$3}'"]
248
+ end
249
+
250
+ libs = container.exec(command, tty: true)[0]
251
+ libs_arr = libs.join("").split("\r\n")
252
+ return libs_arr
253
+
254
+ end
255
+
256
+ def get_bash_history
257
+ container = get_container()
258
+ command = ["/bin/bash", "-lc", "cat /home/ds/.bash_history"]
259
+ history = container.exec(command, tty: true)[0][0]
260
+ if history.include? "No such file"
261
+ history = ""
262
+ end
263
+ return history
264
+ end
265
+
266
+
267
+ def get_image_state
268
+ python_arr = self.get_installed_packages("python")
269
+ py = python_arr.join(",") unless python_arr.nil? or python_arr.empty?
270
+ system_arr = self.get_installed_packages("system")
271
+ sys = system_arr.join(",") unless system_arr.nil? or system_arr.empty?
272
+ bash_history = self.get_bash_history
273
+ diff = [py, sys, bash_history]
274
+
275
+ end
276
+
277
+ def find_image(update=true)
278
+ config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
279
+ image_slug = config[:image_slug]
280
+ if image_slug.nil? or image_slug.empty?
281
+ image_res = Cnvrg::API.request("users/#{@owner}/images/" + "find", 'POST', {image_name: @image_name})
282
+
283
+ if Cnvrg::CLI.is_response_success(image_res)
284
+ image_slug = image_res["result"]["image"]["slug"]
285
+ update_slug(image_slug) unless !update
286
+ return image_slug
287
+ end
288
+ else
289
+ return image_slug
290
+
291
+ end
292
+ end
293
+
294
+ def set_note_url(note_slug)
295
+ config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
296
+ config[:notebook_slug] = note_slug
297
+ File.open(@working_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
298
+ end
299
+ def note_slug
300
+ config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
301
+ note_slug = config[:notebook_slug]
302
+ if note_slug.nil? or note_slug.empty?
303
+ return false
304
+ else
305
+ return note_slug
306
+ end
307
+ end
308
+ def remove_note_slug
309
+ config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
310
+ config[:notebook_slug] = ""
311
+ File.open(@working_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
312
+
313
+ end
314
+
315
+
316
+ def update_slug(slug)
317
+ config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
318
+ config[:image_slug] = slug
319
+ File.open(@working_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
320
+ end
321
+
322
+ def new_machine(instance_type)
323
+ title = "#{instance_type} auto created by cli"
324
+ response = Cnvrg::API.request("users/#{@owner}/machines/new", 'POST', {machine_name: title, instance_type: instance_type})
325
+ return Cnvrg::CLI.is_response_success(response)
326
+
327
+ end
328
+
329
+ def update_image_activity(commit, exp_slug)
330
+ response = Cnvrg::API.request("users/#{@owner}/images/#{@image_slug}/update_activity", 'POST', {commit: commit, project_slug: @project_slug, experiment: exp_slug})
331
+ return Cnvrg::CLI.is_response_success(response)
332
+ end
333
+
334
+ def handle_image_activity
335
+ home_dir = File.expand_path('~')
336
+ zip_dir = "#{home_dir}/.cnvrg/tmp/config.zip"
337
+ compress = `zip -j #{zip_dir} #{home_dir}/.netrc #{home_dir}/.cnvrg/config.yml`
338
+ @files = Cnvrg::Files.new(@owner, @project_slug)
339
+ res_id = @files.upload_exec_file(zip_dir, @image_name, @commit_id)
340
+ FileUtils.remove zip_dir
341
+ return res_id
342
+ end
343
+
344
+
345
+ end
346
+
347
+ end
data/lib/cnvrg/api.rb CHANGED
@@ -80,10 +80,12 @@ module Cnvrg
80
80
  # what if windows?
81
81
  # data[:file] = Faraday::UploadIO.new(data[:absolute_path], content_type)
82
82
  file_base = File.basename(data[:relative_path])
83
- temp_path = File.expand_path('~')+"/.cnvrg/tmp/#{file_base}"
83
+ temp_path = File.expand_path('~')+"/.cnvrg/tmp_files/#{file_base}"
84
84
  FileUtils.touch(temp_path)
85
85
  data[:file] = Faraday::UploadIO.new("#{temp_path}", "plain/text")
86
+
86
87
  response = conn.post "#{endpoint_uri}/#{resource}", data
88
+
87
89
  FileUtils.rm(temp_path)
88
90
 
89
91
  if parse_request == true
@@ -101,7 +103,8 @@ module Cnvrg
101
103
  end
102
104
  else
103
105
  end
104
- rescue
106
+ rescue => e
107
+ puts e
105
108
  return nil
106
109
  end
107
110
 
data/lib/cnvrg/cli.rb CHANGED
@@ -17,10 +17,18 @@ require 'cnvrg/auth'
17
17
  require 'cnvrg/project'
18
18
  require 'cnvrg/files'
19
19
  require 'cnvrg/experiment'
20
+ require 'cnvrg/Images'
20
21
  require 'etc'
21
22
  require 'logstash-logger'
22
23
  require 'cnvrg/job'
23
24
  require 'docker'
25
+ require 'launchy'
26
+ require 'socket'
27
+ require 'timeout'
28
+ require 'fileutils'
29
+ require 'zip'
30
+ require 'active_support/all'
31
+ require 'thor'
24
32
 
25
33
  # DEV VERSION
26
34
  #
@@ -28,23 +36,62 @@ module Cnvrg
28
36
  class CLI < Thor
29
37
 
30
38
  INSTALLATION_URLS = {docker: "https://docs.docker.com/engine/installation/", jupyter: "http://jupyter.readthedocs.io/en/latest/install.html"}
31
- desc 'test', 'Prints cnvrg current version'
39
+ IP="localhost"
40
+ PORT=7654
41
+ desc '', ''
42
+
43
+ def printable_commands(all = true, subcommand = false)
44
+ (all ? all_commands : commands).map do |_, command|
45
+ next if command.hidden? or (command.description.empty? and command.usage.empty?)
46
+ item = []
47
+ item << banner(command, false, subcommand)
48
+ item << (command.description ? "# #{command.description.gsub(/\s+/m, ' ')}" : "")
49
+ item
50
+ end.compact
51
+ end
52
+
53
+ class << self
54
+ # Hackery.Take the run method away from Thor so that we can redefine it.
55
+ def is_thor_reserved_word?(word, type)
56
+ return false if word == "run"
57
+ super
58
+ end
59
+ end
60
+
61
+ desc "", ""
62
+ method_option :schedule, :type => :string, :aliases => ["--s", "-s"], :default => "leahs"
32
63
 
33
64
  def test
34
- verify_software_installed("docker")
35
- container = Docker::Container.create( 'Image' => 'cnvrgio/python2')
36
- # container = Docker::Container.create("1e4e23560813")
37
- container.start
38
- puts container.exec(['bash'], stdin: StringIO.new("python --version"))
65
+ # image_settings = {
66
+ # 'Image' => "cnvrg:latest",
67
+ # 'User' => 'ds',
68
+ # 'Cmd' => '/home/ds/run_ipython.sh',
69
+ # 'ExposedPorts' => {
70
+ # '80/tcp' => {},
71
+ # },
72
+ # 'HostConfig' => {
73
+ # 'PortBindings' => {
74
+ # '80/tcp' => [
75
+ # {'HostPort' => "7654", 'HostIp' => 'localhost'}
76
+ # ],
77
+ # },
78
+ # },
79
+ # }
80
+ container = Docker::Container.get('b4d64bf83f41')
81
+ s = "/leah/1/2/3/4/5"
82
+ command = ["/bin/bash","-lc","sed -i 's#c.NotebookApp.base_url = .*#c.NotebookApp.base_url = \"#{s}\"#' /home/ds/.jupyter/jupyter_notebook_config.py"]
83
+ puts container.exec(command, tty: true)
39
84
 
40
85
  end
41
86
 
87
+
42
88
  desc 'version', 'Prints cnvrg current version'
43
89
 
44
90
  def version
45
91
  puts Cnvrg::VERSION
46
92
 
47
93
  end
94
+
48
95
  map %w(-v --version) => :version
49
96
 
50
97
  desc 'set api url', 'set api url'
@@ -62,22 +109,56 @@ module Cnvrg
62
109
  FileUtils.touch [home_dir+"/.cnvrg/config.yml"]
63
110
  end
64
111
  config = YAML.load_file(home_dir+"/.cnvrg/config.yml")
112
+ owner = config.to_h[:owner]
113
+
65
114
  say "Setting default api to be: #{url}", Thor::Shell::Color::BLUE
66
115
  if config.empty?
67
116
  config = {owner: "", username: "", version_last_check: get_start_day(), api: url}
68
117
  else
69
118
  config = {owner: config.to_h[:owner], username: config.to_h[:username], version_last_check: config.to_h[:version_last_check], api: url}
70
119
  end
71
- checks = Helpers.checkmark
120
+ res = Cnvrg::API.request("/users/#{owner}/custom_api", 'POST', {custom_api: url})
121
+ if Cnvrg::CLI.is_response_success(res)
72
122
 
123
+ checks = Helpers.checkmark
124
+
125
+
126
+ File.open(home_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
127
+ say "#{checks} Done", Thor::Shell::Color::GREEN
128
+ else
129
+ say "Couldn't set default api, contact help@cnvrg.io", Thor::Shell::Color::RED
130
+ exit(1)
131
+
132
+ end
73
133
 
74
- File.open(home_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
75
- say "#{checks} Done", Thor::Shell::Color::GREEN
76
134
  rescue
77
135
  say "Couldn't set default api, contact help@cnvrg.io", Thor::Shell::Color::RED
78
136
  end
79
137
  end
80
138
 
139
+ desc '', ''
140
+
141
+ def set_remote_api_url(owner, current_user, url)
142
+ home_dir = File.expand_path('~')
143
+ if !url.end_with? "/api"
144
+ url = url+"/api"
145
+ end
146
+ begin
147
+ if !File.directory? home_dir+"/.cnvrg"
148
+ FileUtils.mkdir_p([home_dir+"/.cnvrg", home_dir+"/.cnvrg/tmp"])
149
+ end
150
+ if !File.exist?(home_dir+"/.cnvrg/config.yml")
151
+ FileUtils.touch [home_dir+"/.cnvrg/config.yml"]
152
+ end
153
+ config = YAML.load_file(home_dir+"/.cnvrg/config.yml")
154
+ config = {owner: owner, username: current_user, version_last_check: get_start_day(), api: url}
155
+ File.open(home_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
156
+ say "Done"
157
+ rescue
158
+ say "ERROR", Thor::Shell::Color::RED
159
+ end
160
+ end
161
+
81
162
  map %w(-api --api) => :set_api_url
82
163
 
83
164
  desc 'set default owner', 'set default owner'
@@ -97,11 +178,29 @@ module Cnvrg
97
178
  if Cnvrg::CLI.is_response_success(res)
98
179
  owner = username
99
180
  result = res["result"]
100
- if result["owners"].size > 1
101
- owner = ask("Choose default owner:\n"+result["owners"].join("\n")+"\n")
181
+ owners = result["owners"]
182
+ urls = result["urls"]
183
+ choose_owner = result["username"]
184
+
185
+ if owners.empty?
186
+ else
187
+ owners << choose_owner
188
+ chosen = false
189
+ while !chosen
190
+ choose_owner = ask("Choose default owner:\n"+owners.join("\n")+"\n")
191
+
192
+ owners_lower = owners.map { |o| o.downcase }
193
+ ow_index = owners_lower.index(choose_owner.downcase)
194
+ if ow_index.nil?
195
+ say "Could not find owner named #{choose_owner}", Thor::Shell::Color::RED
196
+ else
197
+ chosen = true
198
+ end
199
+ end
200
+
102
201
 
103
202
  end
104
- if set_owner(owner, username)
203
+ if set_owner(owner, username,urls[ow_index])
105
204
  say "Setting default owner: #{owner}", Thor::Shell::Color::GREEN
106
205
  else
107
206
  say "Setting default owenr has failed, try to run cnvrg --config-default-owner", Thor::Shell::Color::RED
@@ -138,6 +237,7 @@ module Cnvrg
138
237
 
139
238
  say "Authenticated successfully as #{@email}", Thor::Shell::Color::GREEN
140
239
  owners = result["owners"]
240
+ urls = result["urls"]
141
241
  choose_owner = result["username"]
142
242
 
143
243
  if owners.empty?
@@ -145,18 +245,21 @@ module Cnvrg
145
245
  owners << choose_owner
146
246
  chosen = false
147
247
  while !chosen
148
- choose_owner = ask("Choose default owner:\n"+owners.join("\n")+"\n")
149
- owners_lower = owners.map{|o| o.downcase}
150
- if !owners_lower.include? choose_owner.downcase
151
- say "Could not find owner named #{choose_owner}", Thor::Shell::Color::RED
152
- else
153
- chosen = true
154
- end
248
+ choose_owner = ask("Choose default owner:\n"+owners.join("\n")+"\n")
249
+
250
+ owners_lower = owners.map { |o| o.downcase }
251
+ ow_index = owners_lower.index(choose_owner.downcase)
252
+ if ow_index.nil?
253
+ say "Could not find owner named #{choose_owner}", Thor::Shell::Color::RED
254
+ else
255
+ chosen = true
256
+ end
155
257
  end
156
258
 
157
259
 
158
260
  end
159
- if set_owner(choose_owner, result["username"])
261
+
262
+ if set_owner(choose_owner, result["username"], urls[ow_index])
160
263
  say "Setting default owner: #{choose_owner}", Thor::Shell::Color::GREEN
161
264
 
162
265
  else
@@ -172,7 +275,7 @@ module Cnvrg
172
275
  end
173
276
  rescue SignalException
174
277
 
175
- say "/nAborting"
278
+ say "\nAborting"
176
279
  logout()
177
280
  exit(1)
178
281
  end
@@ -188,7 +291,7 @@ module Cnvrg
188
291
  netrc.save
189
292
  say "Logged out successfully.\n", Thor::Shell::Color::GREEN
190
293
  rescue SignalException
191
- say "/nAborting"
294
+ say "\nAborting"
192
295
  exit(1)
193
296
  end
194
297
 
@@ -201,7 +304,7 @@ module Cnvrg
201
304
  begin
202
305
 
203
306
  verify_logged_in(false)
204
- log_start(__method__,args,options)
307
+ log_start(__method__, args, options)
205
308
  auth = Cnvrg::Auth.new
206
309
  if (email = auth.get_email)
207
310
  say "Logged in as: #{email}", Thor::Shell::Color::GREEN
@@ -213,13 +316,12 @@ module Cnvrg
213
316
  rescue SignalException
214
317
  log_end(-1)
215
318
 
216
- say "/nAborting"
319
+ say "\nAborting"
217
320
  exit(1)
218
321
  end
219
322
  end
220
323
 
221
324
  ## Projects
222
-
223
325
  desc 'new', 'Create a new cnvrg project'
224
326
  method_option :clean, :type => :boolean, :aliases => ["-c", "--c"], :default => false
225
327
  method_option :docker_image, :type => :string, :aliases => ["-d", "--d"], :default => ""
@@ -227,142 +329,296 @@ module Cnvrg
227
329
  def new(project_name)
228
330
  begin
229
331
  verify_logged_in(false)
230
- log_start(__method__,args,options)
332
+ log_start(__method__, args, options)
231
333
  clean = options["clean"]
232
334
  docker_image = options["docker_image"]
335
+ working_dir = Dir.pwd + "/" + project_name
336
+ docker = false
233
337
  if !docker_image.nil? and !docker_image.empty?
234
- # local_images = Docker::Image.all
235
- # docker_image_local = local_images.map{|x| x.info["RepoTags"]}.select{|y| y[0].include? docker_image}.flatten
236
- # if docker_image_local.size == 0
237
- # if yes? "Image wasn't found locally, pull image from cnvrg repository?"
238
- # image = pull_image(docker_image)
239
- # if image
240
- # say "downloaded image: #{docker_image_local[0]}, creating a container.."
241
- # @container = Docker::Container.create('Image' => '#{docker_image_local[0]}')
242
- # if @container.nil?
243
- # say "could not create container with image #{docker_image_local[0]}"
244
- # end
245
- # end
246
- # else
247
- # say "Could not create a new project with docker, image was not found", Thor::Shell::Color::RED
248
- # exit(1)
249
- #
250
- # end
251
- # elsif docker_image_local.size == 1
252
- # say "found image: #{docker_image_local[0]}, creating a container.."
253
- # @container = Docker::Container.create('Image' => '#{docker_image_local[0]}')
254
- # if @container.nil?
255
- # say "could not create container with image #{docker_image_local[0]}"
256
- # end
257
- #
258
- # end
338
+ docker = true
259
339
  end
260
340
  say "Creating #{project_name}", Thor::Shell::Color::BLUE
261
341
  if Dir.exists? project_name or File.exists? project_name
262
342
  say "Conflict with dir/file #{project_name}", Thor::Shell::Color::RED
263
- log_end(1,"conflict with dir/file #{project_name}")
343
+ log_end(1, "conflict with dir/file #{project_name}")
264
344
  exit(1)
265
- end
266
345
 
267
- if Project.create(project_name, clean)
346
+ end
347
+ if Project.create(project_name, clean, with_docker=docker)
268
348
  path = Dir.pwd + "/" + project_name
269
349
  @project = Project.new(path)
270
350
  @project.generate_idx
351
+ if docker
352
+ local_images = Docker::Image.all
353
+ docker_image_local = local_images.map { |x| x.info["RepoTags"] }.flatten.select { |y| y.include? docker_image }.flatten
354
+ if docker_image_local.size == 0
355
+
356
+ if yes? "Image wasn't found locally, pull image from cnvrg repository?", Thor::Shell::Color::YELLOW
357
+ image = pull_image(docker_image)
358
+ if image
359
+ say "downloaded image: #{docker_image}"
360
+ @image = Images.new(working_dir, docker_image)
361
+ else
362
+ say "Could not create a new project with docker, image was not found", Thor::Shell::Color::RED
363
+ @project.revert(working_dir)
364
+ exit(1)
365
+ end
366
+ else
367
+ say "Could not create a new project with docker, image was not found", Thor::Shell::Color::RED
368
+ @project.revert(working_dir)
369
+ exit(1)
370
+
371
+ end
372
+ elsif docker_image_local.size == 1
373
+ say "found image: #{docker_image_local[0]}, setting it up..", Thor::Shell::Color::BLUE
374
+ @image = Images.new(working_dir, docker_image_local[0])
375
+ elsif docker_image_local.size >1
376
+ say "found #{docker_image_local.size} images, choose the image name you want to use", Thor::Shell::Color::BLUE
377
+ image_name = ask "#{docker_image_local.join("\n")}\n", Thor::Shell::Color::BLUE
378
+ image_name = image_name.strip
379
+ @image = Images.new(working_dir, image_name)
380
+ end
381
+ @image.update_image_activity(nil, nil)
382
+
383
+ end
271
384
  else
272
385
  say "Error creating project, please contact support.", Thor::Shell::Color::RED
273
- log_end(1,"can't create project #{project_name}")
386
+ @project.revert(working_dir)
387
+ log_end(1, "can't create project #{project_name}")
274
388
 
275
389
  exit(0)
276
390
  end
277
391
 
278
- say "created\t\tproject's tree", Thor::Shell::Color::GREEN
279
- say "created\t\tproject's config", Thor::Shell::Color::GREEN
392
+ say "created project successfully", Thor::Shell::Color::GREEN
280
393
  say "Linked directory to\t#{@project.url}", Thor::Shell::Color::GREEN
394
+ rescue => e
395
+ puts e
396
+ log_end(-1)
397
+ if Dir.exist? working_dir
398
+
399
+ @project.revert(working_dir)
400
+ end
401
+
402
+ exit(1)
281
403
 
282
404
  rescue SignalException
283
405
  log_end(-1)
406
+ if Dir.exist? working_dir
284
407
 
285
- say "/nAborting"
408
+ @project.revert(working_dir)
409
+ end
410
+ say "\nAborting"
286
411
  exit(1)
287
412
  end
288
413
  end
414
+ desc 'set_image', 'set_image for a project'
415
+
416
+ def set_image(docker_image)
417
+ verify_logged_in(false)
418
+ log_start(__method__, args, options)
419
+ working_dir = is_cnvrg_dir
420
+ local_images = Docker::Image.all
421
+ docker_image_local = local_images.map { |x| x.info["RepoTags"] }.flatten.select { |y| y.include? docker_image }.flatten
422
+ if docker_image_local.size == 0
423
+
424
+ if yes? "Image wasn't found locally, pull image from cnvrg repository?", Thor::Shell::Color::YELLOW
425
+ image = pull_image(docker_image)
426
+ if image
427
+ say "downloaded image: #{docker_image}"
428
+ @image = Images.new(working_dir, docker_image)
429
+ else
430
+ say "Could not set image, image was not found", Thor::Shell::Color::RED
431
+ exit(1)
432
+ end
433
+ else
434
+ say "Could nset image, image was not found", Thor::Shell::Color::RED
435
+ exit(1)
289
436
 
437
+ end
438
+ elsif docker_image_local.size == 1
439
+ say "found image: #{docker_image_local[0]}, setting it up..", Thor::Shell::Color::BLUE
440
+ @image = Images.new(working_dir, docker_image_local[0])
441
+ elsif docker_image_local.size >1
442
+ say "found #{docker_image_local.size} images, choose the image name you want to use", Thor::Shell::Color::BLUE
443
+ image_name = ask "#{docker_image_local.join("\n")}\n", Thor::Shell::Color::BLUE
444
+ image_name = image_name.strip
445
+ @image = Images.new(working_dir, image_name)
446
+ end
447
+ @image.update_image_activity(nil, nil)
290
448
 
449
+ end
450
+ desc 'link', 'Link current directory to a cnvrg project'
451
+ method_option :sync, :type => :boolean, :aliases => ["-s", "--s"], :default => true
452
+ method_option :docker_image, :type => :string, :aliases => ["-d", "--d"], :default => ""
291
453
 
292
- desc 'link', 'Link current directory to a cnvrg project'
293
- method_option :sync, :type => :boolean, :aliases => ["-s", "--s"], :default => true
454
+ def link
455
+ begin
456
+ verify_logged_in(false)
457
+ log_start(__method__, args, options)
458
+ docker_image = options["docker_image"]
459
+ if !docker_image.nil? and !docker_image.empty?
460
+ docker = true
461
+ else
462
+ docker = false
463
+ end
294
464
 
295
- def link
296
- begin
297
- verify_logged_in(false)
298
- log_start(__method__,args,options)
465
+ sync = options["sync"]
466
+ project_name =File.basename(Dir.getwd)
467
+ say "Linking #{project_name}", Thor::Shell::Color::BLUE
468
+ if File.directory?(Dir.getwd+"/.cnvrg")
469
+ config = YAML.load_file("#{Dir.getwd}/.cnvrg/config.yml")
470
+ say "Directory is already linked to #{config[:project_slug]}", Thor::Shell::Color::RED
299
471
 
300
- sync = options["sync"]
301
- project_name =File.basename(Dir.getwd)
302
- say "Linking #{project_name}", Thor::Shell::Color::BLUE
303
- if File.directory?(Dir.getwd+"/.cnvrg")
304
- config = YAML.load_file("#{Dir.getwd}/.cnvrg/config.yml")
305
- say "Directory is already linked to #{config[:project_slug]}", Thor::Shell::Color::RED
472
+ exit(0)
473
+ end
474
+ working_dir = Dir.getwd
475
+ owner = CLI.get_owner
476
+ if Project.link(owner,project_name, docker)
477
+ path = Dir.pwd
478
+ @project = Project.new(path)
479
+ @project.generate_idx()
480
+ if docker
481
+ local_images = Docker::Image.all
482
+ docker_image_local = local_images.map { |x| x.info["RepoTags"] }.flatten.select { |y| y.include? docker_image }.flatten
483
+ if docker_image_local.size == 0
484
+ if yes? "Image wasn't found locally, pull image from cnvrg repository?", Thor::Shell::Color::YELLOW
485
+ image = pull_image(docker_image)
486
+ if image
487
+ say "downloaded image: #{docker_image}"
488
+ @image = Images.new(working_dir, docker_image)
489
+ else
490
+ say "Could not create a new project with docker, image was not found", Thor::Shell::Color::RED
491
+ @project.revert(working_dir)
492
+ exit(1)
493
+ end
494
+ else
495
+ say "Could not create a new project with docker, image was not found", Thor::Shell::Color::RED
496
+ @project.revert(working_dir)
497
+ exit(1)
306
498
 
307
- exit(0)
308
- end
309
- if Project.link(project_name)
310
- path = Dir.pwd
311
- @project = Project.new(path)
312
- @project.generate_idx()
313
- if sync
314
- upload(true)
499
+ end
500
+ elsif docker_image_local.size == 1
501
+ say "found image: #{docker_image_local[0]}, setting it up..", Thor::Shell::Color::BLUE
502
+ @image = Images.new(working_dir, docker_image_local[0])
503
+ elsif docker_image_local.size >1
504
+ say "found #{docker_image_local.size} images, choose the image name you want to use", Thor::Shell::Color::BLUE
505
+ image_name = ask "#{docker_image_local.join("\n")}\n", Thor::Shell::Color::BLUE
506
+ @image = Images.new(working_dir, image_name)
315
507
  end
508
+ end
509
+ if sync
510
+ say "Syncing project", Thor::Shell::Color::BLUE
511
+ upload(true)
512
+ end
316
513
 
317
- url = @project.url
318
- say "#{project_name}'s location is: #{url}\n", Thor::Shell::Color::BLUE
319
- log_end(0)
514
+ url = @project.url
515
+ check = Helpers.checkmark
516
+ say "#{check} Link finished successfully", Thor::Shell::Color::GREEN
517
+ say "#{project_name}'s location is: #{url}\n", Thor::Shell::Color::GREEN
518
+ log_end(0)
519
+
520
+ else
521
+ log_end(1, "can't link project")
522
+ @project.revert(working_dir) unless @project.nil?
523
+ say "Error linking project, please contact support.", Thor::Shell::Color::RED
524
+ exit(0)
525
+ end
526
+ rescue SignalException
527
+ log_end(-1)
528
+
529
+ say "\nAborting"
530
+ exit(1)
531
+ end
532
+ end
533
+ desc 'unlink','Unlink a porject'
534
+ def unlink
535
+ verify_logged_in(false)
536
+ log_start(__method__, args, options)
537
+ working_dir = is_cnvrg_dir()
538
+ list_to_del = [working_dir+"/.cnvrgignore",working_dir+"/.cnvrg"]
539
+ FileUtils.rm_rf list_to_del
540
+ end
541
+
542
+ desc 'clone', 'Clone a project'
543
+ method_option :remote, :type => :boolean, :aliases => ["-r", "--r"], :default => false
544
+ method_option :commit, :type => :string, :aliases => ["-c", "--c"], :default => nil
545
+
546
+ def clone(project_url)
547
+ begin
548
+ verify_logged_in(false)
549
+ log_start(__method__, args, options)
550
+ url_parts = project_url.split("/")
551
+ project_index = Cnvrg::Helpers.look_for_in_path(project_url, "projects")
552
+ slug = url_parts[project_index+1]
553
+ owner = url_parts[project_index-1]
554
+ remote = options["remote"] || false
555
+ response = Cnvrg::API.request("users/#{owner}/projects/#{slug}/get_project", 'GET')
556
+ Cnvrg::CLI.is_response_success(response)
557
+ response = JSON.parse response["result"]
558
+ project_name = response["title"]
559
+ commit_to_clone = options["commit"] || nil
560
+
561
+ say "Cloning #{project_name}", Thor::Shell::Color::BLUE
562
+ clone_resp = false
563
+ if remote
564
+ clone_resp = Project.clone_dir_remote(slug, owner, project_name)
565
+ project_home = Dir.pwd
566
+ else
567
+ if (Dir.exists? project_name)
568
+ say "Error: Conflict with dir #{project_name}", Thor::Shell::Color::RED
569
+ if no? "Sync to repository anyway? (current data might lost)", Thor::Shell::Color::YELLOW
570
+ say "Remove dir in order to clone #{project_name}", Thor::Shell::Color::RED
571
+ log_end(1, "conflict with dir #{project_name}")
572
+
573
+ exit(1)
574
+ end
320
575
 
321
- else
322
- log_end(1,"can't link project")
323
- say "Error linking project, please contact support.", Thor::Shell::Color::RED
324
- exit(0)
325
576
  end
326
- rescue SignalException
327
- log_end(-1)
577
+ clone_resp = Project.clone_dir(slug, owner, project_name)
578
+ project_home = Dir.pwd+"/"+project_name
579
+
328
580
 
329
- say "/nAborting"
330
- exit(1)
331
581
  end
332
- end
333
582
 
334
- desc 'clone', 'Clone a project'
583
+ if clone_resp
584
+ @project = Project.new(project_home)
585
+ @files = Cnvrg::Files.new(@project.owner, slug)
586
+ response = @project.clone(remote, commit_to_clone)
587
+ Cnvrg::CLI.is_response_success response
588
+ working_dir = project_home
589
+ docker_image = response["result"]["image"]
590
+ idx = {commit: response["result"]["commit"], tree: response["result"]["tree"]}
591
+ File.open(working_dir + "/.cnvrg/idx.yml", "w+") { |f| f.write idx.to_yaml }
592
+ if !docker_image.nil? and !docker_image.empty? and !remote
593
+ local_images = Docker::Image.all
594
+ docker_image_local = local_images.map { |x| x.info["RepoTags"] }.flatten.select { |y| y.eql? "#{docker_image}:latest" }.flatten
595
+ if docker_image_local.size == 0
596
+ if yes? "Image wasn't found locally, pull image from cnvrg repository?", Thor::Shell::Color::YELLOW
597
+ image = pull_image(docker_image)
598
+ if image
599
+ say "downloaded image: #{docker_image}"
600
+ @image = Images.new(working_dir, docker_image)
601
+ else
602
+ say "Could not create a new project with docker, image was not found", Thor::Shell::Color::RED
603
+ @project.revert(working_dir)
604
+ exit(1)
605
+ end
606
+ end
607
+
608
+ elsif docker_image_local.size == 1
609
+ say "found image: #{docker_image_local[0]}, setting it up..", Thor::Shell::Color::BLUE
610
+ @image = Images.new(working_dir, docker_image_local[0])
611
+ elsif docker_image_local.size >1
612
+ say "found #{docker_image_local.size} images, choose the image name you want to use", Thor::Shell::Color::BLUE
613
+ image_name = ask "#{docker_image_local.join("\n")}\n", Thor::Shell::Color::BLUE
614
+ @image = Images.new(working_dir, image_name)
615
+ end
335
616
 
336
- def clone(project_url)
337
- begin
338
- verify_logged_in(false)
339
- log_start(__method__,args,options)
340
- url_parts = project_url.split("/")
341
- project_index = Cnvrg::Helpers.look_for_in_path(project_url, "projects")
342
- slug = url_parts[project_index+1]
343
- owner = url_parts[project_index-1]
344
- response = Cnvrg::API.request("users/#{owner}/projects/#{slug}/get_project", 'GET')
345
- Cnvrg::CLI.is_response_success(response)
346
- response = JSON.parse response["result"]
347
- project_name = response["title"]
348
- say "Cloning #{project_name}", Thor::Shell::Color::BLUE
349
- if Dir.exists? project_name or File.exists? project_name
350
- log_end(1,"conflict with dir/file #{project_name}")
351
-
352
- say "Error: Conflict with dir/file #{project_name}", Thor::Shell::Color::RED
353
- exit(1)
354
617
  end
355
618
 
356
- if Project.clone_dir(slug, owner, project_name)
357
- project_home = Dir.pwd+"/"+project_name
358
- @project = Project.new(project_home)
359
- @files = Cnvrg::Files.new(@project.owner, slug)
360
- response = @project.clone
361
- Cnvrg::CLI.is_response_success response
362
- idx = {commit: response["result"]["commit"], tree: response["result"]["tree"]}
363
- File.open(project_name + "/.cnvrg/idx.yml", "w+") { |f| f.write idx.to_yaml }
364
- successful_changes = []
365
- say "Downloading files", Thor::Shell::Color::BLUE
619
+ successful_changes = []
620
+ say "Downloading files", Thor::Shell::Color::BLUE
621
+ if !response["result"]["tree"].nil?
366
622
  response["result"]["tree"].each do |f|
367
623
  relative_path = f[0].gsub(/^#{@project.local_path}/, "")
368
624
  if f[0].end_with? "/"
@@ -372,202 +628,226 @@ module Cnvrg
372
628
  end
373
629
  else
374
630
  # blob
375
- if @files.download_file(f[0], relative_path, project_home)
631
+ if @files.download_file_s3(f[0], relative_path, project_home)
376
632
  successful_changes << relative_path
377
633
  end
378
634
  end
379
635
  end
380
- say "Done.\nDownloaded total of #{successful_changes.size} files", Thor::Shell::Color::GREEN
381
- log_end(0)
382
- else
383
- log_end(1,"can't create directory")
384
-
385
- say "Error: Couldn't create directory: #{project_name}", Thor::Shell::Color::RED
386
- exit(1)
387
636
  end
388
- rescue SignalException
389
- log_end(-1)
390
- say "/nAborting"
637
+
638
+ say "Done.\nDownloaded total of #{successful_changes.size} files", Thor::Shell::Color::GREEN
639
+ log_end(0)
640
+ else
641
+ log_end(1, "can't create directory")
642
+
643
+ say "Error: Couldn't create directory: #{project_name}", Thor::Shell::Color::RED
391
644
  exit(1)
392
645
  end
393
-
646
+ rescue SignalException
647
+ log_end(-1)
648
+ say "\nAborting"
649
+ exit(1)
394
650
  end
395
651
 
396
- desc 'status', 'Show the working tree status'
397
- def status
398
- begin
399
- verify_logged_in()
400
- log_start(__method__,args,options)
401
- @project = Project.new(get_project_home)
402
- result = @project.compare_idx["result"]
403
- commit = result["commit"]
404
- result = result["tree"]
405
- say "Comparing local changes with remote version:", Thor::Shell::Color::BLUE
406
- if result["added"].empty? and result["updated_on_local"].empty? and result["updated_on_server"].empty? and result["deleted"].empty? and result["conflicts"].empty?
407
- say "Project is up to date", Thor::Shell::Color::GREEN
408
- log_end(0)
409
- return true
410
- end
411
- if result["added"].size > 0
412
- say "Added files:\n", Thor::Shell::Color::BLUE
413
- result["added"].each do |a|
414
- say "\t\tA:\t#{a}", Thor::Shell::Color::GREEN
415
- end
652
+ end
653
+
654
+
655
+ desc 'status', 'Show the working tree status'
656
+ method_option :new_branch, :type => :boolean, :aliases => ["-nb", "--nb"], :desc => "create new branch of commits"
657
+
658
+
659
+ def status
660
+ begin
661
+ verify_logged_in()
662
+ log_start(__method__, args, options)
663
+ @project = Project.new(get_project_home)
664
+ new_branch = options["new_branch"] || false
665
+
666
+ result = @project.compare_idx(new_branch)["result"]
667
+ commit = result["commit"]
668
+ result = result["tree"]
669
+ say "Comparing local changes with remote version:", Thor::Shell::Color::BLUE
670
+ if result["added"].empty? and result["updated_on_local"].empty? and result["updated_on_server"].empty? and result["deleted"].empty? and result["conflicts"].empty?
671
+ say "Project is up to date", Thor::Shell::Color::GREEN
672
+ log_end(0)
673
+ return true
674
+ end
675
+ if result["added"].size > 0
676
+ say "Added files:\n", Thor::Shell::Color::BLUE
677
+ result["added"].each do |a|
678
+ say "\t\tA:\t#{a}", Thor::Shell::Color::GREEN
416
679
  end
680
+ end
417
681
 
418
- if result["deleted"].size > 0
419
- say "Deleted files:\n", Thor::Shell::Color::BLUE
420
- result["deleted"].each do |a|
421
- say "\t\tD:\t#{a}", Thor::Shell::Color::GREEN
422
- end
682
+ if result["deleted"].size > 0
683
+ say "Deleted files:\n", Thor::Shell::Color::BLUE
684
+ result["deleted"].each do |a|
685
+ say "\t\tD:\t#{a}", Thor::Shell::Color::GREEN
423
686
  end
424
- if result["updated_on_local"].size > 0
425
- say "Local changes:\n", Thor::Shell::Color::BLUE
426
- result["updated_on_local"].each do |a|
427
- say "\t\tM:\t#{a}", Thor::Shell::Color::GREEN
428
- end
687
+ end
688
+ if result["updated_on_local"].size > 0
689
+ say "Local changes:\n", Thor::Shell::Color::BLUE
690
+ result["updated_on_local"].each do |a|
691
+ say "\t\tM:\t#{a}", Thor::Shell::Color::GREEN
429
692
  end
693
+ end
430
694
 
431
- if result["updated_on_server"].size > 0
432
- say "Remote changes:\n", Thor::Shell::Color::BLUE
433
- result["updated_on_server"].each do |a|
434
- say "\t\tM:\t#{a}", Thor::Shell::Color::GREEN
435
- end
695
+ if result["updated_on_server"].size > 0
696
+ say "Remote changes:\n", Thor::Shell::Color::BLUE
697
+ result["updated_on_server"].each do |a|
698
+ say "\t\tM:\t#{a}", Thor::Shell::Color::GREEN
436
699
  end
700
+ end
437
701
 
438
- if result["conflicts"].size > 0
439
- say "Conflicted changes:\n", Thor::Shell::Color::BLUE
440
- result["conflicts"].each do |a|
441
- say "\t\tC:\t#{a}", Thor::Shell::Color::RED
442
- end
702
+ if result["conflicts"].size > 0
703
+ say "Conflicted changes:\n", Thor::Shell::Color::BLUE
704
+ result["conflicts"].each do |a|
705
+ say "\t\tC:\t#{a}", Thor::Shell::Color::RED
443
706
  end
444
- log_end(0)
445
- rescue SignalException
446
- log_end(-1)
447
- say "/nAborting"
448
- exit(1)
449
707
  end
708
+ log_end(0)
709
+ rescue SignalException
710
+ log_end(-1)
711
+ say "\nAborting"
712
+ exit(1)
450
713
  end
714
+ end
451
715
 
452
716
 
453
- desc 'upload', 'Upload updated files'
454
- method_option :ignore, :type => :array, :aliases => ["-i", "--i"], :desc => "ignore following files"
717
+ desc 'upload', 'Upload updated files'
718
+ method_option :ignore, :type => :array, :aliases => ["-i", "--i"], :desc => "ignore following files"
719
+ method_option :new_branch, :type => :boolean, :aliases => ["-nb", "--nb"], :desc => "create new branch of commits"
720
+ method_option :verbose, :type => :boolean, :aliases => ["--v"], :default => false
721
+ method_option :sync, :type => :boolean, :aliases => ["--v"], :default => false
455
722
 
456
- def upload(link=false, sync=false)
723
+ def upload(link=false, sync=false)
457
724
 
458
- begin
459
- verify_logged_in()
460
- log_start(__method__,args,options)
725
+ begin
726
+ verify_logged_in(true)
727
+ log_start(__method__, args, options)
461
728
 
462
- @project = Project.new(get_project_home)
729
+ @project = Project.new(get_project_home)
463
730
 
464
- @files = Cnvrg::Files.new(@project.owner, @project.slug)
465
- ignore = options[:ignore] || []
466
- if !@project.update_ignore_list(ignore)
467
- say "Couldn't append new ignore files to .cnvrgignore", Thor::Shell::Color::YELLOW
468
- end
469
- result = @project.compare_idx
470
- commit = result["result"]["commit"]
471
- if !link
472
- if commit != @project.last_local_commit and !@project.last_local_commit.nil? and !result["result"]["tree"]["updated_on_server"].empty?
473
- log_end(0)
731
+ @files = Cnvrg::Files.new(@project.owner, @project.slug)
732
+ ignore = options[:ignore] || []
733
+ if !@project.update_ignore_list(ignore)
734
+ say "Couldn't append new ignore files to .cnvrgignore", Thor::Shell::Color::YELLOW
735
+ end
736
+ new_branch = options["new_branch"] || false
474
737
 
475
- say "Remote server has an updated version, please run `cnvrg download` first, or alternatively: `cnvrg sync`", Thor::Shell::Color::YELLOW
476
- exit(1)
477
- end
478
- say "Comparing local changes with remote version:", Thor::Shell::Color::BLUE
479
- end
480
- result = result["result"]["tree"]
481
- if result["added"].empty? and result["updated_on_local"].empty? and result["deleted"].empty?
738
+ result = @project.compare_idx(new_branch)
739
+ commit = result["result"]["commit"]
740
+ if !link
741
+ if commit != @project.last_local_commit and !@project.last_local_commit.nil? and !result["result"]["tree"]["updated_on_server"].empty?
482
742
  log_end(0)
483
- say "Project is up to date", Thor::Shell::Color::GREEN
484
- return true
743
+
744
+ say "Remote server has an updated version, please run `cnvrg download` first, or alternatively: `cnvrg sync`", Thor::Shell::Color::YELLOW
745
+ exit(1)
485
746
  end
486
- update_count = 0
487
- update_total = result["added"].size + result["updated_on_local"].size + result["deleted"].size
488
- successful_updates = []
489
- successful_deletions = []
747
+
748
+ say "Comparing local changes with remote version:", Thor::Shell::Color::BLUE if options["verbose"]
749
+ end
750
+ result = result["result"]["tree"]
751
+ if result["added"].empty? and result["updated_on_local"].empty? and result["deleted"].empty?
752
+ log_end(0)
753
+ say "Project is up to date", Thor::Shell::Color::GREEN unless options["sync"]
754
+ return true
755
+ end
756
+ update_count = 0
757
+ update_total = result["added"].size + result["updated_on_local"].size + result["deleted"].size
758
+ successful_updates = []
759
+ successful_deletions = []
760
+ if options["verbose"]
490
761
  if update_total == 1
491
762
  say "Updating #{update_total} file", Thor::Shell::Color::BLUE
492
763
  else
493
764
  say "Updating #{update_total} files", Thor::Shell::Color::BLUE
494
765
  end
766
+ else
767
+ say "Syncing files", Thor::Shell::Color::BLUE unless options["sync"]
495
768
 
496
- # Start commit
769
+ end
497
770
 
498
- commit_sha1 = @files.start_commit["result"]["commit_sha1"]
771
+ # Start commit
499
772
 
500
- # upload / update
501
- begin
502
- (result["added"] + result["updated_on_local"]).each do |f|
503
- puts f
504
- absolute_path = "#{@project.local_path}/#{f}"
505
- relative_path = f.gsub(/^#{@project.local_path + "/"}/, "")
506
- if File.directory?(absolute_path)
507
- resDir = @files.create_dir(absolute_path, relative_path, commit_sha1)
508
- if resDir
509
- update_count += 1
510
- successful_updates<< relative_path
511
- end
773
+ commit_sha1 = @files.start_commit(new_branch)["result"]["commit_sha1"]
774
+
775
+ # upload / update
776
+ begin
777
+ (result["added"] + result["updated_on_local"]).each do |f|
778
+ absolute_path = "#{@project.local_path}/#{f}"
779
+ relative_path = f.gsub(/^#{@project.local_path + "/"}/, "")
780
+ if File.directory?(absolute_path)
781
+ resDir = @files.create_dir(absolute_path, relative_path, commit_sha1)
782
+ if resDir
783
+ update_count += 1
784
+ successful_updates<< relative_path
785
+ end
786
+ else
787
+ res = @files.upload_file(absolute_path, relative_path, commit_sha1)
788
+ if res
789
+ update_count += 1
790
+ successful_updates<< relative_path
512
791
  else
513
- res = @files.upload_file(absolute_path, relative_path, commit_sha1)
514
- if res
515
- update_count += 1
516
- successful_updates<< relative_path
517
- else
518
- @files.rollback_commit(commit_sha1)
519
- log_end(1,"can't upload, Rolling Back all changes")
520
- say "Couldn't upload, Rolling Back all changes.", Thor::Shell::Color::RED
521
- exit(0)
522
- end
792
+ @files.rollback_commit(commit_sha1)
793
+ log_end(1, "can't upload, Rolling Back all changes")
794
+ say "Couldn't upload, Rolling Back all changes.", Thor::Shell::Color::RED
795
+ exit(0)
523
796
  end
524
797
  end
798
+ end
525
799
 
526
- # delete
527
- result["deleted"].each do |f|
528
- relative_path = f.gsub(/^#{@project.local_path + "/"}/, "")
529
- if relative_path.end_with?("/")
530
- if @files.delete_dir(f, relative_path, commit_sha1)
531
- update_count += 1
532
- successful_updates<< relative_path
533
- end
534
- else
535
- if @files.delete_file(f, relative_path, commit_sha1)
536
- update_count += 1
537
- successful_updates<< relative_path
538
- end
800
+ # delete
801
+ result["deleted"].each do |f|
802
+ relative_path = f.gsub(/^#{@project.local_path + "/"}/, "")
803
+ if relative_path.end_with?("/")
804
+ if @files.delete_dir(f, relative_path, commit_sha1)
805
+ update_count += 1
806
+ successful_updates<< relative_path
807
+ end
808
+ else
809
+ if @files.delete_file(f, relative_path, commit_sha1)
810
+ update_count += 1
811
+ successful_updates<< relative_path
539
812
  end
540
813
  end
541
- log_end(0)
542
-
543
- rescue SignalException
544
- log_end(-1)
545
- @files.rollback_commit(commit_sha1)
546
- say "User aborted, Rolling Back all changes.", Thor::Shell::Color::RED
547
- exit(0)
548
- rescue => e
549
- log_end(1,e.message)
550
- @files.rollback_commit(commit_sha1)
551
- say "Exception while trying to upload, Rolling back", Thor::Shell::Color::RED
552
- exit(0)
553
814
  end
554
- if update_count == update_total
555
- res = @files.end_commit(commit_sha1)
556
- if (Cnvrg::CLI.is_response_success(res, false))
557
- # save idx
558
- begin
559
- @project.update_idx_with_files_commits!((successful_deletions+successful_updates), res["result"]["commit_time"])
815
+ log_end(0)
560
816
 
561
- @project.update_idx_with_commit!(commit_sha1)
562
- rescue => e
563
- log_end(1,e.message)
564
- @files.rollback_commit(commit_sha1)
565
- say "Couldn't commit updates, Rolling Back all changes.", Thor::Shell::Color::RED
566
- exit(1)
817
+ rescue SignalException
818
+ log_end(-1)
819
+ @files.rollback_commit(commit_sha1)
820
+ say "User aborted, Rolling Back all changes.", Thor::Shell::Color::RED
821
+ exit(0)
822
+ rescue => e
823
+ log_end(1, e.message)
824
+ @files.rollback_commit(commit_sha1)
825
+ say "Exception while trying to upload, Rolling back", Thor::Shell::Color::RED
826
+ exit(0)
827
+ end
828
+ if update_count == update_total
829
+ res = @files.end_commit(commit_sha1)
830
+ if (Cnvrg::CLI.is_response_success(res, false))
831
+ # save idx
832
+ begin
833
+ @project.update_idx_with_files_commits!((successful_deletions+successful_updates), res["result"]["commit_time"])
834
+
835
+ @project.update_idx_with_commit!(commit_sha1)
836
+ rescue => e
837
+ log_end(1, e.message)
838
+ @files.rollback_commit(commit_sha1)
839
+ say "Couldn't commit updates, Rolling Back all changes.", Thor::Shell::Color::RED
840
+ exit(1)
567
841
 
568
- end
842
+ end
843
+ image = is_project_with_docker(Dir.pwd)
844
+ if image and image.is_docker
845
+ image.update_image_activity(commit_sha1, nil)
846
+ end
847
+ check = Helpers.checkmark()
569
848
 
570
- say "Done", Thor::Shell::Color::BLUE
849
+ if options["verbose"]
850
+ say "#{check} Done", Thor::Shell::Color::BLUE
571
851
  if successful_updates.size >0
572
852
  say "Updated:", Thor::Shell::Color::GREEN
573
853
  suc = successful_updates.map { |x| x=Helpers.checkmark() +" "+x }
@@ -579,832 +859,2290 @@ module Cnvrg
579
859
  say del.join("\n"), Thor::Shell::Color::GREEN
580
860
  end
581
861
  say "Total of #{update_count} / #{update_total} files.", Thor::Shell::Color::GREEN
582
- log_end(0)
583
862
  else
584
- @files.rollback_commit(commit_sha1)
585
- log_end(1, "error. Rolling Back all changes")
586
- say "Error. Rolling Back all changes.", Thor::Shell::Color::RED
863
+ say "#{check} Changes were updated successfully", Thor::Shell::Color::GREEN unless options["sync"]
864
+
587
865
  end
866
+
867
+ log_end(0)
588
868
  else
869
+ @files.rollback_commit(commit_sha1)
589
870
  log_end(1, "error. Rolling Back all changes")
590
-
591
- @files.rollback_commit(commit_sha1)
871
+ say "Error. Rolling Back all changes.", Thor::Shell::Color::RED
592
872
  end
593
- rescue SignalException
594
- log_end(-1)
873
+ else
874
+ log_end(1, "error. Rolling Back all changes")
595
875
 
596
- say "\nAborting",Thor::Shell::Color::BLUE
597
- say "\nRolling back all changes",Thor::Shell::Color::BLUE
598
876
  @files.rollback_commit(commit_sha1)
599
- exit(1)
600
877
  end
878
+ rescue
879
+ log_end(-1)
601
880
 
881
+ say "Error occurd, \nAborting", Thor::Shell::Color::BLUE
882
+ @files.rollback_commit(commit_sha1)
883
+ exit(1)
884
+ rescue SignalException
885
+ log_end(-1)
886
+
887
+ say "\nAborting", Thor::Shell::Color::BLUE
888
+ say "\nRolling back all changes", Thor::Shell::Color::BLUE
889
+ @files.rollback_commit(commit_sha1)
890
+ exit(1)
602
891
  end
603
892
 
604
- desc 'download', 'Download updated files'
893
+ end
605
894
 
606
- def download
607
- begin
608
- verify_logged_in()
609
- log_start(__method__,args,options)
610
- project_home = get_project_home
611
- @project = Project.new(project_home)
612
- @files = Cnvrg::Files.new(@project.owner, @project.slug)
895
+ desc 'download', 'Download updated files'
896
+ method_option :new_branch, :type => :boolean, :aliases => ["-nb", "--nb"], :desc => "create new branch of commits"
897
+ method_option :verbose, :type => :boolean, :aliases => ["--v"], :default => false
898
+ method_option :sync, :type => :boolean, :aliases => ["--v"], :default => false
613
899
 
614
- res = @project.compare_idx["result"]
615
- result = res["tree"]
616
- commit = res["commit"]
617
- if result["updated_on_server"].empty? and result["conflicts"] and result["deleted"].empty?
618
- say "Project is up to date", Thor::Shell::Color::GREEN
619
- log_end(0)
620
- return true
621
- end
622
- update_count = 0
623
- update_total = result["updated_on_server"].size + result["conflicts"].size
900
+ def download
901
+ begin
902
+ verify_logged_in(true)
903
+ log_start(__method__, args, options)
904
+ project_home = get_project_home
905
+ @project = Project.new(project_home)
906
+ @files = Cnvrg::Files.new(@project.owner, @project.slug)
907
+ new_branch = options["new_branch"] || false
908
+
909
+ res = @project.compare_idx(new_branch)["result"]
910
+ result = res["tree"]
911
+ commit = res["commit"]
912
+ if result["updated_on_server"].empty? and result["conflicts"] and result["deleted"].empty?
913
+ say "Project is up to date", Thor::Shell::Color::GREEN unless options["sync"]
914
+ log_end(0)
915
+ return true
916
+ end
917
+ update_count = 0
918
+ update_total = result["updated_on_server"].size + result["conflicts"].size
624
919
 
625
- successful_changes = []
626
- if update_total ==1
627
- say "Downloading #{update_total} file", Thor::Shell::Color::BLUE
628
- else
629
- say "Downloading #{update_total} files", Thor::Shell::Color::BLUE
630
920
 
631
- end
921
+ successful_changes = []
922
+ if update_total ==1
923
+ say "Downloading #{update_total} file", Thor::Shell::Color::BLUE unless options["sync"]
924
+ elsif update_total == 0
925
+ say "Project is up to date", Thor::Shell::Color::GREEN unless options["sync"]
926
+ log_end(0)
927
+ return true
928
+ elsif options["verbose"]
929
+ say "Downloading #{update_total} files", Thor::Shell::Color::BLUE
930
+ else
931
+ say "Syncing files", Thor::Shell::Color::BLUE unless options["sync"]
632
932
 
633
- result["conflicts"].each do |f|
634
- relative_path = f.gsub(/^#{@project.local_path}/, "")
635
- if @files.download_file(f, relative_path, project_home, conflict=true)
636
- successful_changes << relative_path
637
- end
638
933
 
934
+ end
935
+
936
+ result["conflicts"].each do |f|
937
+ relative_path = f.gsub(/^#{@project.local_path}/, "")
938
+ if @files.download_file_s3(f, relative_path, project_home, conflict=true)
939
+ successful_changes << relative_path
639
940
  end
640
- result["updated_on_server"].each do |f|
641
- relative_path = f.gsub(/^#{@project.local_path}/, "")
642
- if f.end_with? "/"
643
- # dir
644
- if @files.download_dir(f, relative_path, project_home)
645
- successful_changes << relative_path
646
941
 
647
- end
648
- else
649
- # blob
650
- if @files.download_file(f, relative_path, project_home)
651
- successful_changes << relative_path
652
- end
653
- end
942
+ end
943
+ result["updated_on_server"].each do |f|
944
+ relative_path = f.gsub(/^#{@project.local_path}/, "")
945
+ if f.end_with? "/"
946
+ # dir
947
+ if @files.download_dir(f, relative_path, project_home)
948
+ successful_changes << relative_path
654
949
 
950
+ end
951
+ else
952
+ # blob
953
+ if @files.download_file_s3(f, relative_path, project_home)
954
+ successful_changes << relative_path
955
+ end
655
956
  end
656
- if update_total == successful_changes.size
657
- # update idx with latest commit
658
- @project.update_idx_with_commit!(commit)
659
957
 
660
- say "Done. Downloaded:", Thor::Shell::Color::GREEN
958
+ end
959
+ if update_total == successful_changes.size
960
+ # update idx with latest commit
961
+ @project.update_idx_with_commit!(commit)
962
+ check = Helpers.checkmark()
963
+
964
+ if options["verbose"]
965
+ say "#{check} Done, Downloaded:", Thor::Shell::Color::GREEN
661
966
  say successful_changes.join("\n"), Thor::Shell::Color::GREEN
662
967
  say "Total of #{successful_changes.size} / #{update_total} files.", Thor::Shell::Color::GREEN
663
- log_end(0)
968
+ else
969
+ say "#{check} Downloaded changes successfully", Thor::Shell::Color::GREEN
664
970
  end
665
- rescue SignalException
666
- log_end(-1)
667
- say "\nAborting", Thor::Shell::Color::BLUE
668
- if successful_changes.nil?
669
- exit(1)
971
+
972
+
973
+ log_end(0)
974
+ end
975
+ rescue SignalException
976
+ log_end(-1)
977
+ say "\nAborting", Thor::Shell::Color::BLUE
978
+ if successful_changes.nil?
979
+ exit(1)
980
+ end
981
+ successful_changes.each do |f|
982
+
983
+ abs_path = "#{@project.local_path}/#{f}"
984
+ filename = File.basename abs_path
985
+ say "revoking #{filename}"
986
+ if result["conflicts"].include? f
987
+ @files.revoke_download_file(abs_path, f, filename, true)
988
+ elsif result["updated_on_server"].include? f
989
+ if File.directory? abs_path
990
+ @files.revoke_download_dir(abs_path, f, project_home)
991
+ else
992
+ @files.revoke_download_file(project_home, abs_path, filename)
993
+ end
670
994
  end
671
- successful_changes.each do |f|
995
+ end
996
+ exit(1)
997
+ end
998
+ end
672
999
 
673
- abs_path = "#{@project.local_path}/#{f}"
674
- filename = File.basename abs_path
675
- say "revoking #{filename}"
676
- if result["conflicts"].include? f
677
- @files.revoke_download_file(abs_path,f,filename,true)
678
- elsif result["updated_on_server"].include? f
679
- if File.directory? abs_path
680
- @files.revoke_download_dir(abs_path,f,project_home)
681
- else
682
- @files.revoke_download_file(project_home,abs_path,filename)
1000
+
1001
+ desc 'jump', 'jump to specific commit'
1002
+
1003
+ def jump(commit_sha1)
1004
+ begin
1005
+ verify_logged_in()
1006
+ log_start(__method__, args, options)
1007
+ project_home = get_project_home
1008
+ @project = Project.new(project_home)
1009
+ # say "Syncing existing project tree before jumping", Thor::Shell::Color::BLUE
1010
+ current_commit = @project.last_local_commit
1011
+ # if current_commit.eql? commit_sha1
1012
+ # say "Project is Updated", Thor::Shell::Color::GREEN
1013
+ # return
1014
+ # end
1015
+ @files = Cnvrg::Files.new(@project.owner, @project.slug)
1016
+ #
1017
+ # say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
1018
+ #
1019
+ # download()
1020
+ # upload()
1021
+ # say "Done Syncing", Thor::Shell::Color::BLUE
1022
+
1023
+ response = @project.clone(false, commit_sha1)
1024
+ successful_changes = []
1025
+ if !response["result"]["tree"].nil?
1026
+ idx = {commit: response["result"]["commit"], tree: response["result"]["tree"]}
1027
+ File.open(project_home + "/.cnvrg/idx.yml", "w+") { |f| f.write idx.to_yaml }
1028
+ current_tree = Dir.entries(".").reject { |file| file.start_with? '.' }
1029
+
1030
+ response["result"]["tree"].each do |f|
1031
+ relative_path = f[0].gsub(/^#{@project.local_path}/, "")
1032
+ if f[0].end_with? "/"
1033
+ # dir
1034
+ if @files.download_dir(f[0], relative_path, project_home)
1035
+ current_tree.delete(relative_path[0, relative_path.size-1])
1036
+ successful_changes << relative_path
1037
+ end
1038
+ else
1039
+ # blob
1040
+ if @files.download_file_s3(f[0], relative_path, project_home)
1041
+ current_tree.delete(relative_path)
1042
+
1043
+ successful_changes << relative_path
683
1044
  end
684
1045
  end
685
1046
  end
686
- exit(1)
687
1047
  end
1048
+ FileUtils.rm_rf(current_tree)
1049
+ say "Done. Jumped completed successfully", Thor::Shell::Color::GREEN
1050
+ log_end(0)
1051
+ rescue SignalException
1052
+ log_end(-1)
1053
+ exi(1)
688
1054
  end
1055
+ end
689
1056
 
690
1057
 
691
- desc 'sync', 'Sync with remote server'
1058
+ desc 'sync', 'Sync with remote server'
1059
+ method_option :new_branch, :type => :boolean, :aliases => ["--nb"], :desc => "create new branch of commits"
1060
+ method_option :verbose, :type => :boolean, :aliases => ["--v"], :default => false
692
1061
 
693
- def sync
694
- say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
695
- invoke :download
696
- invoke :upload
697
- end
698
-
699
- # desc 'random', 'random'
700
- # def random
701
- # say "Fun trivia game for taking a recess :-)", Thor::Shell::Color::BLUE
702
- # subject = ask("Pick a subject\n1.NBA\n2.American History\n3.Data Science\n")
703
- # file = "ds.txt"
704
- # case subject
705
- # when "1"
706
- # file = "nba.txt"
707
- # when "2"
708
- # file = "ah.txt"
709
- # when "3"
710
- # file = "ds.txt"
711
- # end
712
- # line = File.readlines(file).sample
713
- # q = line[0,line.index('?')+1]
714
- # a = line[line.index('?')+1,line.size]
715
- # answer = ask(q+"/n")
716
- #
717
- #
718
- #
719
- # end
720
- # Run
721
- #
722
- desc 'exec CMD', 'Execute a process'
723
- method_option :sync_before, :type => :boolean, :aliases => ["-sb", "--sb"], :default => true
724
- method_option :sync_after, :type => :boolean, :aliases => ["-sa", "--sa"], :default => true
725
- method_option :title, :type => :string, :aliases => ["-t", "--t"], :default => ""
726
- method_option :log, :type => :boolean, :aliases => ["-l", "--l"], :default => false
727
- method_option :email_notification, :type => :boolean, :aliases => ["-en", "--en"], :default => false
728
- method_option :upload_output, :type => :string, :aliases => ["--uo", "-uo"], :default => ""
729
-
730
- def exec(*cmd)
731
- # LogJob.perform_async(cmd,options)
732
- #
733
- log = []
734
- cpu_average =0
735
- memory_average = 0
736
- verify_logged_in()
737
- log_start(__method__,args,options)
738
- project_home = get_project_home
739
- @project = Project.new(project_home)
740
- sync_before = options["sync_before"]
741
- sync_after = options["sync_after"]
742
- print_log = options["log"]
743
- title = options["title"]
744
- email_notification = options["email_notification"]
745
- upload_output = options["upload_output"]
746
- time_to_upload = calc_output_time(upload_output)
1062
+ def sync
1063
+ if options["verbose"]
1064
+ say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
1065
+ else
1066
+ say 'Syncing project', Thor::Shell::Color::BLUE
1067
+ end
747
1068
 
748
- begin
749
- if sync_before
750
- # Sync before run
751
- say "Syncing project before running", Thor::Shell::Color::BLUE
752
- say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
753
1069
 
754
- download()
755
- upload()
756
- say "Done Syncing", Thor::Shell::Color::BLUE
757
- end
1070
+ invoke :download, [], :new_branch => options["new_branch"], :verbose => options["verbose"], :sync=>true
1071
+ invoke :upload, [], :new_branch => options["new_branch"], :verbose => options["verbose"],:sync=>true
1072
+ check = Helpers.checkmark()
758
1073
 
759
- start_commit = @project.last_local_commit
760
- cmd = cmd.join("\s")
1074
+ say "#{check} Syncing project completed successfully", Thor::Shell::Color::GREEN
761
1075
 
762
- say "Running: #{cmd}\n", Thor::Shell::Color::BLUE
1076
+ end
763
1077
 
764
- @exp = Experiment.new(@project.owner, @project.slug)
765
1078
 
766
- platform = RUBY_PLATFORM
767
- machine_name = Socket.gethostname
768
- begin
1079
+ desc 'run cmd', 'Runs an experiment'
1080
+ method_option :local, :type => :boolean, :aliases => ["--l"], :default => false
1081
+ method_option :small, :type => :boolean, :aliases => ["--sm"], :default => false
1082
+ method_option :medium, :type => :boolean, :aliases => ["--med"], :default => false
1083
+ method_option :large, :type => :boolean, :aliases => ["--lg"], :default => false
1084
+ method_option :gpu, :type => :boolean, :aliases => ["--gpu"], :default => false
1085
+ method_option :gpuxl, :type => :boolean, :aliases => ["--gxl"], :default => false
1086
+ method_option :sync_before, :type => :boolean, :aliases => ["--sb"], :default => true
1087
+ method_option :sync_after, :type => :boolean, :aliases => ["--sa"], :default => true
1088
+ method_option :title, :type => :string, :aliases => ["--t"], :default => ""
1089
+ method_option :log, :type => :boolean, :aliases => ["--log"], :default => false
1090
+ method_option :email_notification, :type => :boolean, :aliases => ["--en"], :default => false
1091
+ method_option :upload_output, :type => :string, :aliases => ["--uo"], :default => ""
1092
+ method_option :commit, :type => :string, :aliases => ["--c"], :default => ""
1093
+ method_option :schedule, :type => :string, :aliases => ["--s"], :default => ""
1094
+
1095
+
1096
+ def run(*cmd)
1097
+ sync_before = options["sync_before"]
1098
+ sync_after = options["sync_after"]
1099
+ log = options["log"]
1100
+ title = options["title"]
1101
+ commit = options["commit"] || nil
1102
+ email_notification = options["email_notification"]
1103
+ upload_output = options["upload_output"]
1104
+ local = options["local"]
1105
+ schedule = options["schedule"]
1106
+ if local
1107
+ invoke :exec, [cmd], :sync_before => sync_before, :sync_after => sync_after, :title => title,
1108
+ :log => log, :email_notification => email_notification, :upload_output => upload_output, :commit => commit
1109
+ return
1110
+ else
1111
+ instances = {"small" => options["small"], "medium" => options["medium"], "large" => options["large"], "gpu" => options["gpu"], "gpuxl" => options["gpuxl"]}
1112
+ instance_type = get_instance_type(instances)
1113
+ invoke :exec_remote, [cmd], :sync_before => sync_before, :sync_after => sync_after, :title => title, :machine_type => instance_type,
1114
+ :schedule => schedule, :log => log, :email_notification => email_notification, :upload_output => upload_output, :commit => commit
1115
+ return
1116
+ end
1117
+ end
769
1118
 
770
- @exp.start(cmd, platform, machine_name, start_commit, title, email_notification)
771
- unless @exp.slug.nil?
772
- real = Time.now
773
- exp_success = true
774
- memory_total = []
775
- cpu_total = []
776
- start_loop = Time.now
777
- begin
778
- PTY.spawn(cmd) do |stdout, stdin, pid, stderr|
779
- begin
780
- stdout.each do |line|
781
- cur_time = Time.now
782
- monitor = %x{ps aux|awk '{print $2,$3,$4}'|grep #{pid} }
783
- monitor_by = monitor.split(" ")
784
- memory = monitor_by[2]
785
- cpu = monitor_by[1]
786
- memory_total << memory.to_f
787
- cpu_total << cpu.to_f
788
- real_time= Time.now-real
789
-
790
- cur_log = {time: cur_time,
791
- message: line,
792
- type: "stdout",
793
- real: real_time}
794
- if print_log
795
- puts cur_log
796
- end
797
- log << cur_log
798
1119
 
799
- begin
800
- if time_to_upload !=0
801
- if time_to_upload <= Time.now - start_loop
802
- #upload current log
803
- cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
804
- memory_average = memory_total.inject(0) { |sum, el| sum + el }.to_f / memory_total.size
1120
+ desc '', ''
1121
+ method_option :sync_before, :type => :boolean, :aliases => ["-sb", "--sb"], :default => true
1122
+ method_option :sync_after, :type => :boolean, :aliases => ["-sa", "--sa"], :default => true
1123
+ method_option :title, :type => :string, :aliases => ["-t", "--t"], :default => ""
1124
+ method_option :log, :type => :boolean, :aliases => ["-l", "--l"], :default => false
1125
+ method_option :email_notification, :type => :boolean, :aliases => ["-en", "--en"], :default => false
1126
+ method_option :upload_output, :type => :string, :aliases => ["--uo", "-uo"], :default => ""
1127
+ method_option :commit, :type => :string, :aliases => ["--c", "-c"], :default => ""
1128
+
1129
+ def exec(*cmd)
1130
+ log = []
1131
+ cpu_average =0
1132
+ memory_average = 0
1133
+ verify_logged_in(true)
1134
+ log_start(__method__, args, options)
1135
+ working_dir = Dir.pwd
1136
+ image = is_project_with_docker(working_dir)
1137
+
1138
+
1139
+ sync_before = options["sync_before"]
1140
+ sync_after = options["sync_after"]
1141
+ print_log = options["log"]
1142
+ title = options["title"]
1143
+ commit = options["commit"] || nil
1144
+ email_notification = options["email_notification"]
1145
+ upload_output = options["upload_output"]
1146
+ time_to_upload = calc_output_time(upload_output)
1147
+ project_home = get_project_home
1148
+ @project = Project.new(project_home)
1149
+
1150
+ is_new_branch = @project.compare_commit(commit)
1151
+ begin
1152
+ if !commit.nil? and !commit.empty?
1153
+ invoke :jump, [commit], []
1154
+ else
1155
+ if sync_before
1156
+ # Sync before run
1157
+ invoke :sync, [], :new_branch => is_new_branch
1158
+ end
1159
+ end
805
1160
 
806
- @exp.upload_temp_log(log, cpu_average, memory_average)
807
- log = []
808
- start_loop = Time.now
809
- end
810
1161
 
811
- end
812
- rescue
813
- say "Failed to upload ongoing results, continuing with experiment", Thor::Shell::Color::YELLOW
814
- end
1162
+ if image and image.is_docker
1163
+ container= image.get_container
1164
+ if !container
1165
+ say "Couldn't create container with image #{image.image_name}:#{image.image_tag}", Thor::Shell::Color::RED
1166
+ exit(1)
1167
+ end
1168
+ exec_args = args.flatten.join(" ")
1169
+ exec_options = options.map { |x| "--#{x[0]}=#{x[1]}" }.flatten.join(" ")
1170
+ command_to_run = cmd.join(" ")
1171
+ command = ["/bin/bash", "-lc", "cnvrg exec_docker #{exec_options} #{command_to_run} #{exec_args}"]
1172
+ puts container.exec(command, tty: true)
1173
+ container.stop()
1174
+ exit(0)
1175
+ end
815
1176
 
816
- end
1177
+ start_commit = @project.last_local_commit
1178
+ cmd = cmd.join("\s")
817
1179
 
1180
+ say "Running: #{cmd}\n", Thor::Shell::Color::BLUE
818
1181
 
819
- if stderr
1182
+ @exp = Experiment.new(@project.owner, @project.slug)
820
1183
 
821
- stderr.each do |err|
1184
+ platform = RUBY_PLATFORM
1185
+ machine_name = Socket.gethostname
1186
+ begin
1187
+ machine_activity = @exp.get_machine_activity(Dir.pwd)
1188
+ @exp.start(cmd, platform, machine_name, start_commit, title, email_notification, machine_activity)
1189
+ unless @exp.slug.nil?
1190
+ real = Time.now
1191
+ exp_success = true
1192
+ memory_total = []
1193
+ cpu_total = []
1194
+ start_loop = Time.now
1195
+ begin
1196
+ PTY.spawn(cmd) do |stdout, stdin, pid, stderr|
1197
+ begin
1198
+ stdout.each do |line|
1199
+ cur_time = Time.now
1200
+ monitor = %x{ps aux|awk '{print $2,$3,$4}'|grep #{pid} }
1201
+ monitor_by = monitor.split(" ")
1202
+ memory = monitor_by[2]
1203
+ cpu = monitor_by[1]
1204
+ memory_total << memory.to_f
1205
+ cpu_total << cpu.to_f
1206
+ real_time= Time.now-real
1207
+
1208
+ cur_log = {time: cur_time,
1209
+ message: line,
1210
+ type: "stdout",
1211
+ real: real_time}
1212
+ if print_log
1213
+ puts cur_log
1214
+ end
1215
+ log << cur_log
1216
+
1217
+ begin
1218
+ if time_to_upload !=0
1219
+ if time_to_upload <= Time.now - start_loop
1220
+ #upload current log
1221
+ cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
1222
+ memory_average = memory_total.inject(0) { |sum, el| sum + el }.to_f / memory_total.size
1223
+
1224
+ @exp.upload_temp_log(log, cpu_average, memory_average)
1225
+ log = []
1226
+ start_loop = Time.now
1227
+ end
822
1228
 
823
- log << {time: Time.now, message: err, type: "stderr"}
824
1229
  end
1230
+ rescue
1231
+ say "Failed to upload ongoing results, continuing with experiment", Thor::Shell::Color::YELLOW
825
1232
  end
826
1233
 
827
- rescue Errno::EIO => e
828
- break
829
- rescue Errno::ENOENT
830
- log_end(1, "command #{cmd} isn't valid")
1234
+ end
1235
+
831
1236
 
832
- exp_success = false
1237
+ if stderr
833
1238
 
834
- say "command \"#{cmd}\" couldn't be executed, verify command is valid", Thor::Shell::Color::RED
835
- rescue PTY::ChildExited
836
- log_end(1, "proccess exited")
837
- exp_success = false
838
- say "The process exited!", Thor::Shell::Color::RED
839
- rescue => e
840
- log_end(1,e.message)
841
- end
842
- ::Process.wait pid
843
- cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
844
- memory_average = memory_total.inject(0) { |sum, el| sum + el }.to_f / memory_total.size
845
- exit_status = $?.exitstatus
846
- if $?.exitstatus != 0
847
- exp_success = false
1239
+ stderr.each do |err|
1240
+
1241
+ log << {time: Time.now, message: err, type: "stderr"}
1242
+ end
848
1243
  end
849
- if !exp_success
850
- if !Cnvrg::Helpers.internet_connection?
851
- wait_offline = agree "Seems like you're offline, wait until your'e back online?",limited_to: ['y', 'n'], default: 'n'
852
- if wait_offline
853
- say "Waiting until your'e online..", Thor::Shell::Color::BLUE
854
- while !Cnvrg::Helpers.internet_connection?
855
- end
856
- exit_status = 0
857
- else
858
- say "Experiment has failed, your'e computer is offline", Thor::Shell::Color::RED
859
- log_end(1,"experiment has failed,computer is offline")
860
- exit(0)
1244
+
1245
+ rescue Errno::EIO => e
1246
+ puts e
1247
+ # break
1248
+ rescue Errno::ENOENT
1249
+ log_end(1, "command #{cmd} isn't valid")
1250
+
1251
+ exp_success = false
1252
+
1253
+ say "command \"#{cmd}\" couldn't be executed, verify command is valid", Thor::Shell::Color::RED
1254
+ rescue PTY::ChildExited
1255
+ log_end(1, "proccess exited")
1256
+ exp_success = false
1257
+ say "The process exited!", Thor::Shell::Color::RED
1258
+ rescue => e
1259
+ puts e
1260
+ log_end(1, e.message)
1261
+ end
1262
+ ::Process.wait pid
1263
+ cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
1264
+ memory_average = memory_total.inject(0) { |sum, el| sum + el }.to_f / memory_total.size
1265
+ exit_status = $?.exitstatus
1266
+ if $?.exitstatus != 0
1267
+ exp_success = false
1268
+ end
1269
+ if !exp_success
1270
+ if !Cnvrg::Helpers.internet_connection?
1271
+ wait_offline = agree "Seems like you're offline, wait until your'e back online?", Thor::Shell::Color::YELLOW
1272
+ if wait_offline
1273
+ say "Waiting until your'e online..", Thor::Shell::Color::BLUE
1274
+ while !Cnvrg::Helpers.internet_connection?
861
1275
  end
1276
+ exit_status = 0
862
1277
  else
1278
+ say "Experiment has failed, your'e computer is offline", Thor::Shell::Color::RED
1279
+ log_end(1, "experiment has failed,computer is offline")
1280
+ exit(0)
1281
+ end
1282
+ else
863
1283
 
864
1284
  end_commit = @project.last_local_commit
865
1285
  res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
866
1286
  say "Experiment has failed, look at the log for more details or run cnvrg exec --log", Thor::Shell::Color::RED
867
- log_end(1,"experiment has failed")
1287
+ log_end(1, "experiment has failed")
868
1288
  exit(0)
869
- end
870
-
871
- end
872
- if sync_after
873
- say "Syncing project after running", Thor::Shell::Color::BLUE
874
- # Sync after run
875
- download()
876
- upload()
877
- say "Done Syncing", Thor::Shell::Color::BLUE
878
1289
  end
879
- end_commit = @project.last_local_commit
880
1290
 
881
- res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
882
- check = Helpers.checkmark()
883
- say "#{check} Done. Experiment's result: #{Cnvrg::Helpers.remote_url}/#{@project.owner}/projects/#{@project.slug}/experiments/#{@exp.slug}", Thor::Shell::Color::GREEN
884
- log_end(0)
885
1291
  end
886
- rescue =>e
887
- log_end(1,e.message)
888
- say "Couldn't run #{cmd}, check your input parameters", Thor::Shell::Color::RED
889
- exit(1)
890
- end
1292
+ if sync_after
1293
+ # Sync after run
1294
+ if !commit.nil?
1295
+ invoke :sync, [], :new_branch => true
891
1296
 
1297
+ else
1298
+ invoke :sync, [], :new_branch => true
1299
+ end
1300
+ end
1301
+ end_commit = @project.last_local_commit
892
1302
 
1303
+ res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
1304
+ check = Helpers.checkmark()
1305
+ say "#{check} Done. Experiment's result: #{Cnvrg::Helpers.remote_url}/#{@project.owner}/projects/#{@project.slug}/experiments/#{@exp.slug}", Thor::Shell::Color::GREEN
1306
+ log_end(0)
1307
+ end
1308
+ rescue => e
1309
+ puts e
1310
+ log_end(1, e.message)
1311
+ if container
1312
+ container.stop()
1313
+ end
1314
+ say "Couldn't run #{cmd}, check your input parameters", Thor::Shell::Color::RED
1315
+ exit(1)
893
1316
  end
894
1317
 
1318
+
895
1319
  end
896
- rescue SignalException
897
- exit_status = -1
898
- log_end(-1)
899
- end_commit = @project.last_local_commit
900
1320
 
901
- res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
902
- say "\nAborting"
1321
+ end
1322
+ rescue SignalException
1323
+ exit_status = -1
1324
+ log_end(-1)
1325
+ end_commit = @project.last_local_commit
903
1326
 
904
- exit(1)
1327
+ res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
1328
+ if container
1329
+ container.stop()
905
1330
  end
1331
+ say "\nAborting"
1332
+
1333
+ exit(1)
906
1334
  end
1335
+ end
1336
+
1337
+ desc '', ''
1338
+ method_option :sync_before, :type => :boolean, :aliases => ["-sb", "--sb"], :default => true
1339
+ method_option :sync_after, :type => :boolean, :aliases => ["-sa", "--sa"], :default => true
1340
+ method_option :title, :type => :string, :aliases => ["-t", "--t"], :default => ""
1341
+ method_option :log, :type => :boolean, :aliases => ["-l", "--l"], :default => false
1342
+ method_option :email_notification, :type => :boolean, :aliases => ["-en", "--en"], :default => false
1343
+ method_option :upload_output, :type => :string, :aliases => ["--uo", "-uo"], :default => ""
1344
+
1345
+ def exec_docker(*cmd)
1346
+ log = []
1347
+ cpu_average =0
1348
+ memory_average = 0
1349
+ verify_logged_in()
1350
+ log_start(__method__, args, options)
1351
+ project_home = "/home/ds/notebooks"
1352
+ @project = Project.new(project_home)
1353
+ sync_before = options["sync_before"]
1354
+ sync_after = options["sync_after"]
1355
+ print_log = options["log"]
1356
+ title = options["title"]
1357
+ email_notification = options["email_notification"]
1358
+ upload_output = options["upload_output"]
1359
+ time_to_upload = calc_output_time(upload_output)
1360
+ @image = is_project_with_docker(project_home)
907
1361
 
908
- desc 'run_notebook', 'Starts a new notebook environment'
909
- method_option :notebook_dir, :type => :string, :aliases => ["-n", "--n"], :default => "", :desc => "relative path to notebook dir from current directory"
910
- method_option :docker, :type => :boolean, :aliases => ["-d", "--d"], :default => true
911
- method_option :image_name, :type => :string, :aliases => ["-i", "--i"], :default => ""
912
1362
 
913
- def run_notebook
1363
+ begin
1364
+ start_commit = @project.last_local_commit
1365
+ cmd = cmd.join("\s")
1366
+
1367
+ say "Running: #{cmd}\n", Thor::Shell::Color::BLUE
914
1368
 
1369
+ @exp = Experiment.new(@project.owner, @project.slug)
1370
+ machine_activity = @exp.get_machine_activity(project_home)
1371
+
1372
+ platform = RUBY_PLATFORM
1373
+ machine_name = Socket.gethostname
915
1374
  begin
916
- verify_logged_in(false)
917
- log_start(__method__,args,options)
918
- cur_path = Dir.pwd
919
- notebook_dir = options["notebook_dir"]
920
- if notebook_dir.empty?
921
- notebook_dir = cur_path
922
- else
923
- notebook_dir = cur_path+ notebook_dir
924
- end
925
- say "Linking notebook directory to: #{notebook_dir}", Thor::Shell::Color::BLUE
926
- docker = options["docker"]
927
- try_again = true
928
1375
 
1376
+ @exp.start(cmd, platform, machine_name, start_commit, title, email_notification, machine_activity)
1377
+ unless @exp.slug.nil?
1378
+ real = Time.now
1379
+ exp_success = true
1380
+ memory_total = []
1381
+ cpu_total = []
1382
+ start_loop = Time.now
1383
+ begin
1384
+ PTY.spawn(cmd) do |stdout, stdin, pid, stderr|
1385
+ begin
1386
+ stdout.each do |line|
1387
+ cur_time = Time.now
1388
+ monitor = %x{ps aux|awk '{print $2,$3,$4}'|grep #{pid} }
1389
+ monitor_by = monitor.split(" ")
1390
+ memory = monitor_by[2]
1391
+ cpu = monitor_by[1]
1392
+ memory_total << memory.to_f
1393
+ cpu_total << cpu.to_f
1394
+ real_time= Time.now-real
1395
+
1396
+ cur_log = {time: cur_time,
1397
+ message: line,
1398
+ type: "stdout",
1399
+ real: real_time}
1400
+ if print_log
1401
+ puts cur_log
1402
+ end
1403
+ log << cur_log
1404
+
1405
+ begin
1406
+ if time_to_upload !=0
1407
+ if time_to_upload <= Time.now - start_loop
1408
+ #upload current log
1409
+ cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
1410
+ memory_average = memory_total.inject(0) { |sum, el| sum + el }.to_f / memory_total.size
1411
+
1412
+ @exp.upload_temp_log(log, cpu_average, memory_average)
1413
+ log = []
1414
+ start_loop = Time.now
1415
+ end
929
1416
 
930
- if docker
931
- docker_path = verify_software_installed("docker")
932
- image_name = options["image_name"]
933
- if image_name.empty?
934
- images_list = `#{docker_path} images`
935
- if images_list.empty? or images_list.nil?
936
- say "you don't have any images to run", Thor::Shell::Color::BLUE
937
- else
938
- say "Choose image name to run as a container\n", Thor::Shell::Color::BLUE
939
- say images_list
940
- image_name = ask("\nwhat is the image name?\n")
941
- end
1417
+ end
1418
+ rescue
1419
+ say "Failed to upload ongoing results, continuing with experiment", Thor::Shell::Color::YELLOW
1420
+ end
1421
+
1422
+ end
942
1423
 
943
- end
944
- while (try_again) do
945
- run_docker = `#{docker_path} run -d -p 8888:8888 -v #{notebook_dir}:/home/ds/notebooks -t -i #{image_name} 2>&1`
946
- if !run_docker.match(/[a-z0-9]{64}/).nil? and !run_docker.include? "Error"
947
- container_id = get_container_id()
948
- sleep(3)
949
- logs = `docker logs #{container_id}`
950
- url = URI.extract(logs).reject { |x| x if !x.include? "http" }.uniq![0]
951
- if !url.empty?
952
- check = Helpers.checkmark()
953
-
954
- say "#{check} Notebook server started successfully, view notebook in url: #{url}", Thor::Shell::Color::GREEN
955
- try_again= false
956
- else
957
- say "Couldn't start notebook server", Thor::Shell::Color::RED
958
- log_end(1, "can't start notebook server")
959
- exit(1)
960
- end
961
1424
 
962
- elsif run_docker.include? "port is already allocated"
963
- say "Couldn't start notebook with port 8888, port is taken", Thor::Shell::Color::RED
964
- port_container = `#{docker_path} ps |grep 8888 |awk '{print $1}'`.strip!
965
- stop = agree "There is another running notebook server: #{port_container}, do you want to stop it?", limited_to: ['y', 'n'], default: 'y'
966
- if stop == "y"
967
- did_stop = system("#{docker_path} stop #{port_container}")
968
- if !did_stop
969
- say "Couldn't stop notebook server: #{port_container}", Thor::Shell::Color::RED
970
- log_end(1,"can't stop notebook server")
971
- exit(1)
1425
+ if stderr
972
1426
 
1427
+ stderr.each do |err|
1428
+
1429
+ log << {time: Time.now, message: err, type: "stderr"}
1430
+ end
973
1431
  end
974
- else
975
- logs = `#{docker_path} logs #{port_container}`
976
- url = URI.extract(logs).reject { |x| x if !x.include? "http" }.uniq![0]
977
- say "Done, your notebook server is: #{url}", Thor::Shell::Color::BLUE
978
- log_end(0)
979
- exit(1)
1432
+
1433
+ rescue Errno::EIO => e
1434
+ break
1435
+ rescue Errno::ENOENT
1436
+ log_end(1, "command #{cmd} isn't valid")
1437
+
1438
+ exp_success = false
1439
+
1440
+ say "command \"#{cmd}\" couldn't be executed, verify command is valid", Thor::Shell::Color::RED
1441
+ rescue PTY::ChildExited
1442
+ log_end(1, "proccess exited")
1443
+ exp_success = false
1444
+ say "The process exited!", Thor::Shell::Color::RED
1445
+ rescue => e
1446
+ log_end(1, e.message)
980
1447
  end
981
- else
982
- log_end(1, "can;t start notebook server")
983
- say "Couldn't start notebook server", Thor::Shell::Color::RED
984
- exit(1)
1448
+ ::Process.wait pid
1449
+ cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
1450
+ memory_average = memory_total.inject(0) { |sum, el| sum + el }.to_f / memory_total.size
1451
+ exit_status = $?.exitstatus
1452
+ if $?.exitstatus != 0
1453
+ exp_success = false
1454
+ end
1455
+ if !exp_success
1456
+ if !Cnvrg::Helpers.internet_connection?
1457
+ wait_offline = agree "Seems like you're offline, wait until your'e back online?", Thor::Shell::Color::YELLOW
1458
+ if wait_offline
1459
+ say "Waiting until your'e online..", Thor::Shell::Color::BLUE
1460
+ while !Cnvrg::Helpers.internet_connection?
1461
+ end
1462
+ exit_status = 0
1463
+ else
1464
+ say "Experiment has failed, your'e computer is offline", Thor::Shell::Color::RED
1465
+ log_end(1, "experiment has failed,computer is offline")
1466
+ exit(0)
1467
+ end
1468
+ else
1469
+
1470
+ end_commit = @project.last_local_commit
1471
+ res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
1472
+ @image.update_image_activity(@project.last_local_commit, @exp.slug)
1473
+ say "Experiment has failed, look at the log for more details or run cnvrg exec --log", Thor::Shell::Color::RED
1474
+ log_end(1, "experiment has failed")
1475
+ exit(0)
1476
+ end
1477
+
1478
+ end
1479
+ if sync_after
1480
+ say "Syncing project after running", Thor::Shell::Color::BLUE
1481
+ # Sync after run
1482
+ download()
1483
+ upload()
1484
+ say "Done Syncing", Thor::Shell::Color::BLUE
1485
+ end
1486
+ end_commit = @project.last_local_commit
985
1487
 
1488
+ res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
1489
+ @image.update_image_activity(@project.last_local_commit, @exp.slug)
1490
+
1491
+ check = Helpers.checkmark()
1492
+ say "#{check} Done. Experiment's result: #{Cnvrg::Helpers.remote_url}/#{@project.owner}/projects/#{@project.slug}/experiments/#{@exp.slug}", Thor::Shell::Color::GREEN
1493
+ log_end(0)
986
1494
  end
987
- end
988
- else
989
- jup =verify_software_installed("jupyter-notebook")
990
- logs = `#{jup} --no-browser --ip=0.0.0.0 --notebook-dir=#{notebook_dir}`
991
- url = URI.extract(logs).reject { |x| x if !x.include? "http" }.uniq![0]
992
- if !url.empty?
993
- check = Helpers.checkmark()
994
-
995
- say "#{check} Notebook server started successfully, view notebook in url: #{url}", Thor::Shell::Color::GREEN
996
- log_end(0)
997
- else
998
- say "Couldn't start notebook server", Thor::Shell::Color::RED
999
- log_end(1,"can't start notebook server")
1495
+ rescue => e
1496
+ log_end(1, e.message)
1497
+ say "Couldn't run #{cmd}, check your input parameters", Thor::Shell::Color::RED
1000
1498
  exit(1)
1001
1499
  end
1002
1500
 
1501
+
1003
1502
  end
1004
- rescue SignalException
1005
- log_end(-1)
1006
- say "Aborting"
1007
- exit(1)
1503
+
1504
+ end
1505
+ rescue SignalException
1506
+ exit_status = -1
1507
+ log_end(-1)
1508
+ end_commit = @project.last_local_commit
1509
+ if !@exp.nil?
1510
+
1511
+ res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
1008
1512
  end
1009
1513
 
1514
+ say "\nAborting"
1010
1515
 
1516
+ exit(1)
1011
1517
  end
1518
+ end
1012
1519
 
1013
- desc 'install_notebook_libraries', 'Starts a new notebook environment'
1014
- method_option :commit_name, :type => :string, :aliases => ["-c", "--c"], :default => "", :desc => "commit changes to notebook server when finished"
1520
+ desc '', ''
1521
+ method_option :sync_before, :type => :boolean, :aliases => ["-sb", "--sb"], :default => true
1522
+ method_option :sync_after, :type => :boolean, :aliases => ["-sa", "--sa"], :default => true
1523
+ method_option :title, :type => :string, :aliases => ["-t", "--t"], :default => ""
1524
+ method_option :log, :type => :boolean, :aliases => ["-l", "--l"], :default => false
1525
+ method_option :email_notification, :type => :boolean, :aliases => ["-en", "--en"], :default => false
1526
+ method_option :upload_output, :type => :string, :aliases => ["--uo", "-uo"], :default => ""
1527
+ method_option :machine_type, :type => :string, :aliases => ["--i", "-i"], :default => ""
1528
+ method_option :schedule, :type => :string, :aliases => ["--s", "-s"], :default => ""
1529
+ method_option :commit, :type => :string, :aliases => ["--c", "-c"], :default => nil
1530
+
1531
+ def exec_remote(*cmd)
1532
+ verify_logged_in(true)
1533
+ log_start(__method__, args, options)
1534
+ working_dir = is_cnvrg_dir
1535
+ begin
1015
1536
 
1016
- def install_notebook_libraries
1017
- begin
1018
- verify_logged_in(false)
1019
- log_start(__method__,args,options)
1020
- docker_path = verify_software_installed("docker")
1021
- container_id = get_container_id
1022
- say "Opening shell in notebook server\nYou can run pip install [library] to install more tools\ntype exit to finish", Thor::Shell::Color::BLUE
1023
- system("#{docker_path} exec -it #{container_id} bash")
1024
- commit_name = options["commit_name"]
1025
- if !commit_name.empty?
1026
- return commit_notebook(commit_name)
1537
+ instance_type = options["machine_type"] || nil
1538
+ schedule = options["schedule"] || ""
1539
+ if schedule.start_with? 'in'
1540
+ time = schedule.split(" ")
1541
+
1542
+ local = Time.now.localtime
1543
+ if time[2].downcase().start_with? "min"
1544
+ new = local + (time[1].to_i * 60)
1545
+ elsif time[2].downcase().start_with? "hours"
1546
+ new = local + (time[1].to_i * 3600)
1547
+ elsif time[2].downcase().start_with? "days"
1548
+ new = local + (time[1].to_i * 3600 * 24)
1549
+ else
1550
+ say "Could not undersatnd when to schedule experiment", Thor::Shell::Color::RED
1551
+ exit(1)
1027
1552
  end
1028
- rescue SignalException
1029
- log_End(-1)
1030
- say "/nAborting"
1031
- exit(1)
1553
+ new_time = new.to_s
1554
+ new_time = new_time[0, new_time.size-6] #remove timezone
1555
+ schedule = "at #{new_time}"
1556
+ end
1557
+
1558
+
1559
+ options_hash = Hash[options]
1560
+ options_hash.except!("schedule", "machine_type")
1561
+ exec_options = options_hash.map { |x| "--#{x[0]}=#{x[1]}" }.flatten.join(" ")
1562
+ command = "#{exec_options} --uo=1m #{cmd.flatten.join(" ")}"
1563
+ commit_to_run = options["commit"] || nil
1564
+ if !schedule.nil? and !schedule.empty?
1565
+
1566
+ local_timestamp = get_schedule_date
1567
+
1568
+ end
1569
+ project = Project.new(working_dir)
1570
+
1571
+
1572
+ image = is_project_with_docker(working_dir)
1573
+ if !image or !image.is_docker
1574
+ say "Couldn't find image related to project", Thor::Shell::Color::RED
1575
+ default = yes? "use cnvrg default image?", Thor::Shell::Color::YELLOW
1576
+ if default
1577
+ image = Images.new(working_dir, "cnvrg")
1578
+ image_slug = image.image_slug
1579
+ else
1580
+ exit(0)
1581
+ end
1582
+ else
1583
+ image_slug = image.image_slug
1032
1584
  end
1033
1585
 
1586
+
1587
+
1588
+ invoke :sync, [], []
1589
+
1590
+ say "Running remote experiment", Thor::Shell::Color::BLUE
1591
+ exp = Experiment.new(project.owner, project.slug)
1592
+
1593
+ res = exp.exec_remote(command, commit_to_run, instance_type, image_slug, schedule, local_timestamp)
1594
+ if Cnvrg::CLI.is_response_success(res)
1595
+
1596
+ # if res["result"]["machine"] == -1
1597
+ # say "There are no available machines", Thor::Shell::Color::BLUE
1598
+ # create = yes? "create new machine?", Thor::Shell::Color::YELLOW
1599
+ # if create
1600
+ # res = Cnvrg::API.request("users/#{image.owner}/machines/list", 'GET')
1601
+ # if Cnvrg::CLI.is_response_success(res)
1602
+ # instance_type = machine_options(res["result"]["aws_options"])
1603
+ # if @image.new_machine(instance_type)
1604
+ # say "Running remote experiment", Thor::Shell::Color::BLUE
1605
+ #
1606
+ # # res = image.exec_remote(exec_args, exec_options, project.last_local_commit)
1607
+ # # if Cnvrg::CLI.is_response_success(res)
1608
+ #
1609
+ # check = Helpers.checkmark()
1610
+ # say "#{check} Finished successfuly", Thor::Shell::Color::GREEN
1611
+ # exit(0)
1612
+ # # end
1613
+ # end
1614
+ # else
1615
+ # say "No machines are avilable", Thor::Shell::Color::RED
1616
+ # exit(0)
1617
+ # end
1618
+ #
1619
+ #
1620
+ # else
1621
+ # say "Can't execute command on remote machine with local image", Thor::Shell::Color::RED
1622
+ # exit(1)
1623
+ #
1624
+ # end
1625
+ # else
1626
+ check = Helpers.checkmark()
1627
+ say "#{check} Experiment's is on: #{Cnvrg::Helpers.remote_url}/#{project.owner}/projects/#{project.slug}/experiments/#{res["result"]["exp_url"]}", Thor::Shell::Color::GREEN
1628
+
1629
+ exit(0)
1630
+ # end
1631
+ end
1632
+
1633
+
1634
+ rescue SignalException
1635
+ exit_status = -1
1636
+ log_end(-1)
1637
+ end_commit = project.last_local_commit
1638
+
1639
+ res = @exp.end(log, exit_status, end_commit, "", "")
1640
+ say "\nAborting"
1641
+
1642
+ exit(1)
1643
+ end
1644
+ end
1645
+
1646
+ desc 'deploy', 'Deploys model to production'
1647
+ method_option :machine_type, :type => :string, :aliases => ["--i", "-i"], :default => ""
1648
+ method_option :schedule, :type => :string, :aliases => ["--s", "-s"], :default => ""
1649
+ method_option :commit, :type => :string, :aliases => ["--c", "-c"], :default => ""
1650
+
1651
+ def deploy(file_to_run, function)
1652
+ verify_logged_in(true)
1653
+ log_start(__method__, args, options)
1654
+ working_dir = is_cnvrg_dir
1655
+ begin
1656
+
1657
+ instance_type = options["machine_type"] || nil
1658
+ schedule = options["schedule"] || ""
1659
+
1660
+
1661
+
1662
+ if !schedule.nil? and !schedule.empty?
1663
+
1664
+ local_timestamp = get_schedule_date
1665
+
1666
+ end
1667
+ project = Project.new(working_dir)
1668
+ commit_to_run = options["commit"] || nil
1669
+
1670
+
1671
+ image = is_project_with_docker(working_dir)
1672
+ if !image or !image.is_docker
1673
+ say "Couldn't find image related to project", Thor::Shell::Color::RED
1674
+ default = yes? "use cnvrg default image?", Thor::Shell::Color::YELLOW
1675
+ if default
1676
+ image = Images.new(working_dir, "cnvrg")
1677
+ image_slug = image.image_slug
1678
+ else
1679
+ exit(0)
1680
+ end
1681
+ else
1682
+ image_slug = image.image_slug
1683
+ end
1684
+
1685
+
1686
+
1687
+ invoke :sync, [], []
1688
+
1689
+ res = project.deploy(file_to_run, function, nil, commit_to_run, instance_type, image_slug, schedule, local_timestamp)
1690
+
1691
+ if Cnvrg::CLI.is_response_success(res)
1692
+
1693
+ # if res["result"]["machine"] == -1
1694
+ # say "There are no available machines", Thor::Shell::Color::BLUE
1695
+ # create = yes? "create new machine?", Thor::Shell::Color::YELLOW
1696
+ # if create
1697
+ # res = Cnvrg::API.request("users/#{image.owner}/machines/list", 'GET')
1698
+ # if Cnvrg::CLI.is_response_success(res)
1699
+ # instance_type = machine_options(res["result"]["aws_options"])
1700
+ # if @image.new_machine(instance_type)
1701
+ # say "Running remote experiment", Thor::Shell::Color::BLUE
1702
+ #
1703
+ # # res = image.exec_remote(exec_args, exec_options, project.last_local_commit)
1704
+ # # if Cnvrg::CLI.is_response_success(res)
1705
+ #
1706
+ # check = Helpers.checkmark()
1707
+ # say "#{check} Finished successfuly", Thor::Shell::Color::GREEN
1708
+ # exit(0)
1709
+ # # end
1710
+ # end
1711
+ # else
1712
+ # say "No machines are avilable", Thor::Shell::Color::RED
1713
+ # exit(0)
1714
+ # end
1715
+ #
1716
+ #
1717
+ # else
1718
+ # say "Can't execute command on remote machine with local image", Thor::Shell::Color::RED
1719
+ # exit(1)
1720
+ #
1721
+ # end
1722
+ # else
1723
+ check = Helpers.checkmark()
1724
+ say "#{check} Deployment process is on: #{Cnvrg::Helpers.remote_url}/#{project.owner}/projects/#{project.slug}/deploys/show/#{res["result"]["deploy_slug"]}", Thor::Shell::Color::GREEN
1725
+
1726
+ exit(0)
1727
+ # end
1728
+ end
1729
+
1730
+
1731
+ rescue SignalException
1732
+ exit_status = -1
1733
+ log_end(-1)
1734
+ end_commit = project.last_local_commit
1735
+
1736
+ res = @exp.end(log, exit_status, end_commit, "", "")
1737
+ say "\nAborting"
1738
+
1739
+ exit(1)
1740
+ end
1741
+ end
1742
+
1743
+ method_option :kernel, :type => :string, :aliases => ["--k", "-k"], :default => ""
1744
+ method_option :notebook_dir, :type => :string, :aliases => ["-n", "--n"], :default => "", :desc => "relative path to notebook dir from current directory"
1745
+ method_option :local, :type => :boolean, :aliases => ["--l"], :default => false
1746
+ method_option :small, :type => :boolean, :aliases => ["--sm"], :default => false
1747
+ method_option :medium, :type => :boolean, :aliases => ["--med"], :default => false
1748
+ method_option :large, :type => :boolean, :aliases => ["--lg"], :default => false
1749
+ method_option :gpu, :type => :boolean, :aliases => ["--gpu"], :default => false
1750
+ method_option :gpuxl, :type => :boolean, :aliases => ["--gxl"], :default => false
1751
+ desc 'starts a notebook session', 'starts a notebook session remotely or locally'
1752
+
1753
+ def notebook()
1754
+ local = options["local"]
1755
+ notebook_dir = options["notebook_dir"]
1756
+ kernel = options["kernel"]
1757
+
1758
+ if local
1759
+ invoke :run_notebook, [], :notebook_dir => notebook_dir, :remote => false, :kernel => kernel
1760
+ return
1761
+ else
1762
+ instances = {"small" => options["small"], "medium" => options["medium"], "large" => options["large"], "gpu" => options["gpu"], "gpuxl" => options["gpuxl"]}
1763
+ instance_type = get_instance_type(instances)
1764
+
1765
+ invoke :remote_notebook, [], :notebook_dir => notebook_dir, :kernel => kernel, :machine_type => instance_type
1766
+ return
1767
+
1768
+ end
1769
+
1770
+
1771
+ end
1772
+
1773
+ desc 'remote_notebook', 'run notebook server on remote server'
1774
+ method_option :notebook_dir, :type => :string, :aliases => ["-n", "--n"], :default => "", :desc => "relative path to notebook dir from current directory"
1775
+ method_option :machine_type, :type => :string, :aliases => ["--i", "-i"], :default => ""
1776
+ method_option :kernel, :type => :string, :aliases => ["--k", "-k"], :default => ""
1777
+
1778
+ def remote_notebook()
1779
+ verify_logged_in(true)
1780
+ log_start(__method__, args, options)
1781
+ verify_software_installed("docker")
1782
+
1783
+ working_dir = is_cnvrg_dir()
1784
+ notebook_dir = options["notebook_dir"]
1785
+ instance_type = options["machine_type"] || nil
1786
+ kernel = options["kernel"] || nil
1787
+
1788
+
1789
+ begin
1790
+
1791
+ @image = is_project_with_docker(working_dir)
1792
+ if !@image.is_docker
1793
+ say "Couldn't find image related to project", Thor::Shell::Color::RED
1794
+ exit(0)
1795
+ end
1796
+
1797
+ say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
1798
+
1799
+ download()
1800
+ upload()
1801
+
1802
+
1803
+ res = @image.remote_notebook(notebook_dir, instance_type, kernel)
1804
+ if Cnvrg::CLI.is_response_success(res)
1805
+ if res["result"]["machine"] == -1
1806
+ say "There are no available machines", Thor::Shell::Color::BLUE
1807
+ create = yes? "create new machine?", Thor::Shell::Color::YELLOW
1808
+ if create
1809
+ res = Cnvrg::API.request("users/#{@image.owner}/machines/list", 'GET')
1810
+ if Cnvrg::CLI.is_response_success(res)
1811
+ instance_type = machine_options(res["result"]["aws_options"])
1812
+ if @image.new_machine(instance_type)
1813
+ res = @image.remote_notebook(notebook_dir, instance_type, kernel)
1814
+ if Cnvrg::CLI.is_response_success(res)
1815
+ url = res["result"]["url"]
1816
+ if !url.nil? and !url.empty?
1817
+ check = Helpers.checkmark()
1818
+
1819
+ say "#{check} Notebook server started successfully", Thor::Shell::Color::GREEN
1820
+ Launchy.open(url)
1821
+ else
1822
+ say "Couldn't run notebook server", Thor::Shell::Color::RED
1823
+ end
1824
+ exit(0)
1825
+ end
1826
+ end
1827
+ else
1828
+ say "No machines are avilable", Thor::Shell::Color::RED
1829
+ exit(0)
1830
+ end
1831
+
1832
+
1833
+ else
1834
+ say "Can't execute command on remote machine with local image", Thor::Shell::Color::RED
1835
+ exit(1)
1836
+
1837
+ end
1838
+ else
1839
+ note_url = res["result"]["notebook_url"]
1840
+ @image.set_note_url(note_url)
1841
+ check = Helpers.checkmark()
1842
+ say "#{check} Notebook is on: #{Cnvrg::Helpers.remote_url}/#{@project.owner}/projects/#{@project.slug}/notebook_sessions/show/#{note_url}", Thor::Shell::Color::GREEN
1843
+ # Launchy.open(url)
1844
+
1845
+ exit(0)
1846
+ end
1847
+ end
1848
+
1849
+
1850
+ rescue SignalException
1851
+ exit_status = -1
1852
+ log_end(-1)
1853
+ end_commit = @project.last_local_commit
1854
+
1855
+ res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
1856
+ say "\nAborting"
1857
+
1858
+ exit(1)
1859
+ end
1860
+ end
1861
+
1862
+ desc 'search_libraries', 'search if libraries installed'
1863
+
1864
+ def search_libraries(library)
1865
+ begin
1866
+ verify_logged_in(true)
1867
+ log_start(__method__, args, options)
1868
+ verify_software_installed("docker")
1869
+ project_dir = is_cnvrg_dir()
1870
+
1871
+ image = is_project_with_docker(project_dir)
1872
+ if image and image.is_docker
1873
+ container= image.get_container
1874
+ if !container
1875
+ say "Couldn't create container with image #{image.image_name}:#{image.image_tag}", Thor::Shell::Color::RED
1876
+ exit(1)
1877
+ end
1878
+ else
1879
+ say "Project is not configured with any image", Thor::Shell::Color::RED
1880
+ exit(1)
1881
+
1882
+ end
1883
+
1884
+ say "Searching for #{library}", Thor::Shell::Color::BLUE
1885
+ pip_arr = image.get_installed_packages("python")
1886
+ pip_arr = pip_arr.map(&:downcase)
1887
+ check = Helpers.checkmark()
1888
+ if !(p = pip_arr.map { |x| x.split("==")[0] }.index(library.downcase)).nil?
1889
+
1890
+ say "#{check} Found it!", Thor::Shell::Color::GREEN
1891
+
1892
+
1893
+ printf "%-40s %-30s\n", "#{pip_arr[p].split("==")[0]}", "#{pip_arr[p].split("==")[1]}"
1894
+
1895
+ else
1896
+ dpkg_arr = image.get_installed_packages("system")
1897
+ dpkg_arr = dpkg_arr.map(&:downcase)
1898
+ if !(p = dpkg_arr.map { |x| x.split("==")[0] }.index(library.downcase)).nil?
1899
+ say "#{check} Found!", Thor::Shell::Color::GREEN
1900
+
1901
+ printf "%-40s %-30s\n", "#{dpkg_arr[p].split("==")[0]}", "#{dpkg_arr[p].split("==")[1]}"
1902
+ else
1903
+ say "Couldn't find #{library}, run cnvrg install_libraries to install", Thor::Shell::Color::RED
1904
+ exit(1)
1905
+ end
1906
+
1907
+
1908
+ end
1909
+ rescue => e
1910
+ puts e
1911
+ log_end(-1)
1912
+ say "Error occurd, Aborting"
1913
+ if container
1914
+ container.stop()
1915
+ end
1916
+ rescue SignalException
1917
+ log_end(-1)
1918
+ if container
1919
+ container.stop()
1920
+ end
1921
+ say "Aborting"
1922
+ exit(1)
1923
+ end
1924
+ end
1925
+
1926
+ desc 'show_libraries', 'show system libraries installed'
1927
+ method_option :system, :type => :boolean, :aliases => ["-s", "--s"], :default => false, :desc => "show also system libraries installed"
1928
+
1929
+ def show_libraries
1930
+ begin
1931
+ verify_logged_in(true)
1932
+ log_start(__method__, args, options)
1933
+ verify_software_installed("docker")
1934
+ system = options["system"] || false
1935
+
1936
+
1937
+ project_dir = is_cnvrg_dir()
1938
+
1939
+ image = is_project_with_docker(project_dir)
1940
+ if image and image.is_docker
1941
+ container = image.get_container
1942
+ if !container
1943
+ say "Couldn't create container with image #{image.image_name}:#{image.image_tag}", Thor::Shell::Color::RED
1944
+ exit(1)
1945
+ end
1946
+ else
1947
+ say "Project is not configured with any image", Thor::Shell::Color::RED
1948
+ exit(1)
1949
+
1950
+ end
1951
+
1952
+ say "Showing python installed libraries", Thor::Shell::Color::BLUE
1953
+ pip_arr = image.get_installed_packages("python")
1954
+ printf "%-40s %-30s\n", "name", "version"
1955
+ printf "%-40s %-30s\n", "====", "======="
1956
+
1957
+ pip_arr.each do |p|
1958
+
1959
+ printf "%-40s %-30s\n", "#{p.split("==")[0]}", "#{p.split("==")[1]}"
1960
+ end
1961
+ if system
1962
+
1963
+ say "Showing system installed libraries", Thor::Shell::Color::BLUE
1964
+ dpkg_arr = image.get_installed_packages("system")
1965
+ printf "%-40s %-30s\n", "name", "version"
1966
+ printf "%-40s %-30s\n", "====", "======="
1967
+ dpkg_arr.each do |p|
1968
+ printf "%-40s %-30s\n", "#{p.split("==")[0]}", "#{p.split("==")[1]}"
1969
+
1970
+ end
1971
+ end
1972
+ rescue => e
1973
+ puts e
1974
+ log_end(-1)
1975
+ say "Error occurd, Aborting"
1976
+ if container
1977
+ container.stop()
1978
+ end
1979
+ rescue SignalException
1980
+ log_end(-1)
1981
+ say "Aborting"
1982
+ exit(1)
1983
+ end
1984
+ end
1985
+
1986
+
1987
+ desc 'run_notebook', 'Starts a new notebook environment'
1988
+ method_option :notebook_dir, :type => :string, :aliases => ["-n", "--n"], :default => "", :desc => "relative path to notebook dir from current directory"
1989
+ method_option :remote, :type => :boolean, :aliases => ["-r", "--r"], :default => false, :desc => "run on remote machine"
1990
+ method_option :kernel, :type => :string, :aliases => ["-k", "--k"], :default => "", :desc => "default kernel"
1991
+ method_option :verbose, :type => :boolean, :aliases => ["--v"], :default => false
1992
+
1993
+ def run_notebook
1994
+
1995
+ begin
1996
+ verify_logged_in(true)
1997
+ log_start(__method__, args, options)
1998
+ verify_software_installed("docker")
1999
+
2000
+ project_dir = is_cnvrg_dir()
2001
+
2002
+ notebook_dir = options["notebook_dir"]
2003
+ remote = options["remote"] || false
2004
+ kernel = options["kernel"] || ""
2005
+
2006
+
2007
+ if notebook_dir.empty?
2008
+ notebook_dir = project_dir
2009
+ else
2010
+
2011
+ notebook_dir = project_dir+ notebook_dir
2012
+ end
2013
+ say "Linking notebook directory to: #{File.basename notebook_dir}", Thor::Shell::Color::BLUE
2014
+ image = is_project_with_docker(Dir.pwd)
2015
+ if image and image.is_docker and !remote
2016
+ container= image.get_container
2017
+ if !container
2018
+
2019
+ say "Couldn't create container with image #{image.image_name}:#{image.image_tag}", Thor::Shell::Color::RED
2020
+ exit(1)
2021
+ end
2022
+ else
2023
+ say "Project is not configured with any image", Thor::Shell::Color::RED
2024
+ exit(1)
2025
+
2026
+ end
2027
+ if options["verbose"]
2028
+ say "Syncing project before running", Thor::Shell::Color::BLUE
2029
+ say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
2030
+ end
2031
+ @project = Project.new(project_dir)
2032
+
2033
+ start_commit = @project.last_local_commit
2034
+
2035
+ if (note_slug=image.note_slug)
2036
+ say "There is a running notebook session in: https://cnvrg.io/#{@project.owner}/projects/#{@project.slug}/notebook_sessions/show/#{note_slug}", Thor::Shell::Color::BLUE
2037
+ new = yes? "Create a new session?", Thor::Shell::Color::YELLOW
2038
+ if !new
2039
+ exit(0)
2040
+ end
2041
+
2042
+ end
2043
+ invoke :sync, [], :verbose => options["verbose"]
2044
+ say "Done Syncing", Thor::Shell::Color::BLUE if options["verbose"]
2045
+ #replace url
2046
+ base_url = get_base_url()
2047
+
2048
+ local_url = "/#{@project.owner}/projects/#{@project.slug}/notebook_sessions/view/local"
2049
+ command = ["/bin/bash","-lc","sed -i 's#c.NotebookApp.base_url = .*#c.NotebookApp.base_url = \"#{local_url}\"#' /home/ds/.jupyter/jupyter_notebook_config.py"]
2050
+ container.exec(command, tty: true)
2051
+ container.stop()
2052
+ container.start()
2053
+
2054
+ @note = Experiment.new(@project.owner, @project.slug)
2055
+ port = image.container_port()
2056
+
2057
+ command = ["/bin/bash", "-lc", "jupyter notebook list"]
2058
+ list = container.exec(command, tty: true)[0]
2059
+ if list.empty? or list.nil?
2060
+ say "Couldn't start notebook server", Thor::Shell::Color::RED
2061
+ log_end(1, "can't start notebook server")
2062
+ exit(1)
2063
+ end
2064
+
2065
+ url = list[list.size-1].split(" ::")
2066
+ token = url[0][(url[0].index("=")+1)..-1]
2067
+
2068
+ # machine_activity = @note.get_machine_activity(project_dir)
2069
+
2070
+
2071
+ slug = @note.start_notebook_session(kernel, start_commit, token, port, false, notebook_dir)
2072
+ image.set_note_url(slug)
2073
+ note_url = "http://localhost:#{port}/#{@project.owner}/projects/#{@project.slug}/notebook_sessions/view/local/?token=#{token}"
2074
+
2075
+
2076
+ if !note_url.empty?
2077
+ check = Helpers.checkmark()
2078
+
2079
+ say "#{check} Notebook server started successfully", Thor::Shell::Color::GREEN
2080
+ Launchy.open(note_url)
2081
+ else
2082
+ say "Couldn't start notebook server", Thor::Shell::Color::RED
2083
+ log_end(1, "can't start notebook server")
2084
+ exit(1)
2085
+ end
2086
+
2087
+ # jup =verify_software_installed("jupyter-notebook")
2088
+ # logs = `#{jup} --no-browser --ip=0.0.0.0 --notebook-dir=#{notebook_dir}`
2089
+ # url = URI.extract(logs).reject { |x| x if !x.include? "http" }.uniq![0]
2090
+ # if !url.empty?
2091
+ # check = Helpers.checkmark()
2092
+ #
2093
+ # say "#{check} Notebook server started successfully, view notebook in url: #{url}", Thor::Shell::Color::GREEN
2094
+ # log_end(0)
2095
+ # else
2096
+ # say "Couldn't start notebook server", Thor::Shell::Color::RED
2097
+ # log_end(1, "can't start notebook server")
2098
+ # exit(1)
2099
+ # end
2100
+ rescue => e
2101
+ log_end(-1)
2102
+ puts e
2103
+ say "Error occurd, aborting", Thor::Shell::Color::RED
2104
+ if container
2105
+ container.stop()
2106
+ end
2107
+ rescue SignalException
2108
+ log_end(-1)
2109
+ if container
2110
+ container.stop()
2111
+ end
2112
+ say "Aborting"
2113
+ exit(1)
2114
+ end
2115
+
2116
+
2117
+ end
2118
+
2119
+ desc 'notebook_stop', 'Starts a new notebook environment'
2120
+ method_option :notebook_dir, :type => :string, :aliases => ["-n", "--n"], :default => "", :desc => "relative path to notebook dir from current directory"
2121
+ method_option :remote, :type => :boolean, :aliases => ["-r", "--r"], :default => false, :desc => "run on remote machine"
2122
+ method_option :verbose, :type => :boolean, :aliases => ["--v"], :default => false
2123
+
2124
+ def notebook_stop
2125
+ begin
2126
+ verify_logged_in(true)
2127
+ log_start(__method__, args, options)
2128
+ verify_software_installed("docker")
2129
+ remote = options["remote"] || false
2130
+ project_dir = is_cnvrg_dir()
2131
+
2132
+
2133
+ say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE if options["verbose"]
2134
+ invoke :sync, [], :verbose => options["verbose"]
2135
+
2136
+ say "Done Syncing", Thor::Shell::Color::BLUE if options["verbose"]
2137
+
2138
+
2139
+ @project = Project.new(project_dir)
2140
+
2141
+ end_commit = @project.last_local_commit
2142
+
2143
+ @note = Experiment.new(@project.owner, @project.slug)
2144
+
2145
+ slug = get_note_url(project_dir)
2146
+ @note.end_notebook_session(slug, end_commit)
2147
+
2148
+
2149
+ image = is_project_with_docker(Dir.pwd)
2150
+ if image and image.is_docker and !remote
2151
+ container = image.get_container(true)
2152
+ if !container
2153
+ check = Helpers.checkmark()
2154
+
2155
+ say "#{check} Notebook server stopped successfully", Thor::Shell::Color::GREEN
2156
+ exit(0)
2157
+ end
2158
+
2159
+
2160
+ say "Stopping notebook server...", Thor::Shell::Color::BLUE
2161
+
2162
+ check = Helpers.checkmark()
2163
+ image.remove_note_slug()
2164
+ container.stop()
2165
+
2166
+ say "#{check} Notebook server stopped successfully", Thor::Shell::Color::GREEN
2167
+ log_end(0)
2168
+
2169
+ exit(0)
2170
+ elsif remote
2171
+ say "Stopping notebook server...", Thor::Shell::Color::BLUE
2172
+ check = Helpers.checkmark()
2173
+
2174
+ say "#{check} Notebook server stopped successfully", Thor::Shell::Color::GREEN
2175
+ log_end(0)
2176
+ exit(0)
2177
+ end
2178
+ rescue => e
2179
+ puts e
2180
+ log_end(-1)
2181
+ say "Error occurd, aborting"
2182
+ if container
2183
+ container.stop()
2184
+ end
2185
+ rescue SignalException
2186
+ log_end(-1)
2187
+ say "Aborting"
2188
+ exit(1)
2189
+ end
2190
+
2191
+
2192
+ end
2193
+
2194
+
2195
+ desc 'install_system_libraries', 'Install libraries'
2196
+
2197
+ def install_system_libraries(*command_to_run)
2198
+ begin
2199
+ verify_logged_in(false)
2200
+ log_start(__method__, args, options)
2201
+ verify_software_installed("docker")
2202
+ image = is_project_with_docker(Dir.pwd)
2203
+ if image and image.is_docker
2204
+ container = image.get_container
2205
+ if !container
2206
+
2207
+ say "Couldn't create container with image #{image.image_name}:#{image.image_tag}", Thor::Shell::Color::RED
2208
+ exit(1)
2209
+ end
2210
+ else
2211
+ say "Project is not configured with any image", Thor::Shell::Color::RED
2212
+ exit(1)
2213
+
2214
+ end
2215
+
2216
+ command_to_run = command_to_run.join(" ")
2217
+ say "Running #{command_to_run} in container", Thor::Shell::Color::BLUE
2218
+ command = ["/bin/bash", "-lc", "#{command_to_run}"]
2219
+ res = container.exec(command, tty: false)
2220
+ say res[0].join("\n")
2221
+ checks = Helpers.checkmark()
2222
+ say "Updating image", Thor::Shell::Color::BLUE
2223
+
2224
+ image.create_custom_image("")
2225
+ say "#{checks} Done, installing libraries completed", Thor::Shell::Color::GREEN
2226
+ container.stop()
2227
+
2228
+ log_end(0)
2229
+ rescue => e
2230
+ log_end(-1)
2231
+ puts e
2232
+ say "Error occurd, aborting"
2233
+ if container
2234
+ container.stop()
2235
+ end
2236
+ rescue SignalException
2237
+ log_End(-1)
2238
+ if container
2239
+ container.stop()
2240
+ end
2241
+ say "\nAborting"
2242
+ exit(1)
2243
+ end
2244
+
2245
+ end
2246
+
2247
+ desc 'install_libraries', 'Install libraries'
2248
+ method_option :requirement, :type => :string, :aliases => ["-r", "--r"], :default => "", :desc => "Install from the given requirements file"
2249
+
2250
+ def install_python_libraries(*lib)
2251
+ begin
2252
+ verify_logged_in(false)
2253
+ log_start(__method__, args, options)
2254
+ verify_software_installed("docker")
2255
+ image = is_project_with_docker(Dir.pwd)
2256
+ if image and image.is_docker
2257
+ container = image.get_container
2258
+ if !container
2259
+
2260
+ say "Couldn't create container with image #{image.image_name}:#{image.image_tag}", Thor::Shell::Color::RED
2261
+ exit(1)
2262
+ end
2263
+ else
2264
+ say "Project is not configured with any image", Thor::Shell::Color::RED
2265
+ exit(1)
2266
+
2267
+ end
2268
+ req_file = options["requirement"] || nil
2269
+ if lib.nil? and not req_file.nil?
2270
+ if not File.exist? req_file
2271
+ say "Couldn't find #{req_file}", Thor::Shell::Color::RED
2272
+ exit(1)
2273
+
2274
+ end
2275
+ command_to_run = "pip install -r #{req_file}"
2276
+
2277
+ else
2278
+ command_to_run = lib.join(" ")
2279
+
2280
+ end
2281
+ say "Running #{command_to_run} in container", Thor::Shell::Color::BLUE
2282
+ command = ["/bin/bash", "-lc", "#{command_to_run}"]
2283
+ res = container.exec(command, tty: false)
2284
+ say res[0].join("\n")
2285
+ checks = Helpers.checkmark()
2286
+ say "Updating image", Thor::Shell::Color::BLUE
2287
+
2288
+ image.create_custom_image("")
2289
+ say "#{checks} Done, installing libraries completed", Thor::Shell::Color::GREEN
2290
+ container.stop()
2291
+
2292
+ log_end(0)
2293
+ rescue => e
2294
+ log_end(-1)
2295
+ puts e
2296
+ say "Error occurd, aborting"
2297
+ if container
2298
+ container.stop()
2299
+ end
2300
+ rescue SignalException
2301
+ log_End(-1)
2302
+ if container
2303
+ container.stop()
2304
+ end
2305
+ say "\nAborting"
2306
+ exit(1)
2307
+ end
2308
+
2309
+ end
2310
+
2311
+ desc 'commit_notebook', 'commit notebook changes to create a new notebook image'
2312
+
2313
+ def commit_image
2314
+ verify_logged_in(true)
2315
+ log_start(__method__, args, options)
2316
+ verify_software_installed("docker")
2317
+
2318
+ begin
2319
+ image = is_project_with_docker(Dir.pwd)
2320
+ if image and image.is_docker
2321
+ container= image.get_container
2322
+ if !container
2323
+
2324
+ say "Couldn't create container with image #{image.image_name}:#{image.image_tag}", Thor::Shell::Color::RED
2325
+ exit(1)
2326
+ end
2327
+ else
2328
+ say "Project is not configured with any image", Thor::Shell::Color::RED
2329
+ exit(1)
2330
+
2331
+ end
2332
+ project_home = get_project_home
2333
+ @project = Project.new(project_home)
2334
+ last_local_commit = @project.last_local_commit
2335
+ say "Commiting container into image", Thor::Shell::Color::BLUE
2336
+ new_image_name = "#{@project.slug}#{last_local_commit}:latest"
2337
+ image.update_image(new_image_name, container)
2338
+ new_image = container.commit('repo' => "#{@project.slug}#{last_local_commit}", 'tag' => "lastest")
2339
+ checks = Helpers.checkmark()
2340
+ say "#{checks} Done, image was updated", Thor::Shell::Color::GREEN
2341
+ log_end(0)
2342
+ return new_image.id
2343
+ rescue => e
2344
+ puts e
2345
+
2346
+ rescue SignalException
2347
+ log_end(-1)
2348
+ say "\nAborting"
2349
+ exit(1)
2350
+ end
2351
+ end
2352
+
2353
+ desc 'sync_image', 'sync current container into image, and push it to cnvrg repository'
2354
+ method_option :is_public, :type => :boolean, :aliases => ["-p", "--p"], :default => false, :desc => "is public"
2355
+ method_option :is_base, :type => :boolean, :aliases => ["-b", "--b"], :default => false, :desc => "is base for others images"
2356
+ method_option :message, :type => :string, :aliases => ["-m", "--m"], :default => "", :desc => "commit message for this image"
2357
+
2358
+ def sync_image(docker=false)
2359
+ verify_logged_in(true)
2360
+ log_start(__method__, args, options)
2361
+ verify_software_installed("docker")
2362
+ is_public = options["is_public"] || false
2363
+ is_base = options["is_base"] || false
2364
+ message = options["message"] || ""
2365
+ image_id = commit_image
2366
+
2367
+ if docker
2368
+ message = "before running experiment"
2369
+ image = is_project_with_docker(Dir.pwd)
2370
+ if image and image.is_docker
2371
+ container = image.get_container
2372
+ if !container
2373
+
2374
+ upload_image(image_id, is_public, is_base, message)
2375
+ else
2376
+ command = ["/bin/bash", "-lc", "cnvrg upload_image #{image_id} #{is_public} #{is_base} #{message}"]
2377
+ puts "Running in contianer"
2378
+ container.exec(command, detach: false)
2379
+ end
2380
+ end
2381
+
2382
+ else
2383
+ upload_image(image_id, is_public, is_base, message)
2384
+ end
2385
+
2386
+ end
2387
+
2388
+ desc 'create_custom_image', 'commit notebook changes to create a new notebook image'
2389
+ method_option :name, :type => :string, :aliases => ["-n", "--n"], :default => "", :desc => "new image name"
2390
+
2391
+ def create_custom_image()
2392
+ verify_logged_in(true)
2393
+ log_start(__method__, args, options)
2394
+ working_dir = is_cnvrg_dir()
2395
+ image_name = options["name"] || ""
2396
+ if !image_name.empty? and image_name == "cnvrg"
2397
+ say "can't create image with the name cnvrg", Thor::Shell::Color::RED
2398
+ exit(1)
2399
+ end
2400
+ begin
2401
+ image = is_project_with_docker(working_dir)
2402
+ if !image or !image.is_docker
2403
+ say "Couldn't find image related to project", Thor::Shell::Color::RED
2404
+ exit(0)
2405
+ end
2406
+
2407
+ image.create_custom_image(image_name)
2408
+ say "Image was updated successfully", Thor::Shell::Color::BLUE
2409
+
2410
+ rescue => e
2411
+ puts e
2412
+ end
2413
+ end
2414
+
2415
+
2416
+ desc 'upload_image', 'commit notebook changes to create a new notebook image'
2417
+
2418
+ def upload_image(image_id, is_public, is_base, *message)
2419
+ verify_logged_in(true)
2420
+ log_start(__method__, args, options)
2421
+ verify_software_installed("docker")
2422
+ image = Docker::Image.get(image_id)
2423
+ project_home = get_project_home
2424
+ @project = Project.new(project_home)
2425
+ last_local_commit = @project.last_local_commit
2426
+ image_name = @project.slug+"#{last_local_commit}"
2427
+ path = File.expand_path('~')+"/.cnvrg/tmp/#{image_name}.tar"
2428
+ owner = Cnvrg::CLI.get_owner()
2429
+ if !message.nil? or !message.empty?
2430
+ message = message.join(" ")
2431
+ end
2432
+
2433
+ say "Saving image's current state", Thor::Shell::Color::BLUE
2434
+ image.save(path)
2435
+
2436
+ begin
2437
+ say "Compressing image file to upload", Thor::Shell::Color::BLUE
2438
+ gzipRes = system("gzip -f #{path}")
2439
+ if !gzipRes
2440
+ log_End(1, "can't create gz file from image")
2441
+
2442
+ say "Couldn't create tar file from image", Thor::Shell::Color::RED
2443
+ exit(1)
2444
+ end
2445
+ path = path+".gz"
2446
+ @files = Cnvrg::Files.new(owner, "")
2447
+
2448
+ exit_status = $?.exitstatus
2449
+ if exit_status == 0
2450
+ say "Uploading image file", Thor::Shell::Color::BLUE
2451
+
2452
+ diff =container_changes(Dir.pwd)
2453
+ res = @files.upload_image(path, image_name, owner, is_public, is_base, diff[1], diff[0], diff[2], message, image.commit_id)
2454
+ if res
2455
+ File.delete(path)
2456
+ image_loc = is_project_with_docker(Dir.pwd)
2457
+ image_loc.update_slug(res["result"]["id"])
2458
+
2459
+ checks = Helpers.checkmark()
2460
+ say "#{checks} Done", Thor::Shell::Color::GREEN
2461
+ log_end(0)
2462
+ else
2463
+ say "Couldn't upload image", Thor::Shell::Color::RED
2464
+ log_end(1, "can't create upload imag")
2465
+
2466
+ end
2467
+ else
2468
+ say "Couldn't create image file for: #{image_name}", Thor::Shell::Color::RED
2469
+ log_end(1, "can't create upload imag")
2470
+ exit(1)
2471
+ end
2472
+ rescue => e
2473
+ puts e
2474
+
2475
+ rescue SignalException
2476
+ log_end(-1)
2477
+
2478
+ say "Couldn't upload image file for: #{image_name}", Thor::Shell::Color::RED
2479
+ exit(1)
2480
+ end
2481
+ end
2482
+
2483
+ desc '', ''
2484
+
2485
+ def upload_log()
2486
+ log_path = '/home/ds/app/uwsgi.log'
2487
+ loglines = File.new(log_path).readlines
2488
+ logs = loglines.select { |x| x.start_with? "cnvrg_app:" }.collect { |x| x.strip }
2489
+
2490
+ end
2491
+
2492
+ desc '', ''
2493
+
2494
+ def exec_container(container_id, *cmd)
2495
+ container = Docker::Container.get(container_id)
2496
+ container.start()
2497
+ cnvrg_command = cmd.join(" ")
2498
+ command = ["/bin/bash", "-lc", "#{cnvrg_command}"]
2499
+ res = container.exec(command, tty: true,wait:5400)[0]
2500
+ say res
2501
+
2502
+ end
2503
+
2504
+ desc '', ''
2505
+
2506
+ def port_container(container_id)
2507
+ container = Docker::Container.get(container_id)
2508
+ say container.json["HostConfig"]["PortBindings"]["8888/tcp"][0]["HostPort"]
2509
+
2510
+
2511
+ end
2512
+
2513
+ desc '', ''
2514
+
2515
+ def stop_container(container_id)
2516
+ container = Docker::Container.get(container_id)
2517
+ container.stop()
2518
+ container.remove()
2519
+
2520
+ end
2521
+
2522
+ desc '', ''
2523
+ method_option :login, :type => :string, :aliases => ["-l", "--l"], :default => ""
2524
+ method_option :app_dir, :type => :string, :aliases => ["-d", "--d"], :default => "/home/ds/notebooks"
2525
+ method_option :cmd, :type => :string, :aliases => ["-c", "--c"], :default => "/home/ds/run_ipython.sh"
2526
+
2527
+
2528
+ def config_remote(image_name, port=7654)
2529
+ local_images = Docker::Image.all
2530
+
2531
+ docker_image_local = local_images.map { |x| x.info["RepoTags"] }.flatten.select { |y| y.eql? "#{image_name}:latest" }.flatten
2532
+ if docker_image_local.empty?
2533
+ say "no image"
2534
+ exit(1)
2535
+ end
2536
+
2537
+ begin
2538
+ login_content = options["login"]
2539
+ app_dir = options["app_dir"]
2540
+ cmd= options["cmd"]
2541
+
2542
+ image_settings = {
2543
+ 'Image' => "#{image_name}:latest",
2544
+ 'User' => 'ds',
2545
+ 'Cmd' => cmd,
2546
+ 'WorkingDir' => app_dir,
2547
+ 'ExposedPorts' => {
2548
+ '8888/tcp' => {},
2549
+ },
2550
+ 'HostConfig' => {
2551
+ 'PortBindings' => {
2552
+ '8888/tcp' => [
2553
+ {'HostPort' => "#{port}", 'HostIp' => 'localhost'}
2554
+ ],
2555
+ },
2556
+ },
2557
+ }
2558
+ container = Docker::Container.create(image_settings)
2559
+ container.start()
2560
+ command = ["/bin/bash", "-lc", "sudo echo -e \"#{login_content}\" >/home/ds/.netrc"]
2561
+ container.exec(command, tty: true)
2562
+ command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg"]
2563
+ container.exec(command, tty: true)
2564
+ command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg/tmp"]
2565
+ container.exec(command, tty: true)
2566
+ command = ["/bin/bash", "-lc", "sudo chown -R ds /home/ds/.cnvrg /home/ds/.netrc"]
2567
+ container.exec(command, tty: true)
2568
+ command = ["/bin/bash", "-lc", "sudo chmod 0600 /home/ds/.netrc"]
2569
+ container.exec(command, tty: true)
2570
+ say "#{container.id}:#{port}"
2571
+ rescue => e
2572
+ if e.message.include? "is not running"
2573
+ return config_remote(image_name, port-1)
2574
+ end
2575
+ puts "error"
2576
+ puts e
2577
+ if container
2578
+ container.kill()
2579
+ end
2580
+ return false
2581
+ end
2582
+ end
2583
+
2584
+ desc '', ''
2585
+ method_option :login, :type => :string, :aliases => ["-l", "--l"], :default => ""
2586
+
2587
+ def config_flask_remote(image_name, port=80)
2588
+ local_images = Docker::Image.all
2589
+
2590
+ docker_image_local = local_images.map { |x| x.info["RepoTags"] }.flatten.select { |y| y.eql? "#{image_name}:latest" }.flatten
2591
+ if docker_image_local.empty?
2592
+ say "no image"
2593
+ exit(1)
2594
+ end
2595
+
2596
+ begin
2597
+ login_content = options["login"]
2598
+ image_settings = {
2599
+ 'Image' => "#{image_name}:latest",
2600
+ 'User' => 'ds',
2601
+ 'Cmd' => '/home/ds/start_super.sh',
2602
+ 'WorkingDir' => '/home/ds/app',
2603
+ 'ExposedPorts' => {
2604
+ '80/tcp' => {},
2605
+ },
2606
+ 'HostConfig' => {
2607
+ 'PortBindings' => {
2608
+ '80/tcp' => [
2609
+ {'HostPort' => "#{port}", 'HostIp' => 'localhost'}
2610
+ ],
2611
+ },
2612
+ },
2613
+ }
2614
+ container = Docker::Container.create(image_settings)
2615
+ container.start()
2616
+ command = ["/bin/bash", "-lc", "sudo echo -e \"#{login_content}\" >/home/ds/.netrc"]
2617
+ container.exec(command, tty: true)
2618
+ command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg"]
2619
+ container.exec(command, tty: true)
2620
+ command = ["/bin/bash", "-lc", "mkdir /home/ds/.cnvrg/tmp"]
2621
+ container.exec(command, tty: true)
2622
+ command = ["/bin/bash", "-lc", "sudo chown -R ds /home/ds/.cnvrg /home/ds/.netrc"]
2623
+ container.exec(command, tty: true)
2624
+ command = ["/bin/bash", "-lc", "sudo chmod 0600 /home/ds/.netrc"]
2625
+ container.exec(command, tty: true)
2626
+ say "#{container.id}:#{port}"
2627
+ rescue => e
2628
+ if e.message.include? "is not running"
2629
+ return "port is taken"
2630
+ end
2631
+ puts "error"
2632
+ puts e
2633
+ if container
2634
+ container.kill()
2635
+ end
2636
+ return false
2637
+ end
2638
+ end
2639
+
2640
+ desc '', ''
2641
+
2642
+ def upload_cnvrg_image(image_name)
2643
+ verify_logged_in(false)
2644
+ log_start(__method__, args, options)
2645
+ verify_software_installed("docker")
2646
+ owner = Cnvrg::CLI.get_owner()
2647
+
2648
+ path = File.expand_path('~')+"/.cnvrg/tmp/#{image_name}.zip"
2649
+ @files = Cnvrg::Files.new("", "")
2650
+ python_arr = Cnvrg::Images.get_installed_packages("python")
2651
+ py = python_arr.join(",") unless python_arr.nil? or python_arr.empty?
2652
+ system_arr = Cnvrg::Images.get_installed_packages("system")
2653
+ sys = system_arr.join(",") unless system_arr.nil? or system_arr.empty?
2654
+ bash_history = Cnvrg::Images.get_bash_history
2655
+ res = @files.upload_image(path, image_name, owner, true, true, sys, py, bash_history, "Image made by cnvrg.io team", "")
2656
+
2657
+ end
2658
+
2659
+
2660
+ desc '', ''
2661
+
2662
+ def download_built_image(image_name, image_slug)
2663
+ begin
2664
+ verify_logged_in(false)
2665
+ log_start(__method__, args, options)
2666
+ owner = Cnvrg::CLI.get_owner()
2667
+ path = File.expand_path('~')+"/.cnvrg/tmp/#{image_name}.tar.gz"
2668
+ @files = Cnvrg::Files.new(owner, "")
2669
+
2670
+ say "Downloading image file", Thor::Shell::Color::BLUE
2671
+ begin
2672
+ if @files.download_image(path, image_slug, owner)
2673
+ gzipRes = system("gunzip -f #{path}")
2674
+ if !gzipRes
2675
+ log_End(1, "can't unzip gz file from image")
2676
+
2677
+ say "Couldn't create tar file from image", Thor::Shell::Color::RED
2678
+ exit(1)
2679
+ else
2680
+ path = path.gsub(".gz", "")
2681
+ return path
2682
+ end
2683
+
2684
+ else
2685
+ say "Couldn't download image #{image_name}", Thor::Shell::Color::RED
2686
+ log_end(1, "can't download image")
2687
+ return false
2688
+ end
2689
+ rescue Interrupt
2690
+ log_end(-1)
2691
+ say "The user has exited to process, aborting", Thor::Shell::Color::BLUE
2692
+ exit(1)
2693
+ end
2694
+ rescue SignalException
2695
+ log_end(-1)
2696
+ say "\nAborting"
2697
+ exit(1)
2698
+ end
2699
+ end
2700
+
2701
+ desc '', ''
2702
+
2703
+ def download_image(image_name, image_slug)
2704
+ begin
2705
+ verify_logged_in(false)
2706
+ log_start(__method__, args, options)
2707
+ owner = Cnvrg::CLI.get_owner()
2708
+ path = File.expand_path('~')+"/.cnvrg/tmp/#{image_name}.zip"
2709
+ @files = Cnvrg::Files.new(owner, "")
2710
+
2711
+ say "Downloading image file", Thor::Shell::Color::BLUE
2712
+ begin
2713
+ if @files.download_image(path, image_slug, owner)
2714
+
2715
+ dir_path = File.expand_path('~')+"/.cnvrg/tmp/#{image_name}"
2716
+ FileUtils.mkdir_p([dir_path])
2717
+ Zip::File.open(path) do |zip_file|
2718
+ # Handle entries one by one
2719
+ zip_file.each do |entry|
2720
+ f_path=File.join(dir_path, entry.name)
2721
+ zip_file.extract(entry, f_path)
2722
+ end
2723
+ end
2724
+
2725
+ return dir_path
2726
+
2727
+ else
2728
+ say "Couldn't download image #{image_name}", Thor::Shell::Color::RED
2729
+ log_end(1, "can't download image")
2730
+ return false
2731
+ end
2732
+ rescue Interrupt
2733
+ log_end(-1)
2734
+ say "The user has exited to process, aborting", Thor::Shell::Color::BLUE
2735
+ exit(1)
2736
+ end
2737
+ rescue SignalException
2738
+ log_end(-1)
2739
+ say "\nAborting"
2740
+ exit(1)
2741
+ ensure
2742
+ if !path.nil?
2743
+ FileUtils.rm(path)
2744
+ end
2745
+ end
2746
+ end
2747
+
2748
+
2749
+ desc 'list_images', 'lists all custom images you can pull'
2750
+
2751
+ def list_images
2752
+ begin
2753
+ verify_logged_in(false)
2754
+ log_start(__method__, args, options)
2755
+ owner = Cnvrg::CLI.get_owner()
2756
+ res = Cnvrg::API.request("users/#{owner}/images/list", 'GET')
2757
+ if Cnvrg::CLI.is_response_success(res)
2758
+ printf "%-20s %-20s %-30s %-20s %-20s %-20s\n", "name", "project", "message", "created by", "is_public", "last updated"
2759
+ res["result"]["images"].each do |u|
2760
+ time = Time.parse(u["created_at"])
2761
+ update_at = get_local_time(time)
2762
+ created_by = u["created_by"]
2763
+
2764
+ printf "%-20s %-20s %-30s %-20s %-20s %-20s\n", u["name"], u["project"], u["message"], created_by, u["is_public"], update_at
2765
+ end
2766
+ end
2767
+ log_end(0)
2768
+ return res["result"]["images"]
2769
+ rescue SignalException
2770
+ log_end(-1)
2771
+ say "\nAborting"
2772
+ exit(1)
2773
+ end
2774
+
2775
+
2776
+ end
2777
+
2778
+ desc 'list_machines', 'lists all machines belong to your organization'
2779
+
2780
+ def list_machines
2781
+ begin
2782
+ verify_logged_in(false)
2783
+ log_start(__method__, args, options)
2784
+ owner = Cnvrg::CLI.get_owner()
2785
+ res = Cnvrg::API.request("users/#{owner}/machines/list", 'GET')
2786
+ if Cnvrg::CLI.is_response_success(res)
2787
+ printf "%-20s %-20s %-20s\n", "name", "created by", "last_used"
2788
+ res["result"]["machines"].each do |u|
2789
+ time = Time.parse(u["last_used"])
2790
+ update_at = get_local_time(time)
2791
+ printf "%-20s %-20s %-20s\n", u["name"], u["created_by"], update_at
2792
+ end
2793
+ end
2794
+ log_end(0)
2795
+ return res["result"]["images"]
2796
+ rescue SignalException
2797
+ log_end(-1)
2798
+ say "\nAborting"
2799
+ exit(1)
1034
2800
  end
1035
2801
 
1036
- desc 'commit_notebook', 'commit notebook changes to create a new notebook image'
1037
2802
 
1038
- def commit_notebook(notebook_image_name)
1039
- verify_logged_in(false)
1040
- log_start(__method__,args,options)
1041
- begin
1042
- docker_path = verify_software_installed("docker")
1043
-
1044
- container_id = get_container_id
1045
- owner = Cnvrg::CLI.get_owner()
1046
- say "Commiting notebook changes to: #{notebook_image_name}", Thor::Shell::Color::BLUE
2803
+ end
1047
2804
 
1048
- commit_res = system("#{docker_path} commit #{container_id} #{notebook_image_name}")
1049
- if commit_res
1050
- checker = Helpers.checkmark()
1051
- log_end(0)
1052
- say "#{checker} Done.", Thor::Shell::Color::GREEN
1053
- else
1054
- log_End(1,"can't commit new notebook image")
1055
- say "Couldn't commit new notebook image ", Thor::Shell::Color::RED
2805
+ desc 'get_machine', 'create new aws machine'
1056
2806
 
2807
+ def get_machine()
2808
+ begin
2809
+ verify_logged_in(true)
2810
+ log_start(__method__, args, options)
2811
+ owner = Cnvrg::CLI.get_owner()
2812
+ working_dir = is_cnvrg_dir
2813
+ @image = Images.new(working_dir)
2814
+ if @image.nil? or !@image.is_docker
2815
+ say "Couldn't find image related to this project", Thor::Shell::Color::RED
2816
+ exit(0)
2817
+ end
2818
+ res = Cnvrg::API.request("users/#{owner}/machines/list", 'GET')
2819
+ if Cnvrg::CLI.is_response_success(res)
2820
+ if res["result"]["machines"].empty?
2821
+ create = yes? "No machines available, create new machine?", Thor::Shell::Color::YELLOW
2822
+ if create
2823
+ instance_type = machine_options(res["result"]["aws_options"])
2824
+ else
2825
+ exit(0)
2826
+ end
2827
+ end
2828
+ printf "%-20s %-20s %-20s\n", "name", "created by", "last_used", "instance_type"
2829
+ res["result"]["machines"].each do |u|
2830
+ time = Time.parse(u["last_used"])
2831
+ update_at = get_local_time(time)
2832
+ printf "%-20s %-20s %-20s\n", u["name"], u["created_by"], update_at, u["instance type"]
1057
2833
  end
1058
- rescue SignalException
1059
- log_end(-1)
1060
- say "/nAborting"
1061
- exit(1)
1062
2834
  end
2835
+
2836
+ rescue SignalException
2837
+ log_end(-1)
2838
+ say "\nAborting"
2839
+ exit(1)
1063
2840
  end
2841
+ end
2842
+
1064
2843
 
1065
- desc 'upload_notebook', 'commit notebook changes to create a new notebook image'
2844
+ desc 'pull_image', 'downloads and loads an image'
1066
2845
 
1067
- def upload_image(image_name)
2846
+ def pull_image(image_name)
2847
+ begin
1068
2848
  verify_logged_in(false)
1069
- log_start(__method__,args,options)
1070
- docker_path = verify_software_installed("docker")
2849
+ log_start(__method__, args, options)
1071
2850
  owner = Cnvrg::CLI.get_owner()
1072
- # verify image exist
1073
- images = `#{docker_path} images |grep #{image_name}`
1074
- if images.empty?
1075
- say "Couldn't find any images named: #{image_name}", Thor::Shell::Color::RED
2851
+ image = Cnvrg::Images.image_exist(owner, image_name)
2852
+ if !image
2853
+ say "Couldn't find image in cnvrg repository", Thor::Shell::Color::RED
1076
2854
  exit(1)
1077
2855
  end
1078
- path = File.expand_path('~')+"/.cnvrg/#{owner}_#{image_name}.tar"
1079
- begin
1080
- say "Creating image file to upload", Thor::Shell::Color::BLUE
1081
- if !(File.exist? path or File.exist? path+"gz")
1082
- saveRes = system("#{docker_path} save #{image_name}>#{path}")
1083
- if !saveRes
1084
- log_End(1, "can't create tar file from image")
1085
- say "Couldn't create tar file from image", Thor::Shell::Color::RED
1086
- exit(1)
1087
- end
1088
- gzipRes = system("gzip -f #{path}")
1089
- if !gzipRes
1090
- log_End(1, "can't create tar file from image")
1091
-
1092
- say "Couldn't create tar file from image", Thor::Shell::Color::RED
1093
- exit(1)
1094
- end
1095
- end
1096
-
1097
- path = path+".gz"
1098
- @files = Cnvrg::Files.new(owner, "")
1099
-
1100
- exit_status = $?.exitstatus
1101
- if exit_status == 0
1102
- say "Uploading image file", Thor::Shell::Color::BLUE
1103
- res = @files.upload_image(path, image_name, owner)
1104
- if res
1105
- File.delete(path)
1106
- checks = Helpers.checkmark()
1107
- say "#{checks} Done", Thor::Shell::Color::GREEN
1108
- log_end(0)
1109
- else
1110
- say "Couldn't upload image", Thor::Shell::Color::RED
1111
- log_end(1, "can't create upload imag")
1112
-
1113
- end
2856
+ path = download_image(image_name, image["slug"])
2857
+ if path
2858
+ say "Building image", Thor::Shell::Color::BLUE
2859
+ Docker.options[:read_timeout]=1200
2860
+ image = Docker::Image.build_from_dir(path, {'dockerfile' => 'Dockerfile', 't' => "#{image_name}:lastest"})
2861
+ if not image.nil?
2862
+ say "Finished downloading image, cleaning up..", Thor::Shell::Color::GREEN
2863
+ FileUtils.rm_rf(path)
2864
+ checks = Helpers.checkmark()
2865
+ say "#{checks} Done", Thor::Shell::Color::GREEN
2866
+ log_end(0)
2867
+ return image
2868
+ log_end(0)
1114
2869
  else
1115
- say "Couldn't create image file for: #{image_name}", Thor::Shell::Color::RED
1116
- log_end(1, "can't create upload imag")
1117
- exit(1)
2870
+ say "Could not build image", Thor::Shell::Color::RED
2871
+ log_end(1, "Could build image")
2872
+ return false
1118
2873
  end
1119
- rescue SignalException
1120
- log_end(-1)
2874
+ else
2875
+ say "Could not download image", Thor::Shell::Color::RED
2876
+ log_end(1, "Could build image")
2877
+ return false
1121
2878
 
1122
- say "Couldn't upload image file for: #{image_name}", Thor::Shell::Color::RED
1123
- exit(1)
1124
- end
1125
2879
 
2880
+ end
1126
2881
 
1127
- end
2882
+ # else
2883
+ # path = download_image(image_name,image["slug"])
2884
+ # if path
2885
+ # image = Docker::Image.import(path)
2886
+ # image.tag('repo' => image_name, 'tag' => 'latest')
2887
+ # if not image.nil?
2888
+ # say "Finished downloading image, cleaning up..", Thor::Shell::Color::GREEN
2889
+ # FileUtils.rm(path)
2890
+ # checks = Helpers.checkmark()
2891
+ # say "#{checks} Done", Thor::Shell::Color::GREEN
2892
+ # log_end(0)
2893
+ # return image
2894
+ # log_end(0)
2895
+ # else
2896
+ # say "Could not download image", Thor::Shell::Color::RED
2897
+ # return false
2898
+ # end
2899
+ #
2900
+ # end
2901
+ # end
2902
+ rescue
2903
+ say "Couldn't build image", Thor::Shell::Color::RED
1128
2904
 
1129
- desc 'download_image', 'commit notebook changes to create a new notebook image'
2905
+ rescue SignalException
2906
+ say "\nAborting"
2907
+ log_end(-1)
2908
+ exit(1)
2909
+ ensure
2910
+ if path
2911
+ FileUtils.rm_rf(path)
1130
2912
 
1131
- def download_image(image_name)
1132
- begin
1133
- verify_logged_in(false)
1134
- log_start(__method__,args,options)
1135
- owner = Cnvrg::CLI.get_owner()
2913
+ end
2914
+ end
1136
2915
 
1137
- notebooks_res = Cnvrg::API.request("users/#{owner}/images/" + "find", 'POST', {image_name: image_name})
1138
2916
 
1139
- if Cnvrg::CLI.is_response_success(notebooks_res)
2917
+ end
1140
2918
 
1141
- images = notebooks_res["result"]["images"]
1142
- if images.empty?
1143
- say "Couldn't find any image with name: #{image_name}", Thor::Shell::Color::RED
1144
- exit(1)
1145
- elsif images.size == 1
1146
- image_id = images[0]["slug"]
1147
- else
1148
- printf "%-20s %-20s %-30s %-20s\n", "name", "version", "last updated", "created by"
1149
- images.each_with_index do |u, i|
1150
- time = Time.parse(u["updated_at"])
1151
- update_at = get_local_time(time)
1152
- version = u["version"] || "v1"
1153
- created_by = u["image_file_name"][/^[^\_]*/]
1154
- printf "%-20s %-20s %-30s %-20s\n", u["name"], version, update_at, created_by
1155
- end
1156
- choice = ask("Which version to download for #{image_name}?")
1157
- images.each do |u|
1158
- if u["version"] == choice
1159
- image_id = u["slug"]
1160
- end
2919
+ desc 'set_image', 'set image to a porject'
1161
2920
 
1162
- end
2921
+ def set_image(docker_image)
2922
+ verify_logged_in(true)
2923
+ log_start(__method__, args, options)
2924
+ working_dir = is_cnvrg_dir
2925
+ project = Project.new(working_dir)
1163
2926
 
1164
- end
1165
- end
1166
- path = Dir.pwd+"/#{image_name}.tar.gz"
1167
- @files = Cnvrg::Files.new(owner, "")
2927
+ local_images = Docker::Image.all
2928
+ docker_image_local = local_images.map { |x| x.info["RepoTags"] }.flatten.select { |y| y.include? docker_image }.flatten
2929
+ if docker_image_local.size == 0
1168
2930
 
1169
- say "Downloading image file", Thor::Shell::Color::BLUE
1170
- begin
1171
- image_path = @files.download_image(path, image_id, owner)
1172
- return image_path
1173
- # if res
1174
- # checks = Helpers.checkmark()
1175
- # say "#{checks} Done", Thor::Shell::Color::GREEN
1176
- # log_end(0)
1177
- # return true
1178
- # else
1179
- # say "Couldn't download image #{image_name}", Thor::Shell::Color::RED
1180
- # log_end(1,"can't download image")
1181
- # return false
1182
- # end
1183
- rescue Interrupt
1184
- log_end(-1)
1185
- say "The user has exited to process, aborting", Thor::Shell::Color::BLUE
2931
+ if yes? "Image wasn't found locally, pull image from cnvrg repository?", Thor::Shell::Color::YELLOW
2932
+ image = pull_image(docker_image)
2933
+ if image
2934
+ say "downloaded image: #{docker_image}"
2935
+ @image = Images.new(working_dir, docker_image)
2936
+ else
2937
+ say "Could not create a new project with docker, image was not found", Thor::Shell::Color::RED
1186
2938
  exit(1)
1187
2939
  end
1188
- rescue SignalException
1189
- log_end(-1)
1190
- say "/nAborting"
2940
+ else
2941
+ say "Could not create a new project with docker, image was not found", Thor::Shell::Color::RED
1191
2942
  exit(1)
2943
+
1192
2944
  end
2945
+ elsif docker_image_local.size == 1
2946
+ say "found image: #{docker_image_local[0]}, setting it up..", Thor::Shell::Color::BLUE
2947
+ @image = Images.new(working_dir, docker_image_local[0])
2948
+ elsif docker_image_local.size >1
2949
+ say "found #{docker_image_local.size} images, choose the image name you want to use", Thor::Shell::Color::BLUE
2950
+ image_name = ask "#{docker_image_local.join("\n")}\n", Thor::Shell::Color::BLUE
2951
+ image_name = image_name.strip
2952
+ @image = Images.new(working_dir, image_name)
1193
2953
  end
2954
+ @image.update_image_activity(project.last_local_commit, nil)
2955
+ end
1194
2956
 
1195
2957
 
1196
- desc 'list_images', 'lists all custom images you can pull'
2958
+ no_tasks do
2959
+ def get_instance_type(instances)
2960
+ machines = instances.map { |x| x }.select { |y| y[1] }
2961
+ if machines.size == 1
2962
+ instance_type = machines[0][0]
2963
+ elsif machines.size > 1
1197
2964
 
1198
- def list_images
1199
- begin
1200
- verify_logged_in(false)
1201
- log_start(__method__,args,options)
1202
- owner = Cnvrg::CLI.get_owner()
1203
- res = Cnvrg::API.request("users/#{owner}/images/list", 'GET')
1204
- if Cnvrg::CLI.is_response_success(res)
1205
- printf "%-20s %-20s %-30s %-20s\n", "name", "version", "last updated", "created by"
1206
- res["result"]["images"].each do |u|
1207
- time = Time.parse(u["updated_at"])
1208
- update_at = get_local_time(time)
1209
- version = u["version"] || "v1"
1210
- created_by = u["image_file_name"][/^[^\_]*/]
2965
+ values = instances.map { |x| x[0] }
2966
+ machines_str = "#{machines.map { |x| " " +x[0] }.flatten.join(" or")}"
1211
2967
 
1212
- printf "%-20s %-20s %-30s %-20s\n", u["name"], version, update_at, created_by
2968
+ instance_type = ask ("You can't choose more than 1 machine,either:#{machines_str}")
2969
+ instance_type = values.select { |x| x.eql? instance_type }
2970
+ if instance_type.empty?
2971
+ instance_type = nil
2972
+ else
2973
+ instance_type = instance_type[0]
1213
2974
  end
2975
+ else
2976
+ instance_type = nil
1214
2977
  end
1215
- log_end(0)
1216
- return res["result"]["images"]
1217
- rescue SignalException
1218
- log_end(-1)
1219
- say "/nAborting"
1220
- exit(1)
1221
- end
2978
+ return instance_type
2979
+ end
1222
2980
 
2981
+ def get_image(dir)
2982
+ project_dir = is_cnvrg_dir(dir)
2983
+ if !project_dir
2984
+ return false
2985
+ else
2986
+ project_config = YAML.load_file(project_dir+"/.cnvrg/config.yml")
2987
+ if project_config.to_h[:docker]
2988
+ project_config.to_h[:image_base]
2989
+ else
2990
+ false
2991
+ end
2992
+ end
1223
2993
 
1224
2994
  end
1225
2995
 
2996
+ def set_owner(owner, username, url)
2997
+ home_dir = File.expand_path('~')
1226
2998
 
1227
- desc 'pull_image', 'downloads and loads a custom image'
1228
- def pull_image(image_name)
1229
2999
  begin
1230
- verify_logged_in(false)
1231
- log_start(__method__,args,options)
1232
-
1233
- path = download_image(image_name)
1234
- if path
1235
- image = Docker::Image.import(path)
1236
- if not image.nil?
1237
- return image
1238
- log_end(0)
1239
- else
1240
- say "Could not download image", Thor::Shell::Color::RED
1241
- log_end(1,loadRes)
1242
- retunr false
1243
- end
1244
-
3000
+ if !File.directory? home_dir+"/.cnvrg"
3001
+ FileUtils.mkdir_p([home_dir+"/.cnvrg", home_dir+"/.cnvrg/tmp"])
1245
3002
  end
1246
- rescue SignalException
1247
- say "\nAborting"
1248
- log_end(-1)
1249
- exit(1)
3003
+ if !File.exist?(home_dir+"/.cnvrg/config.yml")
3004
+ FileUtils.touch [home_dir+"/.cnvrg/config.yml"]
3005
+ end
3006
+ if url.nil? or url.empty?
3007
+ url = "https://cnvrg.io/api"
3008
+ end
3009
+ config = {owner: owner, username: username, version_last_check: get_start_day(), api: url}
3010
+
3011
+ File.open(home_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
3012
+ return true
3013
+ rescue
3014
+ return false
1250
3015
  end
1251
3016
 
1252
3017
  end
1253
3018
 
1254
- no_tasks do
1255
- def get_container_id
1256
- docker_path = verify_software_installed("docker")
3019
+ def get_start_day
3020
+ time = Time.now
3021
+ return Time.new(time.year, time.month, time.day)
3022
+ end
1257
3023
 
1258
- container_id = `#{docker_path} ps --quiet --last=1 --filter status=running`.strip!
1259
- if container_id.empty?
1260
- say "Couldn't find a running notebook server, execute run_notebook", Thor::Shell::Color::RED
1261
- exit(1)
1262
- end
1263
- return container_id
3024
+ def calc_output_time(upload_output)
3025
+ if upload_output.nil? or upload_output.empty?
3026
+ return 0
3027
+ end
3028
+ time = upload_output.split(/(\d+)/).reject(&:empty?).map { |x| x.strip }
3029
+ if time.size!=2
3030
+ upload_output = ask("upload_output should be {number}{s/m/h/d} i.e. 5m (5 minutes), 1h (1 hour)\nre-enter value for upload_output")
3031
+ return calc_output_time(upload_output)
3032
+ end
3033
+ if time[0] == "0"
3034
+ return -1
3035
+ end
3036
+ case time[1].downcase
3037
+ when "s"
3038
+ return time[0].to_f
3039
+ when "m"
3040
+ return time[0].to_f*60
3041
+ when "h"
3042
+ return time[0].to_f*3600
3043
+ when "d"
3044
+ return time[0].to_f*24*3600
3045
+ else
3046
+ upload_output = ask("upload_output should be {number}{s/m/h/d} i.e. 5m (5 minutes), 1h (1 hour)\n re-enter value for upload_output")
3047
+ calc_output_time(upload_output)
1264
3048
  end
1265
3049
 
1266
- def set_owner(owner, username)
1267
- home_dir = File.expand_path('~')
1268
-
1269
- begin
1270
- if !File.directory? home_dir+"/.cnvrg"
1271
- FileUtils.mkdir_p([home_dir+"/.cnvrg", home_dir+"/.cnvrg/tmp"])
1272
- end
1273
- if !File.exist?(home_dir+"/.cnvrg/config.yml")
1274
- FileUtils.touch [home_dir+"/.cnvrg/config.yml"]
1275
- end
1276
- config = YAML.load_file(home_dir+"/.cnvrg/config.yml")
1277
- if !config or config.empty?
1278
- config = {owner: owner, username: username, version_last_check: get_start_day(), api: "https://cnvrg.io/api"}
1279
- else
1280
- config = {owner: owner, username: username, version_last_check: get_start_day(), api: config.to_h[:api]}
1281
- end
1282
-
1283
- File.open(home_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
1284
- return true
1285
- rescue
1286
- return false
1287
- end
3050
+ end
1288
3051
 
3052
+ def log_start(command, args="", options={})
3053
+ begin
3054
+ $LOG.info "----"
3055
+ $LOG.info ruby_version: RUBY_VERSION, os: Cnvrg::Helpers.os(), cli_version: Cnvrg::VERSION
3056
+ $LOG.info command: command, args: args, options: options
3057
+ rescue
1289
3058
  end
3059
+ end
1290
3060
 
1291
- def get_start_day
1292
- time = Time.now
1293
- return Time.new(time.year, time.month, time.day)
3061
+ def log_end(exit_status=0, error=nil)
3062
+ begin
3063
+ if exit_status==1
3064
+ $LOG.error exit_status: exit_status, error: error
3065
+ else
3066
+ $LOG.info exit_status: exit_status
3067
+ end
3068
+ rescue
1294
3069
  end
3070
+ end
1295
3071
 
1296
- def calc_output_time(upload_output)
1297
- if upload_output.nil? or upload_output.empty?
1298
- return 0
1299
- end
1300
- time = upload_output.split(/(\d+)/).reject(&:empty?).map { |x| x.strip }
1301
- if time.size!=2
1302
- upload_output = ask("upload_output should be {number}{s/m/h/d} i.e. 5m (5 minutes), 1h (1 hour)\nre-enter value for upload_output")
1303
- return calc_output_time(upload_output)
1304
- end
1305
- if time[0] == "0"
1306
- return -1
3072
+ def self.is_response_success(response, should_exit=true)
3073
+ if response.nil?
3074
+ if !Cnvrg::Helpers.internet_connection?
3075
+ # Cnvrg::CLI.log_end(1,"no internet connection")
3076
+ say("<%= color('Error:You seems to be offline', RED) %>")
3077
+ else
3078
+ say("<%= color('Error', RED) %>")
1307
3079
  end
1308
- case time[1].downcase
1309
- when "s"
1310
- return time[0].to_f
1311
- when "m"
1312
- return time[0].to_f*60
1313
- when "h"
1314
- return time[0].to_f*3600
1315
- when "d"
1316
- return time[0].to_f*24*3600
1317
- else
1318
- upload_output = ask("upload_output should be {number}{s/m/h/d} i.e. 5m (5 minutes), 1h (1 hour)\n re-enter value for upload_output")
1319
- calc_output_time(upload_output)
3080
+ elsif response["status"]!= 200
3081
+ error = response['message']
3082
+ # Cnvrg::CLI.log_end(1, error)
3083
+ if response["status"] == 500
3084
+ say("<%= color('Server Error', RED) %>")
3085
+ else
3086
+ say("<%= color('Error:#{error}', RED) %>")
1320
3087
  end
1321
3088
 
1322
- end
1323
- def log_start(command,args="", options={})
1324
- begin
1325
- $LOG.info "----"
1326
- $LOG.info ruby_version: RUBY_VERSION, os: Cnvrg::Helpers.os(), cli_version:Cnvrg::VERSION
1327
- $LOG.info command:command,args:args,options:options
1328
- rescue
1329
- end
1330
- end
1331
- def log_end(exit_status=0, error=nil)
1332
- begin
1333
- if exit_status==1
1334
- $LOG.error exit_status:exit_status, error:error
1335
- else
1336
- $LOG.info exit_status:exit_status
1337
- end
1338
- rescue
3089
+ if should_exit
3090
+ exit(1)
3091
+ else
3092
+ return false
1339
3093
  end
1340
3094
  end
3095
+ return true
3096
+ end
1341
3097
 
1342
- def self.is_response_success(response, should_exit=true)
1343
- if response.nil?
1344
- if !Cnvrg::Helpers.internet_connection?
1345
- # Cnvrg::CLI.log_end(1,"no internet connection")
1346
- say("<%= color('Error:You seems to be offline', RED) %>")
1347
- else
1348
- say("<%= color('Error', RED) %>")
1349
- end
1350
- elsif response["status"]!= 200
1351
- error = response['message']
1352
- # Cnvrg::CLI.log_end(1, error)
1353
- if response["status"] == 500
1354
- say("<%= color('Server Error', RED) %>")
1355
- else
1356
- say("<%= color('Error:#{error}', RED) %>")
1357
- end
3098
+ def self.get_owner
3099
+ home_dir = File.expand_path('~')
1358
3100
 
1359
- if should_exit
1360
- exit(1)
1361
- else
1362
- return false
1363
- end
1364
- end
1365
- return true
3101
+ config = YAML.load_file(home_dir+ "/.cnvrg/config.yml")
3102
+ owner = config.to_h[:owner]
3103
+ if owner.empty?
3104
+ invoke :set_default_owner, [], []
3105
+ return get_owner()
3106
+ else
3107
+ return owner
1366
3108
  end
3109
+ end
3110
+ def get_base_url
3111
+ home_dir = File.expand_path('~')
1367
3112
 
1368
- def self.get_owner
1369
- home_dir = File.expand_path('~')
1370
-
1371
- config = YAML.load_file(home_dir+ "/.cnvrg/config.yml")
1372
- owner = config.to_h[:owner]
1373
- if owner.empty?
1374
- invoke :set_default_owner
1375
- return get_owner()
1376
- else
1377
- return owner
1378
- end
1379
- end
3113
+ config = YAML.load_file(home_dir+ "/.cnvrg/config.yml")
3114
+ api = config.to_h[:api]
3115
+ return api.gsub!("/api","")
3116
+ end
1380
3117
 
1381
- def get_project_home
1382
- absolute_path = Dir.pwd
1383
- dirs = absolute_path.split("/")
1384
- dirs.pop while not Dir.exists?("#{dirs.join("/")}/.cnvrg") and dirs.size != 0
3118
+ def get_project_home
3119
+ absolute_path = Dir.pwd
3120
+ dirs = absolute_path.split("/")
3121
+ dirs.pop while not Dir.exists?("#{dirs.join("/")}/.cnvrg") and dirs.size != 0
1385
3122
 
1386
- if dirs.size == 0
1387
- say "Couldn't find cnvrg directory. Please start a new project", Thor::Shell::Color::RED
1388
- exit(1)
1389
- end
1390
- return dirs.join("/")
3123
+ if dirs.size == 0
3124
+ say "Couldn't find cnvrg directory. Please start a new project", Thor::Shell::Color::RED
3125
+ exit(1)
1391
3126
  end
3127
+ return dirs.join("/")
3128
+ end
1392
3129
 
1393
- def should_update_version
1394
- res = Cnvrg::API.request("/cli/version", 'GET')
1395
- if Cnvrg::CLI.is_response_success(res, false)
1396
- updated_version = res["result"]["version"]
1397
- if updated_version != Cnvrg::VERSION
1398
- return true
1399
- else
1400
- return false
1401
- end
3130
+ def should_update_version
3131
+ res = Cnvrg::API.request("/cli/version", 'GET')
3132
+ if Cnvrg::CLI.is_response_success(res, false)
3133
+ updated_version = res["result"]["version"]
3134
+ if updated_version != Cnvrg::VERSION
3135
+ return true
1402
3136
  else
1403
3137
  return false
1404
3138
  end
3139
+ else
3140
+ return false
1405
3141
  end
1406
- def log_handler
1407
- begin
3142
+ end
3143
+
3144
+ def log_handler
3145
+ begin
1408
3146
  date = DateTime.now.strftime("%m_%d_%Y")
1409
3147
  logfile = File.expand_path('~') +"/.cnvrg/log_#{date}.log"
1410
3148
  if !File.exist? logfile
@@ -1421,63 +3159,83 @@ module Cnvrg
1421
3159
  count+=1
1422
3160
  end
1423
3161
  @files = Cnvrg::Files.new(Cnvrg::CLI.get_owner, "")
1424
- @files.upload_log_file(logfile_old,"log_#{date}.log",yesterday)
3162
+ @files.upload_log_file(logfile_old, "log_#{date}.log", yesterday)
1425
3163
  FileUtils.remove logfile_old
1426
3164
 
1427
3165
 
1428
3166
  end
1429
- $LOG = LogStashLogger.new(type: :file, path: logfile, sync: true)
1430
- rescue => e
1431
- # puts e
1432
- end
3167
+ $LOG = LogStashLogger.new(type: :file, path: logfile, sync: true)
3168
+ rescue => e
3169
+ # puts e
1433
3170
  end
3171
+ end
1434
3172
 
1435
3173
 
3174
+ def verify_logged_in(in_dir=true)
3175
+ log_handler()
3176
+ auth = Cnvrg::Auth.new
3177
+ unless auth.is_logged_in?
3178
+ say 'You\'re not logged in', Thor::Shell::Color::RED
3179
+ say 'Please log in via `cnvrg login`', Thor::Shell::Color::BLUE
3180
+ exit(1)
3181
+ end
1436
3182
 
1437
- def verify_logged_in(in_dir=true)
1438
- log_handler()
1439
- auth = Cnvrg::Auth.new
1440
- unless auth.is_logged_in?
1441
- say 'You\'re not logged in', Thor::Shell::Color::RED
1442
- say 'Please log in via `cnvrg login`', Thor::Shell::Color::YELLOW
1443
- exit(1)
1444
- end
1445
-
1446
- if !Helpers.internet_connection?
1447
- wait_offline = agree "Seems like you're offline, wait until your' back online?",limited_to: ['y', 'n'], default: 'n'
1448
- if wait_offline
1449
- say "Waiting until your'e online..", Thor::Shell::Color::BLUE
1450
- while !Cnvrg::Helpers.internet_connection?
1451
- end
1452
- else
1453
- say "you seem to be offline, please check your internet connection", Thor::Shell::Color::RED
1454
- exit(0)
1455
- end
3183
+ if !Helpers.internet_connection?
3184
+ wait_offline = agree "Seems like you're offline, wait until your'e back online?", Thor::Shell::Color::YELLOW
3185
+ if wait_offline
3186
+ say "Waiting until your'e online..", Thor::Shell::Color::BLUE
3187
+ while !Cnvrg::Helpers.internet_connection?
3188
+ end
3189
+ else
3190
+ say "you seem to be offline, please check your internet connection", Thor::Shell::Color::RED
3191
+ exit(0)
1456
3192
  end
3193
+ end
1457
3194
 
1458
- config = YAML.load_file(File.expand_path('~')+"/.cnvrg/config.yml")
1459
- version_date = config.to_h[:version_last_check]
1460
- next_day = get_start_day+ 86399
1461
- if not (version_date..next_day).cover?(Time.now)
1462
- if should_update_version()
1463
- say "There is a new version, run gem update cnvrg", Thor::Shell::Color::BLUE
1464
- end
3195
+ config = YAML.load_file(File.expand_path('~')+"/.cnvrg/config.yml")
3196
+ version_date = config.to_h[:version_last_check]
3197
+ next_day = get_start_day+ 86399
3198
+ if not (version_date..next_day).cover?(Time.now)
3199
+ if should_update_version()
3200
+ say "There is a new version, run gem update cnvrg", Thor::Shell::Color::BLUE
1465
3201
  end
3202
+ end
1466
3203
  if in_dir
1467
- current_dir = Dir.pwd
1468
- if not Dir.exist? current_dir+"/.cnvrg"
1469
- say "You're not in a cnvrg project directory",Thor::Shell::Color::RED
3204
+ is_cnvrg = is_cnvrg_dir
3205
+ if !is_cnvrg
3206
+ say "You're not in a cnvrg project directory", Thor::Shell::Color::RED
1470
3207
  exit(0)
1471
-
1472
3208
  end
3209
+
1473
3210
  end
3211
+ #verify tmp dirs exist
3212
+ home_dir = File.expand_path('~')
3213
+
3214
+ FileUtils.mkdir_p([home_dir+"/.cnvrg", home_dir+"/.cnvrg/tmp", home_dir+"/.cnvrg/tmp_files"])
1474
3215
 
1475
3216
 
3217
+ end
1476
3218
 
3219
+ def is_cnvrg_dir(dir=Dir.pwd)
3220
+ current_dir = dir
3221
+ home_dir = File.expand_path('~')
3222
+ is_cnvrg = Dir.exist? current_dir+"/.cnvrg"
3223
+ until is_cnvrg == true
3224
+ current_dir = File.expand_path("..", current_dir)
3225
+ is_cnvrg = Dir.exist? current_dir+"/.cnvrg"
3226
+ if File.expand_path("..", current_dir).eql? home_dir
3227
+ break
3228
+ end
1477
3229
  end
3230
+ if is_cnvrg
3231
+ return current_dir
3232
+ else
3233
+ return false
3234
+ end
3235
+ end
1478
3236
 
1479
- def verify_software_installed(software)
1480
- begin
3237
+ def verify_software_installed(software)
3238
+ begin
1481
3239
  install_url = Cnvrg::CLI::INSTALLATION_URLS[software.to_sym]
1482
3240
  installed = `which #{software}`
1483
3241
  if installed.empty? or installed.nil?
@@ -1496,29 +3254,164 @@ module Cnvrg
1496
3254
  #TODO: change here
1497
3255
  say "docker isn't running. run:\ndocker-machine start default 2>/dev/null & eval `docker-machine env default`", Thor::Shell::Color::BLUE
1498
3256
  exit(1)
1499
- end
3257
+ end
1500
3258
  end
1501
3259
  end
1502
3260
 
1503
- return installed
1504
- rescue
1505
- exit(1)
3261
+ return true
3262
+ rescue
3263
+ exit(1)
3264
+ end
3265
+
3266
+ end
3267
+
3268
+ def get_local_time(time_to_update)
3269
+ local = Time.now.localtime
3270
+ gmt_offset = local.gmt_offset
3271
+ new_time =time_to_update +gmt_offset
3272
+ return new_time.to_s.gsub("UTC", "")
3273
+
3274
+ end
3275
+
3276
+
3277
+ def is_project_with_docker(dir)
3278
+ project_dir = is_cnvrg_dir(dir)
3279
+ if !project_dir
3280
+ return false
3281
+ else
3282
+ project_config = YAML.load_file(project_dir+"/.cnvrg/config.yml")
3283
+ if project_config.to_h[:docker]
3284
+ image = Images.new(project_dir)
3285
+ return image
3286
+ else
3287
+ false
3288
+ end
3289
+ end
3290
+
3291
+
3292
+ end
3293
+
3294
+ def machine_options(aws_options)
3295
+ begin
3296
+ say "Choose type of machine:", Thor::Shell::Color::BLUE
3297
+ printf "%-20s %-20s %-30s\n", "type", "details", "options"
3298
+ all_options = []
3299
+ aws_options.each do |a|
3300
+ all_options << a["options"].flatten
3301
+ options = a["options"].join(" ")
3302
+ printf "%-20s %-20s %-30s\n", a["type"], a["details"], options
3303
+ end
3304
+ all_options.flatten!
3305
+ instance_type = ask "which type of machine?", Thor::Shell::Color::YELLOW
3306
+ count = 0
3307
+ while !all_options.include? instance_type and count <4
3308
+ say "Couldn't find #{instance_type}", Thor::Shell::Color::RED
3309
+ instance_type = ask "which type of machine?", Thor::Shell::Color::YELLOW
3310
+ count+=1
1506
3311
  end
3312
+ return instance_type
3313
+ rescue
3314
+ return false
3315
+ rescue SignalException
3316
+ say "\nAborting"
3317
+ Exit(0)
3318
+ end
3319
+
1507
3320
 
3321
+ end
3322
+
3323
+ def container_changes(dir)
3324
+ container_id = is_project_with_docker(dir)
3325
+ if not container_id
3326
+ return false
1508
3327
  end
3328
+ container = Docker::Container.get(container_id)
3329
+ command = ['/bin/bash', '-lc', '/opt/ds/bin/pip freeze']
3330
+ pip = container.exec(command, tty: true)[0]
3331
+ command = ["/bin/bash", "-lc", "dpkg -l"]
3332
+ dpkg = container.exec(command, tty: true)[0]
3333
+ command = ["/bin/bash", "-lc", "cat /home/ds/.bash_history"]
3334
+ history = container.exec(command, tty: true)[0]
3335
+ diff = [pip, dpkg, history]
3336
+ return diff
3337
+ # File.open(dir+"/.cnvrg/pip_#{date}.txt", "w+") { |f| f.write pip }
3338
+ # File.open(dir+"/.cnvrg/dpkg_#{date}.txt", "w+") { |f| f.write dpkg }
3339
+ # File.open(dir+"/.cnvrg/history_#{date}.txt", "w+") { |f| f.write history }
3340
+ #
3341
+ # pip_new = pip[0].split("\r\n")
3342
+ # pip_base_file =JSON.parse(File.open( dir+"/.cnvrg/pip_base.txt","rb").read)
3343
+ # pip_base = pip_base_file[0].split("\r\n")
3344
+ #
3345
+ # pip_diff = pip_new - pip_base
3346
+ # if pip_diff.empty?
3347
+ # puts "pip is same"
3348
+ # else
3349
+ # puts pip_diff
3350
+ # end
3351
+ # dpkg_new = dpkg[0].split("\r\n")
3352
+ # dpkg_base_file =JSON.parse(File.open( dir+"/.cnvrg/dpkg_base.txt","rb").read)
3353
+ # dpkg_base = dpkg_base_file[0].split("\r\n")
3354
+ #
3355
+ # dpkg_diff = dpkg_new - dpkg_base
3356
+ # if dpkg_diff.empty?
3357
+ # puts "dpkg is same"
3358
+ # else
3359
+ # puts dpkg_diff
3360
+ # end
3361
+ # puts history
3362
+ end
1509
3363
 
1510
- def get_local_time(time_to_update)
1511
- local = Time.now.localtime
1512
- gmt_offset = local.gmt_offset
1513
- new_time =time_to_update +gmt_offset
1514
- return new_time.to_s.gsub("UTC", "")
3364
+ def is_port_taken(ip=Cnvrg::CLI::IP, port=Cnvrg::CLI::PORT, seconds=1)
3365
+ Timeout::timeout(seconds) do
3366
+ begin
3367
+ TCPSocket.new(ip, port).close
3368
+ true
3369
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
3370
+ false
3371
+ end
3372
+ end
3373
+ rescue Timeout::Error
3374
+ false
3375
+ end
3376
+
3377
+ def image_activity(image)
3378
+ res = image.handle_image_activity()
3379
+ if res == -1
3380
+ #image is not known
3381
+ say "Images #{image.image_name} is not known", Thor::Shell::Color::YELLOW
3382
+ to_sync = yes? "Sync image?", Thor::Shell::Color::YELLOW
3383
+ if to_sync
3384
+ sync_image()
3385
+ res = image.handle_image_activity()
3386
+ return res
3387
+ else
3388
+ return false
3389
+ end
1515
3390
 
1516
3391
  end
3392
+ return res
3393
+
3394
+ end
1517
3395
 
3396
+ def get_note_url(working_dir)
3397
+ config = YAML.load_file(working_dir+"/.cnvrg/config.yml")
3398
+ return config[:notebook_slug]
1518
3399
 
1519
3400
  end
1520
- end
1521
3401
 
3402
+ def get_schedule_date()
3403
+
3404
+ local = Time.now.localtime
3405
+ # gmt_offset = local.gmt_offset
3406
+ new_time =(local).to_s
3407
+ new_time = new_time[0, new_time.size-6] #remove timezone
3408
+ return new_time
3409
+
3410
+ end
1522
3411
 
1523
3412
 
3413
+ end
3414
+ end
1524
3415
  end
3416
+
3417
+