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