cnvrg 0.0.11 → 0.0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|
+
|