cnvrg 1.9.9.9.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/cnvrg +9 -0
- data/cnvrg.gemspec +47 -0
- data/lib/cnvrg.rb +7 -0
- data/lib/cnvrg/Images.rb +351 -0
- data/lib/cnvrg/api.rb +247 -0
- data/lib/cnvrg/api_v2.rb +14 -0
- data/lib/cnvrg/auth.rb +79 -0
- data/lib/cnvrg/cli.rb +5715 -0
- data/lib/cnvrg/cli/flow.rb +166 -0
- data/lib/cnvrg/cli/library_cli.rb +33 -0
- data/lib/cnvrg/cli/subcommand.rb +28 -0
- data/lib/cnvrg/cli/task.rb +116 -0
- data/lib/cnvrg/colors.rb +8 -0
- data/lib/cnvrg/connect_job_ssh.rb +31 -0
- data/lib/cnvrg/data.rb +335 -0
- data/lib/cnvrg/datafiles.rb +1325 -0
- data/lib/cnvrg/dataset.rb +892 -0
- data/lib/cnvrg/downloader/client.rb +101 -0
- data/lib/cnvrg/downloader/clients/azure_client.rb +45 -0
- data/lib/cnvrg/downloader/clients/gcp_client.rb +50 -0
- data/lib/cnvrg/downloader/clients/s3_client.rb +78 -0
- data/lib/cnvrg/experiment.rb +209 -0
- data/lib/cnvrg/files.rb +1047 -0
- data/lib/cnvrg/flow.rb +137 -0
- data/lib/cnvrg/helpers.rb +422 -0
- data/lib/cnvrg/helpers/agent.rb +188 -0
- data/lib/cnvrg/helpers/executer.rb +213 -0
- data/lib/cnvrg/hyper.rb +21 -0
- data/lib/cnvrg/image.rb +113 -0
- data/lib/cnvrg/image_cli.rb +25 -0
- data/lib/cnvrg/job_cli.rb +73 -0
- data/lib/cnvrg/job_ssh.rb +48 -0
- data/lib/cnvrg/logger.rb +111 -0
- data/lib/cnvrg/org_helpers.rb +5 -0
- data/lib/cnvrg/project.rb +822 -0
- data/lib/cnvrg/result.rb +29 -0
- data/lib/cnvrg/runner.rb +49 -0
- data/lib/cnvrg/ssh.rb +94 -0
- data/lib/cnvrg/storage.rb +128 -0
- data/lib/cnvrg/task.rb +165 -0
- data/lib/cnvrg/version.rb +3 -0
- metadata +460 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cb866c9448de7ea2062759a1f9cd9bf0f9db23b3fae06c8b61d178dbd1a227c9
|
4
|
+
data.tar.gz: dfc63cef384e0a8df9a367e03f544462638f5d0b43913dfe40b5dd59429ea2f8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 760d90fb1e7516a3e2f9ae72a7662ff02ae0e6324a883a17471ad5edacccc252f3b127a5bddf7ec0afcff6d42fe3b3f5596a6697fa058f5740ff0799894934b0
|
7
|
+
data.tar.gz: ae6196d1a37f4bc68534aa728199d93500ee8299c99a896452158d22cf1e73578cf277ba0742f3e302ef9e677c466a335e9dac214c608e15c8ed088d870ddb60
|
data/bin/cnvrg
ADDED
data/cnvrg.gemspec
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cnvrg/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'cnvrg'
|
8
|
+
spec.version = Cnvrg::VERSION
|
9
|
+
spec.authors = ['Yochay Ettun', 'Leah Kolben', 'Omer Shacham']
|
10
|
+
spec.email = ['info@cnvrg.io']
|
11
|
+
spec.summary = %q{A CLI tool for interacting with cnvrg.io.}
|
12
|
+
spec.description = %q{A CLI tool for interacting with cnvrg.io.}
|
13
|
+
spec.homepage = 'https://cnvrg.io'
|
14
|
+
|
15
|
+
#spec.files = `git ls-files`.split($/)
|
16
|
+
spec.files = %w[cnvrg.gemspec] + Dir['*.md', 'bin/*', 'lib/**/*.rb']
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.executables = ['cnvrg']
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler'
|
22
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
23
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
24
|
+
spec.add_development_dependency 'vcr', '~> 3.0'
|
25
|
+
spec.add_development_dependency 'aruba'
|
26
|
+
spec.add_development_dependency 'pry'
|
27
|
+
|
28
|
+
spec.add_runtime_dependency 'mimemagic', '~> 0.3.1','>=0.3.2'
|
29
|
+
spec.add_runtime_dependency 'faraday', '~> 0.15.2'
|
30
|
+
spec.add_runtime_dependency 'netrc', '~> 0.11.0'
|
31
|
+
spec.add_runtime_dependency 'open4', '~> 1.3', '>= 1.3.4'
|
32
|
+
spec.add_runtime_dependency 'highline', '~> 1.7', '>= 1.7.8'
|
33
|
+
spec.add_runtime_dependency 'thor', '~> 0.19.0','>=0.19.1'
|
34
|
+
spec.add_runtime_dependency 'aws-sdk-s3', '~> 1'
|
35
|
+
spec.add_runtime_dependency 'signet', '~> 0.11.0'
|
36
|
+
spec.add_runtime_dependency 'google-cloud-env', '~> 1.2.1'
|
37
|
+
spec.add_runtime_dependency 'google-cloud-core', '~> 1.3.2'
|
38
|
+
spec.add_runtime_dependency 'google-cloud-storage', '~> 1.21.1'
|
39
|
+
spec.add_runtime_dependency 'sucker_punch', '~> 2.0'
|
40
|
+
spec.add_runtime_dependency 'urlcrypt', '~> 0.1.1'
|
41
|
+
spec.add_runtime_dependency 'parallel', '~> 1.12.0'
|
42
|
+
spec.add_runtime_dependency 'azure-storage-blob', '~> 1.1.0'
|
43
|
+
spec.add_runtime_dependency 'logstash-logger', '~> 0.22.1'
|
44
|
+
spec.add_runtime_dependency 'activesupport', '~> 5.2.0'
|
45
|
+
spec.add_runtime_dependency 'ruby-progressbar'
|
46
|
+
spec.add_runtime_dependency 'down'
|
47
|
+
end
|
data/lib/cnvrg.rb
ADDED
data/lib/cnvrg/Images.rb
ADDED
@@ -0,0 +1,351 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'cnvrg/files'
|
3
|
+
require 'mimemagic'
|
4
|
+
|
5
|
+
|
6
|
+
module Cnvrg
|
7
|
+
class Images
|
8
|
+
# attr_reader :image_name, :image_tag, :is_docker, :project_slug, :commit_id, :owner, :port, :image_slug
|
9
|
+
|
10
|
+
|
11
|
+
def initialize()
|
12
|
+
begin
|
13
|
+
home_dir = File.expand_path('~')
|
14
|
+
config = YAML.load_file(home_dir+"/.cnvrg/config.yml")
|
15
|
+
@owner = config.to_h[:owner]
|
16
|
+
@username = config.to_h[:username]
|
17
|
+
rescue => e
|
18
|
+
@owner = ""
|
19
|
+
@username = ""
|
20
|
+
Cnvrg::Logger.log_info("cnvrg is not configured")
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def upload_docker_image(image_path, image_name,workdir, user, description, is_gpu )
|
26
|
+
begin
|
27
|
+
if image_name.present? and image_name.include? ":"
|
28
|
+
image_split = image_name.split(":")
|
29
|
+
image_name = image_split[0]
|
30
|
+
image_tag = image_split[1]
|
31
|
+
if image_tag.blank?
|
32
|
+
image_tag = "latest"
|
33
|
+
end
|
34
|
+
if image_name.blank?
|
35
|
+
Cnvrg::Logger.log_info("image_name: #{image_name} is not valid")
|
36
|
+
return false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
if !File.exist? image_path
|
40
|
+
Cnvrg::Logger.log_info("image_path: #{image_path} was not found")
|
41
|
+
return false
|
42
|
+
end
|
43
|
+
is_dockerfile = (!image_path.end_with? ".tar") ? true : false
|
44
|
+
file_name = File.basename image_path
|
45
|
+
file_size = File.size(image_path).to_f
|
46
|
+
mime_type = MimeMagic.by_path(image_path)
|
47
|
+
content_type = mime_type.present? ? mime_type.type : "application/x-tar"
|
48
|
+
|
49
|
+
image_res = Cnvrg::API.request("users/#{@owner}/images/upload" , 'POST_FILE', {image_name: image_name, image_tag: image_tag,
|
50
|
+
workdir: workdir, user: user, description:description, is_gpu:is_gpu,
|
51
|
+
file_name: file_name,relative_path:image_path,
|
52
|
+
file_size: file_size, file_content_type: content_type, is_dockerfile: is_dockerfile
|
53
|
+
})
|
54
|
+
|
55
|
+
Cnvrg::CLI.is_response_success(image_res, true)
|
56
|
+
|
57
|
+
path = image_res["result"]["path"]
|
58
|
+
image_id = image_res["result"]["image_id"]
|
59
|
+
|
60
|
+
props = Cnvrg::Helpers.get_s3_props(image_res["result"])
|
61
|
+
if props.is_a? Cnvrg::Result
|
62
|
+
return false
|
63
|
+
end
|
64
|
+
|
65
|
+
client = props[:client]
|
66
|
+
upload_options = props[:upload_options]
|
67
|
+
bucket = Aws::S3::Resource.new(client: client).bucket(props[:bucket])
|
68
|
+
resp = bucket.object(path).
|
69
|
+
upload_file(image_path, upload_options)
|
70
|
+
unless resp
|
71
|
+
raise Exception.new("Cant upload #{image_path}")
|
72
|
+
return false
|
73
|
+
end
|
74
|
+
return save_docker_image(image_id)
|
75
|
+
rescue => e
|
76
|
+
Cnvrg::Logger.log_error(e)
|
77
|
+
|
78
|
+
return false
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
def save_docker_image(image_id)
|
86
|
+
image_res = Cnvrg::API.request("users/#{@owner}/images/#{image_id}/save" , 'POST', {})
|
87
|
+
Cnvrg::CLI.is_response_success(image_res, true)
|
88
|
+
return image_res
|
89
|
+
end
|
90
|
+
|
91
|
+
def is_container_exist()
|
92
|
+
config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
|
93
|
+
if config[:container].nil?
|
94
|
+
return false
|
95
|
+
end
|
96
|
+
return config[:container]
|
97
|
+
end
|
98
|
+
|
99
|
+
def container_port()
|
100
|
+
config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
|
101
|
+
if config[:container].nil?
|
102
|
+
return false
|
103
|
+
else
|
104
|
+
return config[:port]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.image_exist(owner, image_name)
|
109
|
+
|
110
|
+
image_res = Cnvrg::API.request("users/#{owner}/images/" + "find", 'POST', {image_name: image_name})
|
111
|
+
|
112
|
+
if Cnvrg::CLI.is_response_success(image_res)
|
113
|
+
image= image_res["result"]["image"]
|
114
|
+
return image
|
115
|
+
else
|
116
|
+
return false
|
117
|
+
|
118
|
+
end
|
119
|
+
end
|
120
|
+
def store_image_build_commands(working_dir, cmd)
|
121
|
+
begin
|
122
|
+
custom_image_file = working_dir+"/.cnvrg/custom_image.txt"
|
123
|
+
if !File.exist? custom_image_file
|
124
|
+
FileUtils.touch [custom_image_file]
|
125
|
+
end
|
126
|
+
File.open(custom_image_file, 'a' ) do |f|
|
127
|
+
f.puts cmd
|
128
|
+
end
|
129
|
+
rescue
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
end
|
134
|
+
def self.create_new_custom_image(type,owner,image_name,is_public,is_base,image_extend,python3,tar_path)
|
135
|
+
response = Cnvrg::API.request("users/#{owner}/images/custom", 'POST', {instance_type:type,image_name:image_name,is_public:is_public,
|
136
|
+
is_base:is_base,image_extend:image_extend,
|
137
|
+
python3:python3})
|
138
|
+
|
139
|
+
return response
|
140
|
+
end
|
141
|
+
def self.create_new_custom_image_with_docker(type,owner,image_name,is_public,is_base,image_extend,python3,tar_path,files)
|
142
|
+
file_name = File.basename tar_path
|
143
|
+
file_size = File.size(tar_path).to_f
|
144
|
+
mime_type = MimeMagic.by_path(tar_path)
|
145
|
+
content_type = !(mime_type.nil? or mime_type.text?) ? mime_type.type : "text/plain"
|
146
|
+
|
147
|
+
upload_resp = Cnvrg::API.request("/users/#{owner}/images/upload_docker", 'POST_FILE', {absolute_path: tar_path, relative_path: tar_path,
|
148
|
+
file_name: file_name, file_size: file_size,
|
149
|
+
file_content_type: content_type,
|
150
|
+
image_name:image_name,is_public:is_public,
|
151
|
+
is_base:is_base,image_extend:image_extend,
|
152
|
+
python3:python3 })
|
153
|
+
|
154
|
+
if Cnvrg::CLI.is_response_success(upload_resp, false)
|
155
|
+
path = upload_resp["result"]["path"]
|
156
|
+
|
157
|
+
s3_res = files.upload_small_files_s3(path, tar_path, content_type)
|
158
|
+
if s3_res
|
159
|
+
image_slug = upload_resp["result"]["id"]
|
160
|
+
response = Cnvrg::API.request("users/#{owner}/images/#{image_slug}/build", 'POST', {instance_type:type,image_extend:image_extend})
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
def self.revoke_custom_new_image(owner,slug)
|
169
|
+
response = Cnvrg::API.request("users/#{owner}/images/#{slug}/revoke_image", 'GET')
|
170
|
+
return response
|
171
|
+
end
|
172
|
+
def self.commit_custom_image(owner,slug,logs)
|
173
|
+
response = Cnvrg::API.request("users/#{owner}/images/#{slug}/commit_custom_image", 'POST', {image_logs:logs})
|
174
|
+
return response
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
def create_custom_image(new_image_name,working_dir,stored_commands)
|
179
|
+
|
180
|
+
python2_arr = get_installed_packages("python2")
|
181
|
+
py2 = python2_arr.join(",") unless python2_arr.nil? or python2_arr.empty?
|
182
|
+
python3_arr = get_installed_packages("python3")
|
183
|
+
py3 = python3_arr.join(",") unless python3_arr.nil? or python3_arr.empty?
|
184
|
+
system_arr = get_installed_packages("system")
|
185
|
+
sys = system_arr.join(",") unless system_arr.nil? or system_arr.empty?
|
186
|
+
|
187
|
+
response = Cnvrg::API.request("users/#{@owner}/projects/#{@project_slug}/images/push", 'POST', {image_slug: @image_slug, py2: py2,py3:py3,
|
188
|
+
dpkg: sys, new_image_name: new_image_name,
|
189
|
+
run_commands:stored_commands})
|
190
|
+
if Cnvrg::CLI.is_response_success(response) and !response["result"]["slug"].nil?
|
191
|
+
container = get_container()
|
192
|
+
name = response["result"]["name"]
|
193
|
+
container = get_container()
|
194
|
+
container.commit({repo:name,tag:"latest"})
|
195
|
+
update_image(name+":latest", container, response["result"]["slug"])
|
196
|
+
File.truncate(working_dir+"/.cnvrg/custom_image.txt", 0)
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
return true
|
201
|
+
|
202
|
+
end
|
203
|
+
|
204
|
+
def update_image(image_name, container, image_slug)
|
205
|
+
config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
|
206
|
+
@image_name = image_name
|
207
|
+
if !@image_name.nil? and !@image_name.empty?
|
208
|
+
@image_name = image_name[0, image_name.index(":")]
|
209
|
+
@image_tag = image_name[image_name.index(":")+1, image_name.size]
|
210
|
+
end
|
211
|
+
config = {project_name: config[:project_name],
|
212
|
+
project_slug: config[:project_slug],
|
213
|
+
owner: config[:owner],
|
214
|
+
docker: true, image_base: @image_name, image_tag: @image_tag, container: container.id, image_slug: image_slug}
|
215
|
+
|
216
|
+
File.open(@working_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
|
217
|
+
end
|
218
|
+
|
219
|
+
def save_installed_libraries(container)
|
220
|
+
begin
|
221
|
+
command = ['/bin/bash', '-lc', '/opt/ds/bin/pip freeze']
|
222
|
+
pip = container.exec(command, tty: true)[0]
|
223
|
+
command = ["/bin/bash", "-lc", "dpkg -l | grep '^ii' | awk '{print $2\"==\"$3}'"]
|
224
|
+
dpkg = container.exec(command, tty: true)[0]
|
225
|
+
File.open(@working_dir+"/.cnvrg/pip_base.txt", "w+") { |f| f.write pip }
|
226
|
+
File.open(@working_dir+"/.cnvrg/dpkg_base.txt", "w+") { |f| f.write dpkg }
|
227
|
+
rescue => e
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
def remote_notebook(notebook_path, instance_type, kernel,data,data_commit)
|
234
|
+
response = Cnvrg::API.request("users/#{@owner}/images/#{@image_slug}/remote_notebook", 'POST', {dir: notebook_path,
|
235
|
+
project_slug: @project_slug,
|
236
|
+
instance_type: instance_type,
|
237
|
+
kernel: kernel,
|
238
|
+
dataset_slug:data,
|
239
|
+
dataset_commit: data_commit})
|
240
|
+
return response
|
241
|
+
end
|
242
|
+
|
243
|
+
def get_installed_packages(repo)
|
244
|
+
container = get_container()
|
245
|
+
case repo
|
246
|
+
when "python2"
|
247
|
+
command = ['/bin/bash', '-lc', '/opt/ds/bin/pip freeze']
|
248
|
+
when "python3"
|
249
|
+
command = ['/bin/bash', '-lc', '/opt/ds3/bin/pip3 freeze']
|
250
|
+
when "system"
|
251
|
+
command = ["/bin/bash", "-lc", "dpkg -l | grep '^ii' | awk '{print $2\"==\"$3}'"]
|
252
|
+
end
|
253
|
+
|
254
|
+
libs = container.exec(command, tty: true)[0]
|
255
|
+
libs_arr = libs.join("").split("\r\n")
|
256
|
+
return libs_arr
|
257
|
+
|
258
|
+
end
|
259
|
+
|
260
|
+
def get_bash_history
|
261
|
+
container = get_container()
|
262
|
+
command = ["/bin/bash", "-lc", "cat /home/ds/.bash_history"]
|
263
|
+
history = container.exec(command, tty: true)[0][0]
|
264
|
+
if history.include? "No such file"
|
265
|
+
history = ""
|
266
|
+
end
|
267
|
+
return history
|
268
|
+
end
|
269
|
+
|
270
|
+
|
271
|
+
def get_image_state
|
272
|
+
python_arr = self.get_installed_packages("python")
|
273
|
+
py = python_arr.join(",") unless python_arr.nil? or python_arr.empty?
|
274
|
+
system_arr = self.get_installed_packages("system")
|
275
|
+
sys = system_arr.join(",") unless system_arr.nil? or system_arr.empty?
|
276
|
+
# bash_history = self.get_bash_history
|
277
|
+
diff = [py, sys]
|
278
|
+
|
279
|
+
end
|
280
|
+
|
281
|
+
def find_image(update=true)
|
282
|
+
config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
|
283
|
+
image_slug = config[:image_slug]
|
284
|
+
if image_slug.nil? or image_slug.empty?
|
285
|
+
image_res = Cnvrg::API.request("users/#{@owner}/images/" + "find", 'POST', {image_name: @image_name})
|
286
|
+
|
287
|
+
if Cnvrg::CLI.is_response_success(image_res)
|
288
|
+
image_slug = image_res["result"]["image"]["slug"]
|
289
|
+
update_slug(image_slug) unless !update
|
290
|
+
return image_slug
|
291
|
+
end
|
292
|
+
else
|
293
|
+
return image_slug
|
294
|
+
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def set_note_url(note_slug)
|
299
|
+
config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
|
300
|
+
config[:notebook_slug] = note_slug
|
301
|
+
File.open(@working_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
|
302
|
+
end
|
303
|
+
def note_slug
|
304
|
+
config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
|
305
|
+
note_slug = config[:notebook_slug]
|
306
|
+
if note_slug.nil? or note_slug.empty?
|
307
|
+
return false
|
308
|
+
else
|
309
|
+
return note_slug
|
310
|
+
end
|
311
|
+
end
|
312
|
+
def remove_note_slug
|
313
|
+
config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
|
314
|
+
config[:notebook_slug] = ""
|
315
|
+
File.open(@working_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
|
316
|
+
|
317
|
+
end
|
318
|
+
|
319
|
+
|
320
|
+
def update_slug(slug)
|
321
|
+
config = YAML.load_file(@working_dir+"/.cnvrg/config.yml")
|
322
|
+
config[:image_slug] = slug
|
323
|
+
File.open(@working_dir+"/.cnvrg/config.yml", "w+") { |f| f.write config.to_yaml }
|
324
|
+
end
|
325
|
+
|
326
|
+
def new_machine(instance_type)
|
327
|
+
title = "#{instance_type} auto created by cli"
|
328
|
+
response = Cnvrg::API.request("users/#{@owner}/machines/new", 'POST', {machine_name: title, instance_type: instance_type})
|
329
|
+
return Cnvrg::CLI.is_response_success(response)
|
330
|
+
|
331
|
+
end
|
332
|
+
|
333
|
+
def update_image_activity(commit, exp_slug)
|
334
|
+
response = Cnvrg::API.request("users/#{@owner}/images/#{@image_slug}/update_activity", 'POST', {commit: commit, project_slug: @project_slug, experiment: exp_slug})
|
335
|
+
return Cnvrg::CLI.is_response_success(response)
|
336
|
+
end
|
337
|
+
|
338
|
+
def handle_image_activity
|
339
|
+
home_dir = File.expand_path('~')
|
340
|
+
zip_dir = "#{home_dir}/.cnvrg/tmp/config.zip"
|
341
|
+
compress = `zip -j #{zip_dir} #{home_dir}/.netrc #{home_dir}/.cnvrg/config.yml`
|
342
|
+
@files = Cnvrg::Files.new(@owner, @project_slug)
|
343
|
+
res_id = @files.upload_exec_file(zip_dir, @image_name, @commit_id)
|
344
|
+
FileUtils.remove zip_dir
|
345
|
+
return res_id
|
346
|
+
end
|
347
|
+
|
348
|
+
|
349
|
+
end
|
350
|
+
|
351
|
+
end
|
data/lib/cnvrg/api.rb
ADDED
@@ -0,0 +1,247 @@
|
|
1
|
+
require 'netrc'
|
2
|
+
require 'faraday'
|
3
|
+
require 'json'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'cnvrg/helpers'
|
6
|
+
require 'logger'
|
7
|
+
|
8
|
+
module Cnvrg
|
9
|
+
class API
|
10
|
+
USER_AGENT = "CnvrgCLI/#{Cnvrg::VERSION}"
|
11
|
+
ENDPOINT_VERSION = 'v1'
|
12
|
+
|
13
|
+
def self.get_api
|
14
|
+
home_dir = File.expand_path('~')
|
15
|
+
config = ""
|
16
|
+
begin
|
17
|
+
if File.exist? home_dir+"/.cnvrg/config.yml"
|
18
|
+
config = YAML.load_file(home_dir+"/.cnvrg/config.yml")
|
19
|
+
else
|
20
|
+
return "https://app.cnvrg.io/api"
|
21
|
+
end
|
22
|
+
|
23
|
+
rescue
|
24
|
+
return "https://app.cnvrg.io/api"
|
25
|
+
end
|
26
|
+
if !config or config.empty? or config.to_h[:api].nil?
|
27
|
+
return "https://app.cnvrg.io/api"
|
28
|
+
else
|
29
|
+
return config.to_h[:api]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
def self.request(resource, method = 'GET', data = {}, parse_request = true)
|
33
|
+
resource = URI::encode resource
|
34
|
+
begin
|
35
|
+
n = Netrc.read
|
36
|
+
rescue => e
|
37
|
+
end
|
38
|
+
|
39
|
+
# Make sure there is an entry for the Acquia API before generating the
|
40
|
+
# requests.
|
41
|
+
if n['cnvrg.io'].nil?
|
42
|
+
puts 'You\'re not logged in'
|
43
|
+
puts 'Please log in via `cnvrg login`'
|
44
|
+
return
|
45
|
+
end
|
46
|
+
|
47
|
+
@user, @pass = n[Cnvrg::Helpers.netrc_domain]
|
48
|
+
begin
|
49
|
+
if !Helpers.is_verify_ssl
|
50
|
+
|
51
|
+
conn = Faraday.new "#{endpoint_uri}", :ssl => {:verify => false}
|
52
|
+
else
|
53
|
+
conn = Faraday.new "#{endpoint_uri}"
|
54
|
+
end
|
55
|
+
conn.headers['Auth-Token'] = @pass
|
56
|
+
conn.headers['User-Agent'] = "#{Cnvrg::API::USER_AGENT}"
|
57
|
+
conn.options.timeout = 420
|
58
|
+
conn.options.open_timeout=180
|
59
|
+
case method
|
60
|
+
when 'GET'
|
61
|
+
retries = 0
|
62
|
+
success = false
|
63
|
+
while !success and retries < 20
|
64
|
+
begin
|
65
|
+
response = conn.get "#{resource}", data
|
66
|
+
success = true
|
67
|
+
Cnvrg::API.parse_version(response)
|
68
|
+
rescue => e
|
69
|
+
Cnvrg::Logger.log_error(e)
|
70
|
+
sleep(5)
|
71
|
+
retries +=1
|
72
|
+
end
|
73
|
+
end
|
74
|
+
if !success
|
75
|
+
return false
|
76
|
+
end
|
77
|
+
if response.to_hash[:status] == 404
|
78
|
+
return false
|
79
|
+
end
|
80
|
+
if parse_request
|
81
|
+
JSON.parse(response.body)
|
82
|
+
else
|
83
|
+
response
|
84
|
+
end
|
85
|
+
when 'POST', 'PUT'
|
86
|
+
conn.options.timeout = 4200
|
87
|
+
conn.options.open_timeout = 180
|
88
|
+
conn.headers['Content-Type'] = "application/json"
|
89
|
+
retries = 0
|
90
|
+
success = false
|
91
|
+
data = data || {}
|
92
|
+
while !success and retries < 20
|
93
|
+
begin
|
94
|
+
response = conn.post "#{resource}", data.to_json if method.eql? 'POST'
|
95
|
+
response = conn.put "#{resource}", data.to_json if method.eql? 'PUT'
|
96
|
+
success = true
|
97
|
+
Cnvrg::API.parse_version(response)
|
98
|
+
|
99
|
+
rescue => e
|
100
|
+
Cnvrg::Logger.log_error(e)
|
101
|
+
sleep(5)
|
102
|
+
retries +=1
|
103
|
+
end
|
104
|
+
end
|
105
|
+
if !success
|
106
|
+
return false
|
107
|
+
end
|
108
|
+
if response.to_hash[:status] == 404
|
109
|
+
return false
|
110
|
+
end
|
111
|
+
if parse_request == true
|
112
|
+
JSON.parse(response.body)
|
113
|
+
else
|
114
|
+
response
|
115
|
+
end
|
116
|
+
when 'POST_JSON'
|
117
|
+
conn.options.timeout = 4200
|
118
|
+
conn.options.open_timeout = 4200
|
119
|
+
conn.headers['Content-Type'] = "application/json"
|
120
|
+
new_data = JSON.dump(data)
|
121
|
+
|
122
|
+
retries = 0
|
123
|
+
success = false
|
124
|
+
|
125
|
+
while !success and retries < 20
|
126
|
+
begin
|
127
|
+
response = conn.post "#{resource}", new_data
|
128
|
+
success = true
|
129
|
+
rescue => e
|
130
|
+
Cnvrg::Logger.log_error(e)
|
131
|
+
sleep(5)
|
132
|
+
retries +=1
|
133
|
+
end
|
134
|
+
end
|
135
|
+
if !success
|
136
|
+
return false
|
137
|
+
end
|
138
|
+
if response.to_hash[:status] == 404
|
139
|
+
return false
|
140
|
+
end
|
141
|
+
if parse_request == true
|
142
|
+
JSON.parse(response.body)
|
143
|
+
else
|
144
|
+
response
|
145
|
+
end
|
146
|
+
when 'POST_FILE'
|
147
|
+
conn = Faraday.new do |fr|
|
148
|
+
fr.headers['Auth-Token'] = @pass
|
149
|
+
fr.headers['User-Agent'] = "#{Cnvrg::API::USER_AGENT}"
|
150
|
+
fr.headers["Content-Type"] = "multipart/form-data"
|
151
|
+
if !Helpers.is_verify_ssl
|
152
|
+
fr.ssl.verify = false
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
fr.request :multipart
|
157
|
+
fr.request :url_encoded
|
158
|
+
fr.request :retry, max: 2, interval: 0.05,interval_randomness: 0.5, backoff_factor: 2
|
159
|
+
fr.adapter :net_http
|
160
|
+
end
|
161
|
+
conn.options.timeout = 4200
|
162
|
+
conn.options.open_timeout =4200
|
163
|
+
|
164
|
+
|
165
|
+
# what if windows?
|
166
|
+
# data[:file] = Faraday::UploadIO.new(data[:absolute_path], content_type)
|
167
|
+
if not File.exists? data[:relative_path]
|
168
|
+
file_base = File.basename(data[:relative_path])
|
169
|
+
|
170
|
+
begin
|
171
|
+
temp_path = File.expand_path('~')+"/.cnvrg/tmp_files/#{file_base}"
|
172
|
+
FileUtils.touch(temp_path)
|
173
|
+
rescue
|
174
|
+
temp_path ="/tmp/#{file_base}"
|
175
|
+
FileUtils.touch(temp_path)
|
176
|
+
end
|
177
|
+
else
|
178
|
+
temp_path = data[:relative_path]
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
data[:file] = Faraday::UploadIO.new("#{temp_path}", "application/tar+gzip")
|
183
|
+
|
184
|
+
response = conn.post "#{endpoint_uri}/#{resource}", data
|
185
|
+
Cnvrg::API.parse_version(response)
|
186
|
+
FileUtils.rm_rf(temp_path)
|
187
|
+
if response.to_hash[:status] == 404
|
188
|
+
return false
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
if parse_request == true
|
193
|
+
JSON.parse(response.body)
|
194
|
+
else
|
195
|
+
response
|
196
|
+
end
|
197
|
+
when 'DELETE'
|
198
|
+
response = conn.delete "#{endpoint_uri}/#{resource}", data
|
199
|
+
Cnvrg::API.parse_version(response)
|
200
|
+
if response.to_hash[:status] == 404
|
201
|
+
return false
|
202
|
+
end
|
203
|
+
if parse_request == true
|
204
|
+
JSON.parse(response.body)
|
205
|
+
else
|
206
|
+
response
|
207
|
+
end
|
208
|
+
else
|
209
|
+
end
|
210
|
+
rescue => e
|
211
|
+
Cnvrg::Logger.log_error(e)
|
212
|
+
return nil
|
213
|
+
rescue SignalException
|
214
|
+
return false
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
def self.endpoint_uri
|
221
|
+
api = get_api()
|
222
|
+
return "#{api}/#{Cnvrg::API::ENDPOINT_VERSION}"
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
def self.display_error(response)
|
227
|
+
"Oops, an error occurred! Reason: #{response['message']}"
|
228
|
+
end
|
229
|
+
|
230
|
+
def self.parse_version(resp)
|
231
|
+
begin
|
232
|
+
version = resp.headers["cnvrg-version"]
|
233
|
+
Cnvrg::Helpers.update_version(version)
|
234
|
+
rescue => e
|
235
|
+
Cnvrg::Logger.log_error(e)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
# Internal: Ensure the response returns a HTTP 200.
|
240
|
+
#
|
241
|
+
# If the response status isn't a HTTP 200, we need to find out why. This
|
242
|
+
# helps identify the issues earlier on and will prevent extra API calls
|
243
|
+
# that won't complete.
|
244
|
+
#
|
245
|
+
# Returns false if the response code isn't a HTTP 200.
|
246
|
+
end
|
247
|
+
end
|