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