cnvrg 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d03fefa80d9bf903d426a4881be28f77bcc4d97a
4
- data.tar.gz: eb27c1b447f2cb7da15157676e9e1f458f4fa9de
3
+ metadata.gz: e6d6742b8d329e83b4eba3acbc60dc05bd2a881d
4
+ data.tar.gz: a20f65edcc1666973f12d7d8f24c4e7837cea0ae
5
5
  SHA512:
6
- metadata.gz: c01b9e13f6e99323da1fec7b9430c8c6c628fabe55cd2bc257a4f1ad11f902091e65b719cf72af810353316078bae5aef4f373199298d5e23603b4789f4b2339
7
- data.tar.gz: 192c3cba43713c61b1592ceb36975390e79162a42833a0e0cfb227329cb73ce0c1f0954f05bd9186727baf0a8143a7036823ceab890352efae9938fa03363cf9
6
+ metadata.gz: b1eb7c4e30a407596bbce0c8e86094a76ad417a7f8bc4003c1d4f72d6eb03c4ae8bc5bb7bb1f9baf88b2a2f31d4971a90afa67b73ee2a91e7190549805664ad0
7
+ data.tar.gz: 74415b8949fc00dd752add66aa441359716e23004ad4decb3fff796e994ef309a1028a0cedd7b073fa0616f307a917344433185df9f4a7828ce233867fc17f85
data/cnvrg.gemspec CHANGED
@@ -23,12 +23,17 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency 'rspec', '~> 3.0'
24
24
  spec.add_development_dependency 'vcr', '~> 3.0'
25
25
  spec.add_development_dependency 'aruba'
26
-
26
+ spec.add_development_dependency 'pry'
27
+
27
28
  spec.add_runtime_dependency 'mimemagic', '~> 0.3.1','>=0.3.2'
28
29
  spec.add_runtime_dependency 'faraday', '~> 0.10.0'
29
30
  spec.add_runtime_dependency 'netrc', '~> 0.11.0'
30
31
  spec.add_runtime_dependency 'open4', '~> 1.3', '>= 1.3.4'
31
32
  spec.add_runtime_dependency 'highline', '~> 1.7', '>= 1.7.8'
32
33
  spec.add_runtime_dependency 'thor', '~> 0.19.0','>=0.19.1'
34
+ spec.add_runtime_dependency 'aws-sdk'
35
+ spec.add_runtime_dependency 'urlcrypt', '~> 0.1.1'
36
+ spec.add_runtime_dependency 'terminal-table'
37
+
33
38
  end
34
39
 
data/lib/cnvrg/api.rb CHANGED
@@ -7,11 +7,17 @@ require 'cnvrg/helpers'
7
7
  module Cnvrg
8
8
  class API
9
9
  USER_AGENT = "CnvrgCLI/#{Cnvrg::VERSION}"
10
- # ENDPOINT = 'http://localhost:3000/api'
11
- ENDPOINT = 'https://cnvrg.io/api'
12
10
  ENDPOINT_VERSION = 'v1'
13
- URL = "#{ENDPOINT}/#{ENDPOINT_VERSION}"
14
11
 
12
+ def self.get_api
13
+ home_dir = File.expand_path('~')
14
+ config = YAML.load_file(home_dir+"/.cnvrg/config.yml")
15
+ if config.empty? or config.to_h[:api].nil?
16
+ return "https://cnvrg.io/api"
17
+ else
18
+ return config.to_h[:api]
19
+ end
20
+ end
15
21
  def self.request(resource, method = 'GET', data = {}, parse_request = true)
16
22
  begin
17
23
  n = Netrc.read
@@ -65,7 +71,7 @@ module Cnvrg
65
71
  # what if windows?
66
72
  # data[:file] = Faraday::UploadIO.new(data[:absolute_path], content_type)
67
73
  file_base = File.basename(data[:relative_path])
68
- temp_path = ".cnvrg/#{file_base}"
74
+ temp_path = File.expand_path('~')+"/.cnvrg/tmp/#{file_base}"
69
75
  FileUtils.touch(temp_path)
70
76
  data[:file] = Faraday::UploadIO.new("#{temp_path}", "plain/text")
71
77
  response = conn.post "#{endpoint_uri}/#{resource}", data
@@ -89,7 +95,8 @@ module Cnvrg
89
95
  end
90
96
 
91
97
  def self.endpoint_uri
92
- "#{Cnvrg::API::ENDPOINT}/#{Cnvrg::API::ENDPOINT_VERSION}"
98
+ api = get_api()
99
+ return "#{api}/#{Cnvrg::API::ENDPOINT_VERSION}"
93
100
  end
94
101
 
95
102
 
data/lib/cnvrg/auth.rb CHANGED
@@ -45,7 +45,7 @@ module Cnvrg
45
45
  end
46
46
 
47
47
  def sign_in(email, password)
48
- url = API::URL
48
+ url = Cnvrg::API.endpoint_uri()
49
49
  url = URI.parse(url+ "/users/sign_in")
50
50
  http = Net::HTTP.new(url.host, url.port)
51
51
 
@@ -60,11 +60,11 @@ module Cnvrg
60
60
  response = http.request(req)
61
61
 
62
62
  result = JSON.parse(response.body)
63
- if result["status"] == 200
63
+ if Cnvrg::CLI.is_response_success(result)
64
64
  return result["result"]
65
- else
66
- return nil
67
65
  end
66
+
67
+
68
68
  end
69
69
 
70
70
 
data/lib/cnvrg/cli.rb CHANGED
@@ -19,29 +19,67 @@ require 'cnvrg/files'
19
19
  require 'cnvrg/experiment'
20
20
  require 'etc'
21
21
 
22
+
22
23
  # DEV VERSION
23
24
  #
24
25
  module Cnvrg
25
26
  class CLI < Thor
26
27
 
28
+ INSTALLATION_URLS = {docker: "https://docs.docker.com/engine/installation/", jupyter: "http://jupyter.readthedocs.io/en/latest/install.html"}
29
+
27
30
  desc 'version', 'Prints cnvrg current version'
28
31
 
29
32
  def version
33
+
30
34
  puts Cnvrg::VERSION
31
35
  end
32
36
 
33
37
  map %w(-v --version) => :version
