cnvrg 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 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