38
+
39
+ desc 'set api url', 'set api url'
40
+
41
+ def set_api_url(url)
42
+ home_dir = File.expand_path('~')
43
+ if !url.end_with? "/api"
44
+ url = url+"/api"
45
+ end
46
+ begin
47
+ if !File.directory? home_dir+"/.cnvrg"
48
+ FileUtils.mkdir_p([home_dir+"/.cnvrg", home_dir+"/.cnvrg/tmp"])
49
+ end
50
+ if !File.exist?(home_dir+"/.cnvrg/config.yml")
51
+ FileUtils.touch [home_dir+"/.cnvrg/config.yml"]
52
+ end
53
+ config = YAML.load_file(home_dir+"/.cnvrg/config.yml")
54
+ say "Setting default api to be: #{url}", Thor::Shell::Color::BLUE
55
+ if config.empty?
56
+ config = {owner: "", username: "", version_last_check: get_start_day(), api: url}
57
+ else
58
+ config = {owner: config.to_h[:owner], username: config.to_h[:username], version_last_check: config.to_h[:version_last_check], api: url}
59
+ end
60
+ checks = Helpers.checkmark
61
+
62
+
63
+ File.open(home_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
64
+ say "#{checks} Done", Thor::Shell::Color::GREEN
65
+ rescue
66
+ say "Couldn't set default api, contact help@cnvrg.io", Thor::Shell::Color::RED
67
+ end
68
+ end
69
+
70
+ map %w(-api --api) => :set_api_url
71
+
34
72
  desc 'set default owner', 'set default owner'
35
73
 
36
74
  def set_default_owner
37
75
 
38
76
  path = File.expand_path('~')+"/.cnvrg/config.yml"
39
77
  if !File.exist?(path)
40
- say "Couldn't find ~/.cnvrg/config.yml file, please logout and login again" ,Thor::Shell::Color::RED
78
+ say "Couldn't find ~/.cnvrg/config.yml file, please logout and login again", Thor::Shell::Color::RED
41
79
 
42
80
  exit(0)
43
81
  end
44
- config = YAML.load_file(path)
82
+ config = YAML.load_file(path)
45
83
 
46
84
  username = config.to_h[:username]
47
85
  res = Cnvrg::API.request("/users/#{username}/get_possible_owners", 'GET')
@@ -66,66 +104,83 @@ module Cnvrg
66
104
  desc 'login', 'Authenticate with cnvrg.io and store credentials'
67
105
 
68
106
  def login
69
- cmd = HighLine.new
107
+ begin
108
+ cmd = HighLine.new
70
109
 
71
- say 'Authenticating with cnvrg', Thor::Shell::Color::YELLOW
110
+ say 'Authenticating with cnvrg', Thor::Shell::Color::YELLOW
72
111
 
73
- @auth = Cnvrg::Auth.new
74
- netrc = Netrc.read
75
- @email, token, owner = netrc[Cnvrg::Helpers.netrc_domain]
76
- puts owner
112
+ @auth = Cnvrg::Auth.new
113
+ netrc = Netrc.read
114
+ @email, token = netrc[Cnvrg::Helpers.netrc_domain]
77
115
 
78
- if @email and token
79
- say 'Seems you\'re already logged in', Thor::Shell::Color::BLUE
80
- exit(0)
81
- end
82
- @email = ask("Enter your Email:")
83
- password = cmd.ask("Enter your password (hidden):") { |q| q.echo = "*" }
84
- result = @auth.sign_in(@email, password)
85
- if (token = result["token"])
86
- netrc[Cnvrg::Helpers.netrc_domain] = @email, token
87
- netrc.save
116
+ if @email and token
117
+ say 'Seems you\'re already logged in', Thor::Shell::Color::BLUE
118
+ exit(0)
119
+ end
120
+ @email = ask("Enter your email:")
121
+ password = cmd.ask("Enter your password (hidden):") { |q| q.echo = "*" }
122
+ result = @auth.sign_in(@email, password)
88
123
 
89
- say "Authenticated successfully as #{@email}", Thor::Shell::Color::GREEN
90
- owners = result["owners"]
91
- choose_owner = result["username"]
124
+ if !result["token"].nil?
125
+ netrc[Cnvrg::Helpers.netrc_domain] = @email, result["token"]
126
+ netrc.save
92
127
 
93
- if owners.empty?
94
- else
95
- owners << choose_owner
96
- choose_owner = ask("Choose default owner:\n"+owners.join("\n")+"\n")
128
+ say "Authenticated successfully as #{@email}", Thor::Shell::Color::GREEN
129
+ owners = result["owners"]
130
+ choose_owner = result["username"]
131
+
132
+ if owners.empty?
133
+ else
134
+ owners << choose_owner
135
+ choose_owner = ask("Choose default owner:\n"+owners.join("\n")+"\n")
136
+
137
+ end
138
+ if set_owner(choose_owner, result["username"])
139
+ say "Setting default owner: #{choose_owner}", Thor::Shell::Color::GREEN
140
+ else
141
+ say "Setting default owenr has failed, try to run cnvrg --config-default-owner", Thor::Shell::Color::RED
142
+ end
97
143
 
98
- end
99
- if set_owner(choose_owner, result["username"])
100
- say "Setting default owner: #{choose_owner}", Thor::Shell::Color::GREEN
101
144
  else
102
- say "Setting default owenr has failed, try to run cnvrg --config-default-owner", Thor::Shell::Color::RED
145
+ say "Failed to authenticate, wrong email/password", Thor::Shell::Color::RED
146
+ exit false
103
147
  end
104
-
105
- else
106
- say "Failed to authenticate, wrong email/password", Thor::Shell::Color::RED
107
- exit false
148
+ rescue SignalException
149
+ say "/nAborting"
150
+ exit(1)
108
151
  end
109
152
  end
110
153
 
154
+
111
155
  desc 'logout', 'Logout existing user'
112
156
 
113
157
  def logout
114
- netrc = Netrc.read
115
- netrc.delete(Cnvrg::Helpers.netrc_domain)
116
- netrc.save
117
- say "Logged out successfully.\n", Thor::Shell::Color::GREEN
158
+ begin
159
+ netrc = Netrc.read
160
+ netrc.delete(Cnvrg::Helpers.netrc_domain)
161
+ netrc.save
162
+ say "Logged out successfully.\n", Thor::Shell::Color::GREEN
163
+ rescue SignalException
164
+ say "/nAborting"
165
+ exit(1)
166
+ end
167
+
118
168
  end
119
169
 
120
170
  desc 'me', 'Prints the current logged in user email'
121
171
 
122
172
  def me
123
- verify_logged_in()
124
- auth = Cnvrg::Auth.new
125
- if (email = auth.get_email)
126
- say "Logged in as: #{email}", Thor::Shell::Color::GREEN
127
- else
128
- say "You're not logged in.", Thor::Shell::Color::RED
173
+ begin
174
+ verify_logged_in()
175
+ auth = Cnvrg::Auth.new
176
+ if (email = auth.get_email)
177
+ say "Logged in as: #{email}", Thor::Shell::Color::GREEN
178
+ else
179
+ say "You're not logged in.", Thor::Shell::Color::RED
180
+ end
181
+ rescue SignalException
182
+ say "/nAborting"
183
+ exit(1)
129
184
  end
130
185
  end
131
186
 
@@ -133,613 +188,1049 @@ module Cnvrg
133
188
 
134
189
  desc 'new', 'Create a new cnvrg project'
135
190
  method_option :clean, :type => :boolean, :aliases => ["-c", "--c"], :default => false
191
+ method_option :docker_image, :type => :string, :aliases => ["-d", "--d"], :default => ""
136
192
 
137
193
  def new(project_name)
138
- verify_logged_in()
139
- clean = options["clean"]
140
- say "Creating #{project_name}", Thor::Shell::Color::BLUE
141
- if Dir.exists? project_name or File.exists? project_name
142
- say "Conflict with dir/file #{project_name}", Thor::Shell::Color::RED
143
- exit(1)
144
- end
145
-
146
- if Project.create(project_name, clean)
147
- path = Dir.pwd + "/" + project_name
148
- @project = Project.new(path)
149
- @project.generate_idx
150
- else
151
- say "Error creating project, please contact support.", Thor::Shell::Color::RED
152
- exit(0)
153
- end
194
+ begin
195
+ verify_logged_in()
196
+ clean = options["clean"]
197
+ docker_image = options["docker_image"]
198
+ if !docker_image.nil? and !docker_image.empty?
199
+ pull_image(docker_image)
200
+ end
201
+ say "Creating #{project_name}", Thor::Shell::Color::BLUE
202
+ if Dir.exists? project_name or File.exists? project_name
203
+ say "Conflict with dir/file #{project_name}", Thor::Shell::Color::RED
204
+ exit(1)
205
+ end
154
206
 
155
- say "created\t\tproject's tree", Thor::Shell::Color::GREEN
156
- say "created\t\tproject's config", Thor::Shell::Color::GREEN
157
- say "Linked directory to\t#{@project.url}", Thor::Shell::Color::GREEN
158
- end
207
+ if Project.create(project_name, clean)
208
+ path = Dir.pwd + "/" + project_name
209
+ @project = Project.new(path)
210
+ @project.generate_idx
211
+ else
212
+ say "Error creating project, please contact support.", Thor::Shell::Color::RED
213
+ exit(0)
214
+ end
159
215
 
160
- desc 'link', 'Link current directory to a cnvrg project'
161
- method_option :sync, :type => :boolean, :aliases => ["-s", "--s"], :default => true
162
-
163
- def link
164
- verify_logged_in()
165
- sync = options["sync"]
166
- project_name =File.basename(Dir.getwd)
167
- say "Linking #{project_name}", Thor::Shell::Color::BLUE
168
- if File.directory?(Dir.getwd+"/.cnvrg")
169
- config = YAML.load_file("#{Dir.getwd}/.cnvrg/config.yml")
170
- say "Directory is already linked to #{config[:project_slug]}", Thor::Shell::Color::RED
171
- exit(0)
216
+ say "created\t\tproject's tree", Thor::Shell::Color::GREEN
217
+ say "created\t\tproject's config", Thor::Shell::Color::GREEN
218
+ say "Linked directory to\t#{@project.url}", Thor::Shell::Color::GREEN
219
+ rescue SignalException
220
+ say "/nAborting"
221
+ exit(1)
172
222
  end
173
- if Project.link(project_name)
174
- path = Dir.pwd
175
- @project = Project.new(path)
176
- @project.generate_idx()
177
- if sync
178
- upload(true)
179
- end
180
-
181
- url = @project.url
182
- say "#{project_name}'s location is: #{url}\n", Thor::Shell::Color::BLUE
183
- else
184
- say "Error linking project, please contact support.", Thor::Shell::Color::RED
185
- exit(0)
186
223
  end
187
- end
188
224
 
189
- desc 'clone', 'Clone a project'
190
-
191
- def clone(project_url)
192
- verify_logged_in()
193
- url_parts = project_url.split("/")
194
- project_index = Cnvrg::Helpers.look_for_in_path(project_url, "projects")
195
- slug = url_parts[project_index+1]
196
- owner = url_parts[project_index-1]
197
- response = Cnvrg::API.request("users/#{owner}/projects/#{slug}/get_project", 'GET')
198
- Cnvrg::CLI.is_response_success(response)
199
- response = JSON.parse response["result"]
200
- project_name = response["title"]
201
- say "Cloning #{project_name}", Thor::Shell::Color::BLUE
202
- if Dir.exists? project_name or File.exists? project_name
203
- say "Error: Conflict with dir/file #{project_name}", Thor::Shell::Color::RED
204
- exit(1)
205
- end
206
225
 
207
- if Project.clone_dir(slug, owner, project_name)
208
- project_home = Dir.pwd+"/"+project_name
209
- @project = Project.new(project_home)
210
- @files = Cnvrg::Files.new(@project.owner, slug)
211
- response = @project.clone
212
- Cnvrg::CLI.is_response_success response
213
- idx = {commit: response["result"]["commit"], tree: response["result"]["tree"]}
214
- File.open(project_name + "/.cnvrg/idx.yml", "w+") { |f| f.write idx.to_yaml }
215
- successful_changes = []
216
- say "Downloading files", Thor::Shell::Color::BLUE
217
- response["result"]["tree"].each do |f|
218
- relative_path = f[0].gsub(/^#{@project.local_path}/, "")
219
- if f[0].end_with? "/"
220
- # dir
221
- if @files.download_dir(f[0], relative_path, project_home)
222
- successful_changes << relative_path
226
+ desc 'link', 'Link current directory to a cnvrg project'
227
+ method_option :sync, :type => :boolean, :aliases => ["-s", "--s"], :default => true
228
+
229
+ def link
230
+ begin
231
+ verify_logged_in()
232
+ sync = options["sync"]
233
+ project_name =File.basename(Dir.getwd)
234
+ say "Linking #{project_name}", Thor::Shell::Color::BLUE
235
+ if File.directory?(Dir.getwd+"/.cnvrg")
236
+ config = YAML.load_file("#{Dir.getwd}/.cnvrg/config.yml")
237
+ say "Directory is already linked to #{config[:project_slug]}", Thor::Shell::Color::RED
238
+ exit(0)
239
+ end
240
+ if Project.link(project_name)
241
+ path = Dir.pwd
242
+ @project = Project.new(path)
243
+ @project.generate_idx()
244
+ if sync
245
+ upload(true)
223
246
  end
247
+
248
+ url = @project.url
249
+ say "#{project_name}'s location is: #{url}\n", Thor::Shell::Color::BLUE
224
250
  else
225
- # blob
226
- if @files.download_file(f[0], relative_path, project_home)
227
- successful_changes << relative_path
228
- end
251
+ say "Error linking project, please contact support.", Thor::Shell::Color::RED
252
+ exit(0)
229
253
  end
254
+ rescue SignalException
255
+ say "/nAborting"
256
+ exit(1)
230
257
  end
231
- say "Done.\nDownloaded total of #{successful_changes.size} files", Thor::Shell::Color::BLUE
232
- else
233
- say "Error: Couldn't create directory: #{project_name}", Thor::Shell::Color::RED
234
- exit(1)
235
258
  end
236
259
 
237
- end
260
+ desc 'clone', 'Clone a project'
238
261
 
239
- desc 'status', 'Show the working tree status'
240
-
241
- def status
242
- verify_logged_in()
243
- @project = Project.new(get_project_home)
244
- result = @project.compare_idx["result"]
245
- commit = result["commit"]
246
- result = result["tree"]
247
- say "Comparing local changes with remote version:", Thor::Shell::Color::BLUE
248
- if result["added"].empty? and result["updated_on_local"].empty? and result["updated_on_server"].empty? and result["deleted"].empty? and result["conflicts"].empty?
249
- say "Project is up to date", Thor::Shell::Color::GREEN
250
- return true
251
- end
252
- if result["added"].size > 0
253
- say "Added files:\n", Thor::Shell::Color::BLUE
254
- result["added"].each do |a|
255
- say "\t\tA:\t#{a}", Thor::Shell::Color::GREEN
256
- end
257
- end
258
-
259
- if result["deleted"].size > 0
260
- say "Deleted files:\n", Thor::Shell::Color::BLUE
261
- result["deleted"].each do |a|
262
- say "\t\tD:\t#{a}", Thor::Shell::Color::GREEN
263
- end
264
- end
265
- if result["updated_on_local"].size > 0
266
- say "Local changes:\n", Thor::Shell::Color::BLUE
267
- result["updated_on_local"].each do |a|
268
- say "\t\tM:\t#{a}", Thor::Shell::Color::GREEN
269
- end
270
- end
262
+ def clone(project_url)
263
+ begin
264
+ verify_logged_in()
265
+ url_parts = project_url.split("/")
266
+ project_index = Cnvrg::Helpers.look_for_in_path(project_url, "projects")
267
+ slug = url_parts[project_index+1]
268
+ owner = url_parts[project_index-1]
269
+ response = Cnvrg::API.request("users/#{owner}/projects/#{slug}/get_project", 'GET')
270
+ Cnvrg::CLI.is_response_success(response)
271
+ response = JSON.parse response["result"]
272
+ project_name = response["title"]
273
+ say "Cloning #{project_name}", Thor::Shell::Color::BLUE
274
+ if Dir.exists? project_name or File.exists? project_name
275
+ say "Error: Conflict with dir/file #{project_name}", Thor::Shell::Color::RED
276
+ exit(1)
277
+ end
271
278
 
272
- if result["updated_on_server"].size > 0
273
- say "Remote changes:\n", Thor::Shell::Color::BLUE
274
- result["updated_on_server"].each do |a|
275
- say "\t\tM:\t#{a}", Thor::Shell::Color::GREEN
279
+ if Project.clone_dir(slug, owner, project_name)
280
+ project_home = Dir.pwd+"/"+project_name
281
+ @project = Project.new(project_home)
282
+ @files = Cnvrg::Files.new(@project.owner, slug)
283
+ response = @project.clone
284
+ Cnvrg::CLI.is_response_success response
285
+ idx = {commit: response["result"]["commit"], tree: response["result"]["tree"]}
286
+ File.open(project_name + "/.cnvrg/idx.yml", "w+") { |f| f.write idx.to_yaml }
287
+ successful_changes = []
288
+ say "Downloading files", Thor::Shell::Color::BLUE
289
+ response["result"]["tree"].each do |f|
290
+ relative_path = f[0].gsub(/^#{@project.local_path}/, "")
291
+ if f[0].end_with? "/"
292
+ # dir
293
+ if @files.download_dir(f[0], relative_path, project_home)
294
+ successful_changes << relative_path
295
+ end
296
+ else
297
+ # blob
298
+ if @files.download_file(f[0], relative_path, project_home)
299
+ successful_changes << relative_path
300
+ end
301
+ end
302
+ end
303
+ say "Done.\nDownloaded total of #{successful_changes.size} files", Thor::Shell::Color::GREEN
304
+ else
305
+ say "Error: Couldn't create directory: #{project_name}", Thor::Shell::Color::RED
306
+ exit(1)
307
+ end
308
+ rescue SignalException
309
+ say "/nAborting"
310
+ exit(1)
276
311
  end
277
- end
278
312
 
279
- if result["conflicts"].size > 0
280
- say "Conflicted changes:\n", Thor::Shell::Color::BLUE
281
- result["conflicts"].each do |a|
282
- say "\t\tC:\t#{a}", Thor::Shell::Color::RED
283
- end
284
313
  end
285
- end
286
-
287
314
 
288
- desc 'upload', 'Upload updated files'
289
- method_option :ignore, :type => :array, :aliases => ["-i", "--i"], :desc => "ignore following files"
315
+ desc 'status', 'Show the working tree status'
316
+ def status
317
+ begin
318
+ verify_logged_in()
319
+ @project = Project.new(get_project_home)
320
+ result = @project.compare_idx["result"]
321
+ commit = result["commit"]
322
+ result = result["tree"]
323
+ say "Comparing local changes with remote version:", Thor::Shell::Color::BLUE
324
+ if result["added"].empty? and result["updated_on_local"].empty? and result["updated_on_server"].empty? and result["deleted"].empty? and result["conflicts"].empty?
325
+ say "Project is up to date", Thor::Shell::Color::GREEN
326
+ return true
327
+ end
328
+ if result["added"].size > 0
329
+ say "Added files:\n", Thor::Shell::Color::BLUE
330
+ result["added"].each do |a|
331
+ say "\t\tA:\t#{a}", Thor::Shell::Color::GREEN
332
+ end
333
+ end
290
334
 
291
- def upload(link=false, sync=false)
335
+ if result["deleted"].size > 0
336
+ say "Deleted files:\n", Thor::Shell::Color::BLUE
337
+ result["deleted"].each do |a|
338
+ say "\t\tD:\t#{a}", Thor::Shell::Color::GREEN
339
+ end
340
+ end
341
+ if result["updated_on_local"].size > 0
342
+ say "Local changes:\n", Thor::Shell::Color::BLUE
343
+ result["updated_on_local"].each do |a|
344
+ say "\t\tM:\t#{a}", Thor::Shell::Color::GREEN
345
+ end
346
+ end
292
347
 
293
- verify_logged_in()
294
- @project = Project.new(get_project_home)
348
+ if result["updated_on_server"].size > 0
349
+ say "Remote changes:\n", Thor::Shell::Color::BLUE
350
+ result["updated_on_server"].each do |a|
351
+ say "\t\tM:\t#{a}", Thor::Shell::Color::GREEN
352
+ end
353
+ end
295
354
 
296
- @files = Cnvrg::Files.new(@project.owner, @project.slug)
297
- ignore = options[:ignore] || []
298
- if !@project.update_ignore_list(ignore)
299
- say "Couldn't append new ignore files to .cnvrgignore", Thor::Shell::Color::YELLOW
300
- end
301
- result = @project.compare_idx
302
- commit = result["result"]["commit"]
303
- if !link
304
- if commit != @project.last_local_commit and !@project.last_local_commit.nil?
305
- say "Remote server has an updated version, please run `cnvrg download` first, or alternatively: `cnvrg sync`", Thor::Shell::Color::YELLOW
355
+ if result["conflicts"].size > 0
356
+ say "Conflicted changes:\n", Thor::Shell::Color::BLUE
357
+ result["conflicts"].each do |a|
358
+ say "\t\tC:\t#{a}", Thor::Shell::Color::RED
359
+ end
360
+ end
361
+ rescue SignalException
362
+ say "/nAborting"
306
363
  exit(1)
307
364
  end
308
- say "Comparing local changes with remote version:", Thor::Shell::Color::BLUE
309
- end
310
- result = result["result"]["tree"]
311
- if result["added"].empty? and result["updated_on_local"].empty? and result["deleted"].empty?
312
- say "Project is up to date", Thor::Shell::Color::GREEN
313
- return true
314
- end
315
- update_count = 0
316
- update_total = result["added"].size + result["updated_on_local"].size + result["deleted"].size
317
- successful_updates = []
318
- successful_deletions = []
319
- if update_total == 1
320
- say "Updating #{update_total} file", Thor::Shell::Color::BLUE
321
- else
322
- say "Updating #{update_total} files", Thor::Shell::Color::BLUE
323
365
  end
324
366
 
325
- # Start commit
326
367
 
327
- commit_sha1 = @files.start_commit["result"]["commit_sha1"]
368
+ desc 'upload', 'Upload updated files'
369
+ method_option :ignore, :type => :array, :aliases => ["-i", "--i"], :desc => "ignore following files"
328
370
 
329
- # upload / update
330
- begin
331
- (result["added"] + result["updated_on_local"]).each do |f|
332
- puts f
333
- relative_path = f.gsub(/^#{@project.local_path + "/"}/, "")
334
-
335
- if File.directory?(f)
336
- resDir = @files.create_dir(f, relative_path, commit_sha1)
337
- if resDir
338
- update_count += 1
339
- successful_updates<< relative_path
371
+ def upload(link=false, sync=false)
372
+
373
+ begin
374
+ verify_logged_in()
375
+ @project = Project.new(get_project_home)
376
+
377
+ @files = Cnvrg::Files.new(@project.owner, @project.slug)
378
+ ignore = options[:ignore] || []
379
+ if !@project.update_ignore_list(ignore)
380
+ say "Couldn't append new ignore files to .cnvrgignore", Thor::Shell::Color::YELLOW
381
+ end
382
+ result = @project.compare_idx
383
+ commit = result["result"]["commit"]
384
+ if !link
385
+ if commit != @project.last_local_commit and !@project.last_local_commit.nil? and !result["result"]["tree"]["updated_on_server"].empty?
386
+ say "Remote server has an updated version, please run `cnvrg download` first, or alternatively: `cnvrg sync`", Thor::Shell::Color::YELLOW
387
+ exit(1)
340
388
  end
389
+ say "Comparing local changes with remote version:", Thor::Shell::Color::BLUE
390
+ end
391
+ result = result["result"]["tree"]
392
+ if result["added"].empty? and result["updated_on_local"].empty? and result["deleted"].empty?
393
+ say "Project is up to date", Thor::Shell::Color::GREEN
394
+ return true
395
+ end
396
+ update_count = 0
397
+ update_total = result["added"].size + result["updated_on_local"].size + result["deleted"].size
398
+ successful_updates = []
399
+ successful_deletions = []
400
+ if update_total == 1
401
+ say "Updating #{update_total} file", Thor::Shell::Color::BLUE
341
402
  else
342
- res = @files.upload_file(f, relative_path, commit_sha1)
343
- if res
344
- update_count += 1
345
- successful_updates<< relative_path
403
+ say "Updating #{update_total} files", Thor::Shell::Color::BLUE
404
+ end
405
+
406
+ # Start commit
407
+
408
+ commit_sha1 = @files.start_commit["result"]["commit_sha1"]
409
+
410
+ # upload / update
411
+ begin
412
+ (result["added"] + result["updated_on_local"]).each do |f|
413
+ puts f
414
+ relative_path = f.gsub(/^#{@project.local_path + "/"}/, "")
415
+
416
+ if File.directory?(f)
417
+ resDir = @files.create_dir(f, relative_path, commit_sha1)
418
+ if resDir
419
+ update_count += 1
420
+ successful_updates<< relative_path
421
+ end
422
+ else
423
+ res = @files.upload_file(f, relative_path, commit_sha1)
424
+ if res
425
+ update_count += 1
426
+ successful_updates<< relative_path
427
+ else
428
+ @files.rollback_commit(commit_sha1)
429
+ say "Couldn't upload, Rolling Back all changes.", Thor::Shell::Color::RED
430
+ exit(0)
431
+ end
432
+ end
433
+ end
434
+
435
+ # delete
436
+ result["deleted"].each do |f|
437
+ relative_path = f.gsub(/^#{@project.local_path + "/"}/, "")
438
+ if relative_path.end_with?("/")
439
+ if @files.delete_dir(f, relative_path, commit_sha1)
440
+ update_count += 1
441
+ successful_updates<< relative_path
442
+ end
443
+ else
444
+ if @files.delete_file(f, relative_path, commit_sha1)
445
+ update_count += 1
446
+ successful_updates<< relative_path
447
+ end
448
+ end
449
+ end
450
+
451
+ rescue SignalException
452
+ @files.rollback_commit(commit_sha1)
453
+ say "User aborted, Rolling Back all changes.", Thor::Shell::Color::RED
454
+ exit(0)
455
+ rescue
456
+ @files.rollback_commit(commit_sha1)
457
+ say "Exception while trying to upload, Rolling back", Thor::Shell::Color::RED
458
+ exit(0)
459
+ end
460
+ if update_count == update_total
461
+ res = @files.end_commit(commit_sha1)
462
+ if (Cnvrg::CLI.is_response_success(res, false))
463
+ # save idx
464
+ begin
465
+ @project.update_idx_with_files_commits!((successful_deletions+successful_updates), res["result"]["commit_time"])
466
+
467
+ @project.update_idx_with_commit!(commit_sha1)
468
+ rescue
469
+ @files.rollback_commit(commit_sha1)
470
+ say "Couldn't commit updates, Rolling Back all changes.", Thor::Shell::Color::RED
471
+ exit(1)
472
+
473
+ end
474
+
475
+ say "Done", Thor::Shell::Color::BLUE
476
+ if successful_updates.size >0
477
+ say "Updated:", Thor::Shell::Color::GREEN
478
+ suc = successful_updates.map { |x| x=Helpers.checkmark() +" "+x }
479
+ say suc.join("\n"), Thor::Shell::Color::GREEN
480
+ end
481
+ if successful_deletions.size >0
482
+ say "Deleted:", Thor::Shell::Color::GREEN
483
+ del = successful_updates.map { |x| x=Helpers.checkmark() +" "+x }
484
+ say del.join("\n"), Thor::Shell::Color::GREEN
485
+ end
486
+ say "Total of #{update_count} / #{update_total} files.", Thor::Shell::Color::GREEN
346
487
  else
347
488
  @files.rollback_commit(commit_sha1)
348
- say "Couldn't upload, Rolling Back all changes.", Thor::Shell::Color::RED
349
- exit(0)
489
+ say "Error. Rolling Back all changes.", Thor::Shell::Color::RED
350
490
  end
491
+ else
492
+ @files.rollback_commit(commit_sha1)
351
493
  end
494
+ rescue SignalException
495
+ say "/nAborting"
496
+ exit(1)
352
497
  end
353
498
 
354
- # delete
355
- result["deleted"].each do |f|
356
- relative_path = f.gsub(/^#{@project.local_path + "/"}/, "")
357
- if relative_path.end_with?("/")
358
- if @files.delete_dir(f, relative_path, commit_sha1)
359
- update_count += 1
360
- successful_updates<< relative_path
361
- end
499
+ end
500
+
501
+ desc 'download', 'Download updated files'
502
+
503
+ def download
504
+ begin
505
+ verify_logged_in()
506
+ project_home = get_project_home
507
+ @project = Project.new(project_home)
508
+ @files = Cnvrg::Files.new(@project.owner, @project.slug)
509
+
510
+ res = @project.compare_idx["result"]
511
+ result = res["tree"]
512
+ commit = res["commit"]
513
+ if result["updated_on_server"].empty? and result["conflicts"] and result["deleted"].empty?
514
+ say "Project is up to date", Thor::Shell::Color::GREEN
515
+ return true
516
+ end
517
+ update_count = 0
518
+ update_total = result["updated_on_server"].size + result["conflicts"].size
519
+
520
+ successful_changes = []
521
+ if update_total ==1
522
+ say "Downloading #{update_total} file", Thor::Shell::Color::BLUE
362
523
  else
363
- if @files.delete_file(f, relative_path, commit_sha1)
364
- update_count += 1
365
- successful_updates<< relative_path
524
+ say "Downloading #{update_total} files", Thor::Shell::Color::BLUE
525
+
526
+ end
527
+
528
+ result["conflicts"].each do |f|
529
+ relative_path = f.gsub(/^#{@project.local_path}/, "")
530
+ if @files.download_file(f, relative_path, project_home, conflict=true)
531
+ successful_changes << relative_path
366
532
  end
533
+
367
534
  end
535
+ result["updated_on_server"].each do |f|
536
+ relative_path = f.gsub(/^#{@project.local_path}/, "")
537
+ if f.end_with? "/"
538
+ # dir
539
+ if @files.download_dir(f, relative_path, project_home)
540
+ successful_changes << relative_path
541
+ end
542
+ else
543
+ # blob
544
+ if @files.download_file(f, relative_path, project_home)
545
+ successful_changes << relative_path
546
+ end
547
+ end
548
+
549
+ end
550
+ if update_total == successful_changes.size
551
+ # update idx with latest commit
552
+ @project.update_idx_with_commit!(commit)
553
+ say "Done. Downloaded:", Thor::Shell::Color::GREEN
554
+ say successful_changes.join("\n"), Thor::Shell::Color::GREEN
555
+ say "Total of #{successful_changes.size} / #{update_total} files.", Thor::Shell::Color::GREEN
556
+ end
557
+ rescue SignalException
558
+ say "/nAborting"
559
+ exit(1)
368
560
  end
561
+ end
369
562
 
370
- rescue Interrupt
371
- @files.rollback_commit(commit_sha1)
372
- say "User aborted, Rolling Back all changes.", Thor::Shell::Color::RED
373
- exit(0)
374
- rescue
375
- @files.rollback_commit(commit_sha1)
376
- say "Exception while trying to upload, Rolling back", Thor::Shell::Color::RED
377
- exit(0)
563
+
564
+ desc 'sync', 'Sync with remote server'
565
+
566
+ def sync
567
+ say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
568
+ invoke :download
569
+ invoke :upload
378
570
  end
379
- if update_count == update_total
380
- res = @files.end_commit(commit_sha1)
381
- if (Cnvrg::CLI.is_response_success(res, false))
382
- # save idx
571
+
572
+ # desc 'random', 'random'
573
+ # def random
574
+ # say "Fun trivia game for taking a recess :-)", Thor::Shell::Color::BLUE
575
+ # subject = ask("Pick a subject\n1.NBA\n2.American History\n3.Data Science\n")
576
+ # file = "ds.txt"
577
+ # case subject
578
+ # when "1"
579
+ # file = "nba.txt"
580
+ # when "2"
581
+ # file = "ah.txt"
582
+ # when "3"
583
+ # file = "ds.txt"
584
+ # end
585
+ # line = File.readlines(file).sample
586
+ # q = line[0,line.index('?')+1]
587
+ # a = line[line.index('?')+1,line.size]
588
+ # answer = ask(q+"/n")
589
+ #
590
+ #
591
+ #
592
+ # end
593
+ # Run
594
+ #
595
+ desc 'exec CMD', 'Execute a process'
596
+ method_option :sync_before, :type => :boolean, :aliases => ["-sb", "--sb"], :default => true
597
+ method_option :sync_after, :type => :boolean, :aliases => ["-sa", "--sa"], :default => true
598
+ method_option :title, :type => :string, :aliases => ["-t", "--t"], :default => ""
599
+ method_option :log, :type => :boolean, :aliases => ["-l", "--l"], :default => false
600
+ method_option :email_notification, :type => :boolean, :aliases => ["-en", "--en"], :default => false
601
+ method_option :upload_output, :type => :string, :aliases => ["--uo", "-uo"], :default => ""
602
+
603
+ def exec(*cmd)
604
+ begin
605
+ verify_logged_in()
606
+
607
+ project_home = get_project_home
608
+ @project = Project.new(project_home)
609
+ sync_before = options["sync_before"]
610
+ sync_after = options["sync_after"]
611
+ print_log = options["log"]
612
+ title = options["title"]
613
+ email_notification = options["email_notification"]
614
+ upload_output = options["upload_output"]
615
+ time_to_upload = calc_output_time(upload_output)
616
+
617
+ if sync_before
618
+ # Sync before run
619
+ say "Syncing project before running", Thor::Shell::Color::BLUE
620
+ say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
621
+ download()
622
+ upload()
623
+ say "Done Syncing", Thor::Shell::Color::BLUE
624
+ end
625
+
626
+ start_commit = @project.last_local_commit
627
+ cmd = cmd.join("\s")
628
+ log = []
629
+ say "Running: #{cmd}\n", Thor::Shell::Color::BLUE
630
+
631
+ @exp = Experiment.new(@project.owner, @project.slug)
632
+
633
+ platform = RUBY_PLATFORM
634
+ machine_name = Socket.gethostname
383
635
  begin
384
- @project.update_idx_with_files_commits!((successful_deletions+successful_updates), res["result"]["commit_time"])
385
636
 
386
- @project.update_idx_with_commit!(commit_sha1)
387
- rescue
388
- @files.rollback_commit(commit_sha1)
389
- say "Couldn't commit updates, Rolling Back all changes.", Thor::Shell::Color::RED
390
- exit(1)
637
+ @exp.start(cmd, platform, machine_name, start_commit, title, email_notification)
638
+ unless @exp.slug.nil?
639
+ real = Time.now
640
+ exp_success = true
641
+ memory_total = []
642
+ cpu_total = []
643
+ start_loop = Time.now
644
+ begin
645
+ PTY.spawn(cmd) do |stdout, stdin, pid, stderr|
646
+ begin
647
+ stdout.each do |line|
648
+ cur_time = Time.now
649
+ monitor = %x{ps aux|awk '{print $2,$3,$4}'|grep #{pid} }
650
+ monitor_by = monitor.split(" ")
651
+ memory = monitor_by[2]
652
+ cpu = monitor_by[1]
653
+ memory_total << memory.to_f
654
+ cpu_total << cpu.to_f
655
+ real_time= Time.now-real
656
+
657
+ cur_log = {time: cur_time,
658
+ message: line,
659
+ type: "stdout",
660
+ real: real_time}
661
+ if print_log
662
+ puts cur_log
663
+ end
664
+ log << cur_log
665
+
666
+ begin
667
+ if time_to_upload !=0
668
+ if time_to_upload <= Time.now - start_loop
669
+ #upload current log
670
+ cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
671
+ memory_average = memory_total.inject(0) { |sum, el| sum + el }.to_f / memory_total.size
672
+
673
+ @exp.upload_temp_log(log, cpu_average, memory_average)
674
+ log = []
675
+ start_loop = Time.now
676
+ end
677
+
678
+ end
679
+ rescue
680
+ say "Failed to upload ongoing results, continuing with experiment", Thor::Shell::Color::YELLOW
681
+ end
391
682
 
392
- end
683
+ end
684
+
685
+
686
+ if stderr
687
+
688
+ stderr.each do |err|
689
+
690
+ log << {time: Time.now, message: err, type: "stderr"}
691
+ puts err
692
+ end
693
+ end
694
+
695
+ rescue Errno::EIO => e
696
+ break
697
+ rescue Errno::ENOENT
698
+
699
+ exp_success = false
700
+ say "command \"#{cmd}\" couldn't be executed, verify command is valid", Thor::Shell::Color::RED
701
+ rescue PTY::ChildExited
702
+
703
+ exp_success = false
704
+ say "The process exited!", Thor::Shell::Color::RED
705
+ rescue => e
706
+ ensure
707
+ ::Process.wait pid
708
+
709
+ end
710
+ cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
711
+ memory_average = memory_total.inject(0) { |sum, el| sum + el }.to_f / memory_total.size
712
+ exit_status = $?.exitstatus
713
+ puts exit_status
714
+ if exit_status != 0
715
+ exp_success = false
716
+ end
717
+ if !exp_success
718
+ end_commit = @project.last_local_commit
719
+ res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
720
+ say "Experiment has failed, look at the log for more details or run cnvrg exec --log", Thor::Shell::Color::RED
721
+ exit(0)
722
+ end
723
+ if sync_after
724
+ say "Syncing project after running", Thor::Shell::Color::BLUE
725
+ # Sync after run
726
+ download()
727
+ upload()
728
+ say "Done Syncing", Thor::Shell::Color::BLUE
729
+ end
730
+ end_commit = @project.last_local_commit
731
+
732
+ res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
733
+ check = Helpers.checkmark()
734
+ say "#{check} Done. Experiment's result: #{Cnvrg::Helpers.remote_url}/#{@project.owner}/projects/#{@project.slug}/experiments/#{@exp.slug}", Thor::Shell::Color::GREEN
735
+ end
736
+ rescue
737
+ say "Couldn't run #{cmd}, check your input parameters", Thor::Shell::Color::RED
738
+ exit(1)
739
+ end
740
+
741
+
742
+ end
393
743
 
394
- say "Done", Thor::Shell::Color::BLUE
395
- if successful_updates.size >0
396
- say "Updated:", Thor::Shell::Color::GREEN
397
- suc = successful_updates.map { |x| x=Helpers.checkmark() +" "+x }
398
- say suc.join("\n"), Thor::Shell::Color::GREEN
399
- end
400
- if successful_deletions.size >0
401
- say "Deleted:", Thor::Shell::Color::GREEN
402
- del = successful_updates.map { |x| x=Helpers.checkmark() +" "+x }
403
- say del.join("\n"), Thor::Shell::Color::GREEN
404
744
  end
405
- say "Total of #{update_count} / #{update_total} files.", Thor::Shell::Color::GREEN
406
- else
407
- @files.rollback_commit(commit_sha1)
408
- say "Error. Rolling Back all changes.", Thor::Shell::Color::RED
745
+ rescue SignalException
746
+ say "/nAborting"
747
+ exit(1)
409
748
  end
410
- else
411
- @files.rollback_commit(commit_sha1)
412
749
  end
413
750
 
414
- end
751
+ desc 'run_notebook', 'Starts a new notebook environment'
752
+ method_option :notebook_dir, :type => :string, :aliases => ["-n", "--n"], :default => "", :desc => "relative path to notebook dir from current directory"
753
+ method_option :docker, :type => :boolean, :aliases => ["-d", "--d"], :default => true
754
+ method_option :image_name, :type => :string, :aliases => ["-i", "--i"], :default => ""
415
755
 
416
- desc 'download', 'Download updated files'
756
+ def run_notebook
757
+ begin
758
+ cur_path = Dir.pwd
759
+ notebook_dir = options["notebook_dir"]
760
+ if notebook_dir.empty?
761
+ notebook_dir = cur_path
762
+ else
763
+ notebook_dir = cur_path+ notebook_dir
764
+ end
765
+ say "Linking notebook directory to: #{notebook_dir}", Thor::Shell::Color::BLUE
766
+ docker = options["docker"]
767
+ try_again = true
768
+
769
+
770
+ if docker
771
+ docker_path = verify_software_installed("docker")
772
+ image_name = options["image_name"]
773
+ if image_name.empty?
774
+ images_list = `#{docker_path} images`
775
+ if images_list.empty? or images_list.nil?
776
+ say "you don't have any images to run", Thor::Shell::Color::BLUE
777
+ else
778
+ say "Choose image name to run as a container\n", Thor::Shell::Color::BLUE
779
+ say images_list
780
+ image_name = ask("\nwhat is the image name?\n")
781
+ end
417
782
 
418
- def download
419
- verify_logged_in()
420
- project_home = get_project_home
421
- @project = Project.new(project_home)
422
- @files = Cnvrg::Files.new(@project.owner, @project.slug)
783
+ end
784
+ while (try_again) do
785
+ run_docker = `#{docker_path} run -d -p 8888:8888 -v #{notebook_dir}:/home/ds/notebooks -t -i #{image_name} 2>&1`
786
+ if !run_docker.match(/[a-z0-9]{64}/).nil? and !run_docker.include? "Error"
787
+ container_id = get_container_id()
788
+ sleep(3)
789
+ logs = `docker logs #{container_id}`
790
+ url = URI.extract(logs).reject { |x| x if !x.include? "http" }.uniq![0]
791
+ if !url.empty?
792
+ check = Helpers.checkmark()
793
+
794
+ say "#{check} Notebook server started successfully, view notebook in url: #{url}", Thor::Shell::Color::GREEN
795
+ try_again= false
796
+ else
797
+ say "Couldn't start notebook server", Thor::Shell::Color::RED
798
+ exit(1)
799
+ end
423
800
 
424
- res = @project.compare_idx["result"]
425
- result = res["tree"]
426
- commit = res["commit"]
427
- if result["updated_on_server"].empty? and result["conflicts"] and result["deleted"].empty?
428
- say "Project is up to date", Thor::Shell::Color::GREEN
429
- return true
430
- end
431
- update_count = 0
432
- update_total = result["updated_on_server"].size + result["conflicts"].size
801
+ elsif run_docker.include? "port is already allocated"
802
+ say "Couldn't start notebook with port 8888, port is taken", Thor::Shell::Color::RED
803
+ port_container = `#{docker_path} ps |grep 8888 |awk '{print $1}'`.strip!
804
+ stop = ask "There is another running notebook server: #{port_container}, do you want to stop it?", Thor::Shell::Color::BLUE, limited_to: ['y', 'n'], default: 'y'
805
+ if stop == "y"
806
+ did_stop = system("#{docker_path} stop #{port_container}")
807
+ if !did_stop
808
+ say "Couldn't stop notebook server: #{port_container}", Thor::Shell::Color::RED
809
+ exit(1)
433
810
 
434
- successful_changes = []
435
- if update_total ==1
436
- say "Downloading #{update_total} file", Thor::Shell::Color::BLUE
437
- else
438
- say "Downloading #{update_total} files", Thor::Shell::Color::BLUE
811
+ end
812
+ else
813
+ logs = `#{docker_path} logs #{port_container}`
814
+ url = URI.extract(logs).reject { |x| x if !x.include? "http" }.uniq![0]
815
+ say "Okay, you could find the existing server in: #{url}", Thor::Shell::Color::BLUE
816
+ exit(1)
817
+ end
818
+ else
819
+ say "Couldn't start notebook server", Thor::Shell::Color::RED
820
+ exit(1)
439
821
 
440
- end
822
+ end
823
+ end
824
+ else
825
+ jup =verify_software_installed("jupyter-notebook")
826
+ logs = `#{jup} --no-browser --ip=0.0.0.0 --notebook-dir=#{notebook_dir}`
827
+ url = URI.extract(logs).reject { |x| x if !x.include? "http" }.uniq![0]
828
+ if !url.empty?
829
+ check = Helpers.checkmark()
441
830
 
442
- result["conflicts"].each do |f|
443
- relative_path = f.gsub(/^#{@project.local_path}/, "")
444
- if @files.download_file(f, relative_path, project_home, conflict=true)
445
- successful_changes << relative_path
831
+ say "#{check} Notebook server started successfully, view notebook in url: #{url}", Thor::Shell::Color::GREEN
832
+ else
833
+ say "Couldn't start notebook server", Thor::Shell::Color::RED
834
+ exit(1)
835
+ end
836
+
837
+ end
838
+ rescue SignalException
839
+ say "Aborting"
840
+ exit(1)
446
841
  end
447
842
 
843
+
448
844
  end
449
- result["updated_on_server"].each do |f|
450
- relative_path = f.gsub(/^#{@project.local_path}/, "")
451
- if f.end_with? "/"
452
- # dir
453
- if @files.download_dir(f, relative_path, project_home)
454
- successful_changes << relative_path
455
- end
456
- else
457
- # blob
458
- if @files.download_file(f, relative_path, project_home)
459
- successful_changes << relative_path
845
+
846
+ desc 'install_notebook_libraries', 'Starts a new notebook environment'
847
+ method_option :commit_name, :type => :string, :aliases => ["-c", "--c"], :default => "", :desc => "commit changes to notebook server when finished"
848
+
849
+ def install_notebook_libraries
850
+ begin
851
+ docker_path = verify_software_installed("docker")
852
+ container_id = get_container_id
853
+ say "Opening shell in notebook server\nYou can run pip install [library] to install more tools\ntype exit to finish", Thor::Shell::Color::BLUE
854
+ system("#{docker_path} exec -it #{container_id} bash")
855
+ commit_name = options["commit_name"]
856
+ if !commit_name.empty?
857
+ return commit_notebook(commit_name)
460
858
  end
859
+ rescue SignalException
860
+ say "/nAborting"
861
+ exit(1)
461
862
  end
462
863
 
463
864
  end
464
- if update_total == successful_changes.size
465
- # update idx with latest commit
466
- @project.update_idx_with_commit!(commit)
467
- say "Done. Downloaded:", Thor::Shell::Color::GREEN
468
- say successful_changes.join("\n"), Thor::Shell::Color::GREEN
469
- say "Total of #{successful_changes.size} / #{update_total} files.", Thor::Shell::Color::GREEN
470
- end
471
- end
472
865
 
866
+ desc 'commit_notebook', 'commit notebook changes to create a new notebook image'
473
867
 
474
- desc 'sync', 'Sync with remote server'
868
+ def commit_notebook(notebook_image_name)
869
+ begin
870
+ docker_path = verify_software_installed("docker")
475
871
 
476
- def sync
477
- say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
478
- invoke :download
479
- invoke :upload
480
- end
872
+ container_id = get_container_id
873
+ owner = Cnvrg::CLI.get_owner()
874
+ say "Commiting notebook changes to a: #{owner}/#{notebook_image_name}", Thor::Shell::Color::BLUE
481
875
 
482
- # desc 'random', 'random'
483
- # def random
484
- # say "Fun trivia game for taking a recess :-)", Thor::Shell::Color::BLUE
485
- # subject = ask("Pick a subject\n1.NBA\n2.American History\n3.Data Science\n")
486
- # file = "ds.txt"
487
- # case subject
488
- # when "1"
489
- # file = "nba.txt"
490
- # when "2"
491
- # file = "ah.txt"
492
- # when "3"
493
- # file = "ds.txt"
494
- # end
495
- # line = File.readlines(file).sample
496
- # q = line[0,line.index('?')+1]
497
- # a = line[line.index('?')+1,line.size]
498
- # answer = ask(q+"/n")
499
- #
500
- #
501
- #
502
- # end
503
- # Run
504
- #
505
- desc 'exec CMD', 'Execute a process'
506
- method_option :sync_before, :type => :boolean, :aliases => ["-sb", "--sb"], :default => true
507
- method_option :sync_after, :type => :boolean, :aliases => ["-sa", "--sa"], :default => true
508
- method_option :title, :type => :string, :aliases => ["-t", "--t"], :default => ""
509
- method_option :log, :type => :boolean, :aliases => ["-l", "--l"], :default => false
510
- method_option :email_notification, :type => :boolean, :aliases => ["-en", "--en"], :default => false
511
- method_option :upload_output, :type => :string, :aliases => ["--uo", "-uo"], :default => ""
512
-
513
- def exec(*cmd)
514
- verify_logged_in()
515
-
516
- project_home = get_project_home
517
- @project = Project.new(project_home)
518
- sync_before = options["sync_before"]
519
- sync_after = options["sync_after"]
520
- print_log = options["log"]
521
- title = options["title"]
522
- email_notification = options["email_notification"]
523
- upload_output = options["upload_output"]
524
- time_to_upload = calc_output_time(upload_output)
525
-
526
- if sync_before
527
- # Sync before run
528
- say "Syncing project before running", Thor::Shell::Color::BLUE
529
- say 'Checking for new updates from remote version', Thor::Shell::Color::BLUE
530
- download()
531
- upload()
532
- say "Done Syncing", Thor::Shell::Color::BLUE
876
+ commit_res = system("#{docker_path} commit #{container_id} #{owner}/#{notebook_image_name}")
877
+ if commit_res
878
+ checker = Helpers.checkmark()
879
+ say "#{checker} Done.", Thor::Shell::Color::GREEN
880
+ else
881
+ say "Couldn't commit new notebook image ", Thor::Shell::Color::RED
882
+
883
+ end
884
+ rescue SignalException
885
+ say "/nAborting"
886
+ exit(1)
887
+ end
533
888
  end
534
889
 
535
- start_commit = @project.last_local_commit
536
- cmd = cmd.join("\s")
537
- log = []
538
- say "Running: #{cmd}", Thor::Shell::Color::BLUE
890
+ desc 'upload_notebook', 'commit notebook changes to create a new notebook image'
539
891
 
540
- @exp = Experiment.new(@project.owner, @project.slug)
892
+ def upload_image(image_name)
893
+ docker_path = verify_software_installed("docker")
894
+ owner = Cnvrg::CLI.get_owner()
895
+ # verify image exist
896
+ # owner = "cnvrgio"
897
+ images = `#{docker_path} images |grep #{owner}/#{image_name}`
898
+ if images.empty?
899
+ say "Couldn't find any images named: #{owner}/#{image_name}", Thor::Shell::Color::RED
900
+ exit(1)
901
+ end
902
+ path = File.expand_path('~')+"/.cnvrg/#{owner}_#{image_name}.tar"
903
+ begin
904
+ say "Creating image file to upload", Thor::Shell::Color::BLUE
905
+ if !(File.exist? path or File.exist? path+"gz")
906
+ saveRes = system("#{docker_path} save #{owner}/#{image_name}>#{path}")
907
+ if !saveRes
908
+ say "Couldn't create tar file from image", Thor::Shell::Color::RED
909
+ exit(1)
910
+ end
911
+ gzipRes = system("gzip -f #{path}")
912
+ if !gzipRes
913
+ say "Couldn't create tar file from image", Thor::Shell::Color::RED
914
+ exit(1)
915
+ end
916
+ end
541
917
 
542
- platform = RUBY_PLATFORM
543
- machine_name = Socket.gethostname
544
- begin
918
+ path = path+".gz"
919
+ @files = Cnvrg::Files.new(owner, "")
545
920
 
546
- @exp.start(cmd, platform, machine_name, start_commit, title, email_notification)
547
- unless @exp.slug.nil?
548
- real = Time.now
549
- exp_success = true
550
- memory_total = []
551
- cpu_total = []
552
- start_loop = Time.now
553
-
554
-
555
- PTY.spawn(cmd) do |stdout, stdin, pid, stderr|
556
- begin
557
- stdout.each do |line|
558
-
559
- cur_time = Time.now
560
- monitor = %x{ps aux|awk '{print $2,$3,$4}'|grep #{pid} }
561
- monitor_by = monitor.split(" ")
562
- memory = monitor_by[2]
563
- cpu = monitor_by[1]
564
- memory_total << memory.to_f
565
- cpu_total << cpu.to_f
566
- real_time= Time.now-real
567
-
568
- cur_log = {time: cur_time,
569
- message: line,
570
- type: "stdout",
571
- rss: memory,
572
- cpu: cpu,
573
- real: real_time}
574
- if print_log
575
- puts cur_log
576
- end
577
- log << cur_log
578
- begin
579
- if time_to_upload !=0
580
- if time_to_upload <= Time.now - start_loop
581
- #upload current log
582
- cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
583
- memory_average = memory_total.inject(0) { |sum, el| sum + el }.to_f / memory_total.size
584
-
585
- @exp.upload_temp_log(log, cpu_average, memory_average)
586
- log = []
587
- start_loop = Time.now
588
- end
921
+ exit_status = $?.exitstatus
922
+ if exit_status == 0
923
+ say "Uploading image file", Thor::Shell::Color::BLUE
924
+ res = @files.upload_image(path, image_name, owner)
925
+ if res
926
+ File.delete(path)
927
+ checks = Helpers.checkmark()
928
+ say "#{checks} Done", Thor::Shell::Color::GREEN
929
+ else
930
+ say "Couldn't upload image", Thor::Shell::Color::RED
931
+ end
932
+ else
933
+ say "Couldn't create image file for: #{owner}/#{image_name}", Thor::Shell::Color::RED
934
+ exit(1)
935
+ end
936
+ rescue SignalException
937
+ say "Couldn't upload image file for: #{owner}/#{image_name}", Thor::Shell::Color::RED
938
+ exit(1)
939
+ end
589
940
 
590
- end
591
- rescue
592
- say "Failed to upload ongoing results, continuing with experiment", Thor::Shell::Color::YELLOW
593
- end
594
941
 
942
+ end
943
+
944
+ desc 'download_image', 'commit notebook changes to create a new notebook image'
945
+
946
+ def download_image(image_name)
947
+ begin
948
+ owner = Cnvrg::CLI.get_owner()
595
949
 
950
+ notebooks_res = Cnvrg::API.request("users/#{owner}/images/" + "find", 'POST', {image_name: image_name})
951
+
952
+ if Cnvrg::CLI.is_response_success(notebooks_res)
953
+
954
+ images = notebooks_res["result"]["images"]
955
+ if images.empty?
956
+ say "Couldn't find any image with name: #{image_name}", Thor::Shell::Color::RED
957
+ exit(1)
958
+ elsif images.size == 1
959
+ image_id = images[0]["slug"]
960
+ else
961
+ printf "%-20s %-20s %-30s %-20s\n", "name", "version", "last updated", "created by"
962
+ images.each_with_index do |u, i|
963
+ time = Time.parse(u["updated_at"])
964
+ update_at = get_local_time(time)
965
+ version = u["version"] || "v1"
966
+ created_by = u["image_file_name"][/^[^\_]*/]
967
+ printf "%-20s %-20s %-30s %-20s\n", u["name"], version, update_at, created_by
596
968
  end
597
- if stderr
598
- stderr.each do |err|
599
- log << {time: Time.now, message: err, type: "stderr"}
969
+ choice = ask("Which version to download for #{image_name}?")
970
+ images.each do |u|
971
+ if u["version"] == choice
972
+ image_id = u["slug"]
600
973
  end
974
+
601
975
  end
602
- Process.wait(pid)
603
- rescue Errno::EIO
604
- break
605
- rescue Errno::ENOENT
606
- exp_success = false
607
- say "command \"#{cmd}\" couldn't be executed, verify command is valid", Thor::Shell::Color::RED
608
- rescue PTY::ChildExited
609
- exp_success = false
610
- puts "The process exited!"
611
- end
612
976
 
613
- cpu_average = cpu_total.inject(0) { |sum, el| sum + el }.to_f / cpu_total.size
614
- memory_average = memory_total.inject(0) { |sum, el| sum + el }.to_f / memory_total.size
615
- exit_status = $?.exitstatus
616
- if !exp_success
617
- end_commit = @project.last_local_commit
618
- res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
619
- say "Experiment has failed", Thor::Shell::Color::RED
620
- exit(0)
621
977
  end
622
- if sync_after
623
- say "Syncing project after running", Thor::Shell::Color::BLUE
624
- # Sync after run
625
- download()
626
- upload()
627
- say "Done Syncing", Thor::Shell::Color::BLUE
978
+ end
979
+ path = Dir.pwd+"/#{owner}_#{image_name}.tar.gz"
980
+ @files = Cnvrg::Files.new(owner, "")
981
+
982
+ say "Downloading image file", Thor::Shell::Color::BLUE
983
+ begin
984
+ res = @files.download_image(path, image_id, owner)
985
+ if res
986
+ checks = Helpers.checkmark()
987
+ say "#{checks} Done", Thor::Shell::Color::GREEN
988
+ return true
989
+ else
990
+ say "Couldn't download image #{image_name}", Thor::Shell::Color::RED
991
+ return false
628
992
  end
629
- end_commit = @project.last_local_commit
993
+ rescue Interrupt
994
+ say "The user has exited to process, aborting", Thor::Shell::Color::BLUE
995
+ exit(1)
996
+ end
997
+ rescue SignalException
998
+ say "/nAborting"
999
+ exit(1)
1000
+ end
1001
+ end
1002
+
1003
+
1004
+ desc 'list_images', 'lists all custom images you can pull'
630
1005
 
631
- res = @exp.end(log, exit_status, end_commit, cpu_average, memory_average)
632
- check = Helpers.checkmark()
633
- say "#{check} Done. Experiment's result: #{Cnvrg::Helpers.remote_url}/#{@project.owner}/projects/#{@project.slug}/experiments/#{@exp.slug}", Thor::Shell::Color::GREEN
1006
+ def list_images
1007
+ owner = Cnvrg::CLI.get_owner()
1008
+ res = Cnvrg::API.request("users/#{owner}/images/list", 'GET')
1009
+ if Cnvrg::CLI.is_response_success(res)
1010
+ printf "%-20s %-20s %-30s %-20s\n", "name", "version", "last updated", "created by"
1011
+ res["result"]["images"].each do |u|
1012
+ time = Time.parse(u["updated_at"])
1013
+ update_at = get_local_time(time)
1014
+ version = u["version"] || "v1"
1015
+ created_by = u["image_file_name"][/^[^\_]*/]
1016
+
1017
+ printf "%-20s %-20s %-30s %-20s\n", u["name"], version, update_at, created_by
634
1018
  end
1019
+ end
1020
+ return res["result"]["images"]
1021
+ end
635
1022
 
1023
+
1024
+ desc 'pull_image', 'downloads and loads a custom image'
1025
+
1026
+ def pull_image(image_name)
1027
+ begin
1028
+
1029
+ if download_image(image_name)
1030
+ path = Dir.pwd+"/#{owner}_#{image_name}.tar.gz"
1031
+ loadRes = system("docker load < #{path}")
1032
+ if loadRes.include? "Loaded image"
1033
+ say loadRes, Thor::Shell::Color::GREEN
1034
+ else
1035
+ say loadRes, Thor::Shell::Color::RED
1036
+ end
1037
+
1038
+ end
1039
+ rescue SignalException
1040
+ say "\nAborting"
1041
+ exit(1)
636
1042
  end
637
1043
 
638
1044
  end
639
- end
640
1045
 
1046
+ no_tasks do
1047
+ def get_container_id
1048
+ docker_path = verify_software_installed("docker")
641
1049
 
642
- no_tasks do
643
- def set_owner(owner, username)
644
- home_dir = File.expand_path('~')
1050
+ container_id = `#{docker_path} ps --quiet --last=1 --filter status=running`.strip!
1051
+ if container_id.empty?
1052
+ say "Couldn't find a running notebook server, execute run_notebook", Thor::Shell::Color::RED
1053
+ exit(1)
1054
+ end
1055
+ return container_id
1056
+ end
645
1057
 
646
- begin
647
- if !File.directory? home_dir+"/.cnvrg"
648
- FileUtils.mkdir_p(home_dir+"/.cnvrg")
1058
+ def set_owner(owner, username)
1059
+ home_dir = File.expand_path('~')
1060
+
1061
+ begin
1062
+ if !File.directory? home_dir+"/.cnvrg"
1063
+ FileUtils.mkdir_p([home_dir+"/.cnvrg", home_dir+"/.cnvrg/tmp"])
1064
+ end
1065
+ if !File.exist?(home_dir+"/.cnvrg/config.yml")
1066
+ FileUtils.touch [home_dir+"/.cnvrg/config.yml"]
1067
+ end
1068
+ config = YAML.load_file(home_dir+"/.cnvrg/config.yml")
1069
+ if config.empty?
1070
+ config = {owner: owner, username: username, version_last_check: get_start_day(), api: "https://cnvrg.io/api"}
1071
+ else
1072
+ config = {owner: owner, username: username, version_last_check: get_start_day(), api: config.to_h[:api]}
1073
+ end
1074
+
1075
+ File.open(home_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
1076
+ return true
1077
+ rescue
1078
+ return false
649
1079
  end
650
- if !File.exist?(home_dir+"/.cnvrg/config.yml")
651
- FileUtils.touch [home_dir+"/.cnvrg/config.yml"]
1080
+
1081
+ end
1082
+
1083
+ def get_start_day
1084
+ time = Time.now
1085
+ return Time.new(time.year, time.month, time.day)
1086
+ end
1087
+
1088
+ def calc_output_time(upload_output)
1089
+ if upload_output.nil? or upload_output.empty?
1090
+ return 0
652
1091
  end
653
- config = {owner: owner, username: username}
654
- File.open(home_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
655
- return true
656
- rescue
657
- return false
1092
+ time = upload_output.split(/(\d+)/).reject(&:empty?).map { |x| x.strip }
1093
+ if time.size!=2
1094
+ 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")
1095
+ return calc_output_time(upload_output)
1096
+ end
1097
+ if time[0] == "0"
1098
+ return -1
1099
+ end
1100
+ case time[1].downcase
1101
+ when "s"
1102
+ return time[0].to_f
1103
+ when "m"
1104
+ return time[0].to_f*60
1105
+ when "h"
1106
+ return time[0].to_f*3600
1107
+ when "d"
1108
+ return time[0].to_f*24*3600
1109
+ else
1110
+ 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")
1111
+ calc_output_time(upload_output)
1112
+ end
1113
+
658
1114
  end
659
1115
 
660
- end
1116
+ def self.is_response_success(response, should_exit=true)
1117
+ if response["status"]!= 200
1118
+ error = response['message']
1119
+ if response["status"] == 500
1120
+ say("<%= color('Server Error', RED) %>")
1121
+ else
1122
+ say("<%= color('Error: #{error}', RED) %>")
1123
+ end
661
1124
 
662
- def calc_output_time(upload_output)
663
- puts upload_output
664
- if upload_output.nil? or upload_output.empty?
665
- return 0
666
- end
667
- time = upload_output.split(/(\d+)/).reject(&:empty?).map { |x| x.strip }
668
- if time.size!=2
669
- 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")
670
- return calc_output_time(upload_output)
671
- end
672
- case time[1].downcase
673
- when "s"
674
- return time[0].to_f
675
- when "m"
676
- return time[0].to_f*60
677
- when "h"
678
- return time[0].to_f*3600
679
- when "d"
680
- return time[0].to_f*24*3600
681
- else
682
- 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")
683
- calc_output_time(upload_output)
1125
+ if should_exit
1126
+ exit(1)
1127
+ else
1128
+ return false
1129
+ end
1130
+ end
1131
+ return true
684
1132
  end
685
1133
 
686
- end
1134
+ def self.get_owner
1135
+ home_dir = File.expand_path('~')
687
1136
 
688
- def self.is_response_success(response, should_exit=true)
689
- puts response
690
- if response["status"]!= 200
691
- error = response['message']
692
- if response["status"] == 500
693
- say("<%= color('Server Error', RED) %>")
1137
+ config = YAML.load_file(home_dir+ "/.cnvrg/config.yml")
1138
+ owner = config.to_h[:owner]
1139
+ if owner.empty?
1140
+ invoke :set_default_owner
1141
+ return get_owner()
694
1142
  else
695
- say("<%= color('Error: #{error}', RED) %>")
1143
+ return owner
696
1144
  end
1145
+ end
1146
+
1147
+ def get_project_home
1148
+ absolute_path = Dir.pwd
1149
+ dirs = absolute_path.split("/")
1150
+ dirs.pop while not Dir.exists?("#{dirs.join("/")}/.cnvrg") and dirs.size != 0
697
1151
 
698
- if should_exit
1152
+ if dirs.size == 0
1153
+ say "Couldn't find cnvrg directory. Please start a new project", Thor::Shell::Color::RED
699
1154
  exit(1)
1155
+ end
1156
+ return dirs.join("/")
1157
+ end
1158
+
1159
+ def should_update_version
1160
+ res = Cnvrg::API.request("/cli/version", 'GET')
1161
+ if Cnvrg::CLI.is_response_success(res, false)
1162
+ updated_version = res["result"]["version"]
1163
+ if updated_version != Cnvrg::VERSION
1164
+ return true
1165
+ else
1166
+ return false
1167
+ end
700
1168
  else
701
1169
  return false
702
1170
  end
703
1171
  end
704
- return true
705
- end
706
1172
 
707
- def self.get_owner
708
- config = YAML.load_file("~/.cnvrg/config.yml")
709
- owner = config.to_h[:owner]
710
- if owner.empty?
711
- invoke :set_default_owner
712
- return get_owner()
713
- else
714
- return owner
1173
+ def verify_logged_in
1174
+ auth = Cnvrg::Auth.new
1175
+ unless auth.is_logged_in?
1176
+ say 'You\'re not logged in', Thor::Shell::Color::RED
1177
+ say 'Please log in via `cnvrg login`', Thor::Shell::Color::YELLOW
1178
+ exit(1)
1179
+ end
1180
+ if !Helpers.internet_connection?
1181
+ say "you seem to be offline, please check your internet connection", Thor::Shell::Color::RED
1182
+ exit(1)
1183
+ end
1184
+
1185
+ config = YAML.load_file(File.expand_path('~')+"/.cnvrg/config.yml")
1186
+ version_date = config.to_h[:version_last_check]
1187
+ next_day = get_start_day+ 86399
1188
+ if (version_date..next_day).cover?(Time.now)
1189
+ return true
1190
+ else
1191
+ if should_update_version()
1192
+ say "There is a new version, run gem update cnvrg", Thor::Shell::Color::BLUE
1193
+ end
1194
+ end
1195
+
715
1196
  end
716
- end
717
1197
 
718
- def get_project_home
719
- absolute_path = Dir.pwd
720
- dirs = absolute_path.split("/")
721
- dirs.pop while not Dir.exists?("#{dirs.join("/")}/.cnvrg") and dirs.size != 0
1198
+ def verify_software_installed(software)
1199
+ install_url = Cnvrg::CLI::INSTALLATION_URLS[software.to_sym]
1200
+ installed = `which #{software}`
1201
+ if installed.empty? or installed.nil?
1202
+ say "#{software} isn't installed, please install it first: #{install_url}", Thor::Shell::Color::RED
1203
+ exit(1)
1204
+ end
1205
+ installed.strip!
1206
+ case software
1207
+ when "docker"
1208
+ is_running = `#{installed} images`
1209
+ if is_running.include? "Cannot connect to the Docker daemon"
1210
+ if Helpers.mac?
1211
+ system("open -a Docker")
1212
+ else
1213
+ #is linux
1214
+
722
1215
 
723
- if dirs.size == 0
724
- say "Couldn't find cnvrg directory. Please start a new project", Thor::Shell::Color::RED
725
- exit(1)
1216
+ end
1217
+ end
1218
+ end
1219
+ return installed
726
1220
  end
727
- return dirs.join("/")
728
- end
729
1221
 
730
- def verify_logged_in
731
- auth = Cnvrg::Auth.new
732
- unless auth.is_logged_in?
733
- say 'You\'re not logged in', Thor::Shell::Color::RED
734
- say 'Please log in via `cnvrg login`', Thor::Shell::Color::YELLOW
735
- exit(1)
1222
+ def get_local_time(time_to_update)
1223
+ local = Time.now.localtime
1224
+ gmt_offset = local.gmt_offset
1225
+ new_time =time_to_update +gmt_offset
1226
+ return new_time.to_s.gsub("UTC", "")
1227
+
736
1228
  end
737
- end
738
1229
 
739
1230
 
1231
+ end
740
1232
  end
741
1233
  end
742
- end
743
1234
 
744
1235
 
745
1236