cnvrg 0.0.2
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 +7 -0
- data/bin/cnvrg +5 -0
- data/cnvrg.gemspec +27 -0
- data/lib/cnvrg.rb +10 -0
- data/lib/cnvrg/api.rb +106 -0
- data/lib/cnvrg/auth.rb +74 -0
- data/lib/cnvrg/cli.rb +574 -0
- data/lib/cnvrg/experiment.rb +26 -0
- data/lib/cnvrg/files.rb +115 -0
- data/lib/cnvrg/helpers.rb +90 -0
- data/lib/cnvrg/old_cli.rb +332 -0
- data/lib/cnvrg/project.rb +237 -0
- data/lib/cnvrg/version.rb +3 -0
- metadata +165 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module Cnvrg
|
2
|
+
class Experiment
|
3
|
+
attr_reader :slug
|
4
|
+
def initialize(owner, project_slug)
|
5
|
+
@project_slug = project_slug
|
6
|
+
@owner = owner
|
7
|
+
@base_resource = "users/#{owner}/projects/#{project_slug}/"
|
8
|
+
@slug = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def start(input, platform, machine_name, start_commit,name)
|
12
|
+
res = Cnvrg::API.request(@base_resource + "experiment/start", 'POST', { input: input, platform: platform, machine_name: machine_name, start_commit: start_commit , title:name})
|
13
|
+
Cnvrg::CLI.is_response_success(res)
|
14
|
+
|
15
|
+
@slug = res.to_h["result"].to_h["slug"]
|
16
|
+
|
17
|
+
return res
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def end(output, exit_status, end_commit,cpu_average, memory_average)
|
22
|
+
response = Cnvrg::API.request(@base_resource + "experiment/end", 'POST', { output: output, exp_slug: @slug, exit_status: exit_status, end_commit: end_commit, cpu_average:cpu_average,memory_average:memory_average })
|
23
|
+
Cnvrg::CLI.is_response_success(response)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/cnvrg/files.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'mimemagic'
|
2
|
+
require 'pry'
|
3
|
+
module Cnvrg
|
4
|
+
class Files
|
5
|
+
|
6
|
+
attr_reader :base_resource
|
7
|
+
|
8
|
+
def initialize(owner, project_slug)
|
9
|
+
@project_slug = project_slug
|
10
|
+
@owner = owner
|
11
|
+
@base_resource = "users/#{owner}/projects/#{project_slug}/"
|
12
|
+
end
|
13
|
+
|
14
|
+
def upload_file(absolute_path, relative_path, commit_sha1)
|
15
|
+
file_name = File.basename relative_path
|
16
|
+
file_size = File.size(relative_path).to_f
|
17
|
+
upload_resp = Cnvrg::API.request(@base_resource + "upload_file", 'POST_FILE', { absolute_path: absolute_path, relative_path: relative_path,
|
18
|
+
commit_sha1: commit_sha1, file_name: file_name ,file_size:file_size})
|
19
|
+
if Cnvrg::CLI.is_response_success(upload_resp, false)
|
20
|
+
path = upload_resp["result"]["path"]
|
21
|
+
s3_res = upload_s3(path,relative_path)
|
22
|
+
if s3_res
|
23
|
+
Cnvrg::API.request(@base_resource + "update_s3", 'POST', { path:path,commit_id:upload_resp["result"]["commit_id"],
|
24
|
+
blob_id:upload_resp["result"]["blob_id"]})
|
25
|
+
return true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
return false
|
29
|
+
end
|
30
|
+
def upload_s3(url,file)
|
31
|
+
url = URI.parse(url)
|
32
|
+
mime_type = MimeMagic.by_path(file)
|
33
|
+
content_type = !mime_type.nil? ? mime_type.type : ""
|
34
|
+
file = File.open(file, "rb")
|
35
|
+
body = file.read
|
36
|
+
begin
|
37
|
+
Net::HTTP.start(url.host) do |http|
|
38
|
+
http.send_request("PUT", url.request_uri, body, {
|
39
|
+
"content-type" => content_type,
|
40
|
+
})
|
41
|
+
end
|
42
|
+
return true
|
43
|
+
rescue Interrupt
|
44
|
+
return false
|
45
|
+
rescue => e
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
def upload_url(file_path)
|
50
|
+
response = Cnvrg::API.request(@base_resource + "upload_url", 'POST', { file_s3_path: file_path})
|
51
|
+
if Cnvrg::CLI.is_response_success(response, false)
|
52
|
+
return response
|
53
|
+
else
|
54
|
+
return nil
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
def delete_file(absolute_path, relative_path, commit_sha1)
|
59
|
+
response = Cnvrg::API.request(@base_resource + "delete_file", 'DELETE',{ absolute_path: absolute_path, relative_path: relative_path, commit_sha1: commit_sha1 })
|
60
|
+
return Cnvrg::CLI.is_response_success(response, false)
|
61
|
+
end
|
62
|
+
|
63
|
+
def delete_dir(absolute_path, relative_path, commit_sha1)
|
64
|
+
response = Cnvrg::API.request(@base_resource + "delete_dir", 'DELETE', { absolute_path: absolute_path, relative_path: relative_path, commit_sha1: commit_sha1 })
|
65
|
+
return Cnvrg::CLI.is_response_success(response, false)
|
66
|
+
end
|
67
|
+
|
68
|
+
def create_dir(absolute_path, relative_path, commit_sha1)
|
69
|
+
response = Cnvrg::API.request(@base_resource + "create_dir", 'POST',{ absolute_path: absolute_path, relative_path: relative_path, commit_sha1: commit_sha1 })
|
70
|
+
return Cnvrg::CLI.is_response_success(response, false)
|
71
|
+
end
|
72
|
+
|
73
|
+
def download_file(absolute_path, relative_path, project_home, conflict=false)
|
74
|
+
res = Cnvrg::API.request(@base_resource + "download_file", 'POST', { absolute_path: absolute_path, relative_path: relative_path })
|
75
|
+
Cnvrg::CLI.is_response_success(res, false)
|
76
|
+
if res["result"]
|
77
|
+
res = res["result"]
|
78
|
+
return false if res["link"].empty? or res["filename"].empty?
|
79
|
+
filename = res["filename"]
|
80
|
+
file_location = absolute_path.gsub(/#{filename}\/?$/, "")
|
81
|
+
|
82
|
+
FileUtils.mkdir_p project_home + "/" + file_location
|
83
|
+
filename += ".conflict" if conflict
|
84
|
+
|
85
|
+
File.open("#{project_home}/#{file_location}/#{filename}", "wb") do |file|
|
86
|
+
file.write open(res["link"]).read
|
87
|
+
end
|
88
|
+
else
|
89
|
+
return false
|
90
|
+
end
|
91
|
+
return true
|
92
|
+
end
|
93
|
+
|
94
|
+
def download_dir(absolute_path, relative_path, project_home)
|
95
|
+
FileUtils.mkdir_p("#{project_home}/#{absolute_path}")
|
96
|
+
end
|
97
|
+
|
98
|
+
def start_commit
|
99
|
+
|
100
|
+
response = Cnvrg::API.request("#{base_resource}/commit/start", 'POST', { project_slug: @project_slug,
|
101
|
+
username: @owner} )
|
102
|
+
Cnvrg::CLI.is_response_success(response)
|
103
|
+
return response
|
104
|
+
end
|
105
|
+
|
106
|
+
def end_commit(commit_sha1)
|
107
|
+
response = Cnvrg::API.request("#{base_resource}/commit/end", 'POST', { commit_sha1: commit_sha1 } )
|
108
|
+
return response
|
109
|
+
end
|
110
|
+
def rollback_commit(commit_sha1)
|
111
|
+
response = Cnvrg::API.request("#{base_resource}/commit/rollback", 'POST', { commit_sha1: commit_sha1 } )
|
112
|
+
Cnvrg::CLI.is_response_success(response, false)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Cnvrg
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
extend self
|
5
|
+
def checkmark
|
6
|
+
checkmark = "\u2713"
|
7
|
+
return checkmark.encode('utf-8')
|
8
|
+
end
|
9
|
+
|
10
|
+
def remote_url
|
11
|
+
"https://cnvrg.io"
|
12
|
+
end
|
13
|
+
|
14
|
+
def windows?
|
15
|
+
!!(RUBY_PLATFORM =~ /mswin32|mingw32/)
|
16
|
+
end
|
17
|
+
|
18
|
+
def mac?
|
19
|
+
!!(RUBY_PLATFORM =~ /-darwin\d/)
|
20
|
+
end
|
21
|
+
|
22
|
+
def linux?
|
23
|
+
not mac? and not windows?
|
24
|
+
end
|
25
|
+
|
26
|
+
def cnvrgignore_content
|
27
|
+
%{
|
28
|
+
# cnvrg ignore: Ignore the following directories and files
|
29
|
+
# for example:
|
30
|
+
# some_dir/
|
31
|
+
# some_file.txt
|
32
|
+
}.strip
|
33
|
+
end
|
34
|
+
|
35
|
+
def readme_content
|
36
|
+
%{
|
37
|
+
# README
|
38
|
+
|
39
|
+
This README would normally contain some context and description about the project.
|
40
|
+
|
41
|
+
Things you may want to cover:
|
42
|
+
|
43
|
+
* Data description
|
44
|
+
|
45
|
+
* Benchmark and measurement guidelines
|
46
|
+
|
47
|
+
* Used algorithms
|
48
|
+
|
49
|
+
* Scores
|
50
|
+
|
51
|
+
* Configurations
|
52
|
+
|
53
|
+
* Requirements
|
54
|
+
|
55
|
+
* How to run the experiments
|
56
|
+
|
57
|
+
* ...}.strip
|
58
|
+
end
|
59
|
+
|
60
|
+
def netrc_domain
|
61
|
+
"cnvrg.io"
|
62
|
+
end
|
63
|
+
|
64
|
+
def look_for_in_path(path, name)
|
65
|
+
url_split = path.split("/")
|
66
|
+
url_split.each_with_index do |u, i|
|
67
|
+
if u == name
|
68
|
+
return i
|
69
|
+
end
|
70
|
+
end
|
71
|
+
return -1
|
72
|
+
end
|
73
|
+
|
74
|
+
# cpu
|
75
|
+
|
76
|
+
def cpu_time
|
77
|
+
Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID, :microsecond)
|
78
|
+
end
|
79
|
+
|
80
|
+
def wall_time
|
81
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC, :microsecond)
|
82
|
+
end
|
83
|
+
|
84
|
+
# memory
|
85
|
+
#
|
86
|
+
def get_mem(pid)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,332 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'commander/import'
|
5
|
+
require "open4"
|
6
|
+
require 'netrc'
|
7
|
+
require 'net/http'
|
8
|
+
require 'uri'
|
9
|
+
require 'json'
|
10
|
+
require 'yaml'
|
11
|
+
require 'digest' # sha1
|
12
|
+
|
13
|
+
# DEV VERSION
|
14
|
+
#require 'pry'
|
15
|
+
#
|
16
|
+
|
17
|
+
|
18
|
+
program :name, 'cnvrg'
|
19
|
+
program :version, '0.0.1'
|
20
|
+
program :description, 'cnvrg\'s cli for running scripts'
|
21
|
+
|
22
|
+
command :idx do |c|
|
23
|
+
c.action do |args,options|
|
24
|
+
generate_idx
|
25
|
+
end
|
26
|
+
end
|
27
|
+
command :status do |c|
|
28
|
+
c.action do |args,options|
|
29
|
+
status
|
30
|
+
end
|
31
|
+
end
|
32
|
+
command :run do |c|
|
33
|
+
c.syntax = 'cnvrg run script [options]'
|
34
|
+
c.summary = 'monitor run of script'
|
35
|
+
c.description = 'Runs scripts and sending notification when finished'
|
36
|
+
c.option '--script_args script arguments', String, 'script arguments if exist'
|
37
|
+
c.option '--sms', String, 'set sms if you want to be notify by sms when the run is over'
|
38
|
+
c.option '--email', String, 'set email if you want to be notify by email when the run is over'
|
39
|
+
c.option '--silent', String, 'set silent if you want to run script in non-blocking'
|
40
|
+
c.action do |args, options|
|
41
|
+
is_exist = verify_auth_exist()
|
42
|
+
unless is_exist
|
43
|
+
puts("You have to be logged in to continue. Please login.\n")
|
44
|
+
loged_in = login_process()
|
45
|
+
if !loged_in
|
46
|
+
puts("Error: Couldn't logged you in, please run cnvr login separately")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
silent = ''
|
51
|
+
if options.silent
|
52
|
+
silent = '&'
|
53
|
+
end
|
54
|
+
script = args[0]
|
55
|
+
if args.length != 1
|
56
|
+
puts "Error: only one script should be listed to run"
|
57
|
+
found = false
|
58
|
+
args.each do |arg|
|
59
|
+
ans = agree("should I run #{arg}?")
|
60
|
+
if ans
|
61
|
+
found = true
|
62
|
+
script = arg
|
63
|
+
break
|
64
|
+
end
|
65
|
+
end
|
66
|
+
if not found
|
67
|
+
exit(0)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
#check if file exist
|
71
|
+
exist = File.file?(script)
|
72
|
+
if not exist
|
73
|
+
puts "Error: Can't find #{script}, try using the full path"
|
74
|
+
exit(0)
|
75
|
+
end
|
76
|
+
puts "Running #{script} with args: #{options.script_args}"
|
77
|
+
body = {try: 'yay'}.to_json
|
78
|
+
puts run(true,body)
|
79
|
+
pid, stdin, stdout, stderr = Open4::popen4 "sh"
|
80
|
+
stdin.puts "./#{script} #{options.script_args}"
|
81
|
+
stdin.close
|
82
|
+
|
83
|
+
ignored, status = Process::waitpid2 pid
|
84
|
+
|
85
|
+
#try to run
|
86
|
+
if stderr.read.strip.include? "Permission denied"
|
87
|
+
ans = agree("Your script #{script} isn't executable, should I make it executable?")
|
88
|
+
if ans
|
89
|
+
puts "Making #{script} executable"
|
90
|
+
run_result = %x(chmod +x ./#{script} 2>&1)
|
91
|
+
if run_result.include? "Operation not permitted"
|
92
|
+
puts "Can't make script executable,you should first run sudo chmod +x #{script}"
|
93
|
+
exit(0)
|
94
|
+
end
|
95
|
+
puts "Running again #{script} with args: #{options.script_args}"
|
96
|
+
|
97
|
+
pid, stdin, stdout, stderr = Open4::popen4 "sh"
|
98
|
+
stdin.puts "./#{script} #{options.script_args}"
|
99
|
+
stdin.close
|
100
|
+
ignored, status = Process::waitpid2 pid
|
101
|
+
|
102
|
+
if !stderr.read.strip.empty?
|
103
|
+
puts "Error: #{stderr.read.strip}"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
puts stdout.read.strip
|
108
|
+
# send results to the server
|
109
|
+
puts "Finished running with status #{status.exitstatus}"
|
110
|
+
puts run(false, body)
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
command :new do |c|
|
116
|
+
c.syntax = "cnvrg new project-name"
|
117
|
+
c.summary = "Create a new data science project"
|
118
|
+
|
119
|
+
c.action do |args, options|
|
120
|
+
is_exist = verify_auth_exist()
|
121
|
+
unless is_exist
|
122
|
+
"You have to login"
|
123
|
+
else
|
124
|
+
if args[0].to_s.size == 0
|
125
|
+
exit(0)
|
126
|
+
else
|
127
|
+
new(args[0])
|
128
|
+
link_dir(args[0], "")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
command :login do |c|
|
135
|
+
c.syntax = 'cnvrg login'
|
136
|
+
c.summary = 'login to cnvrg app'
|
137
|
+
c.description = 'Login to the CNVRG system'
|
138
|
+
c.option '--reset', String, 'set reset if you want to change current login credentials'
|
139
|
+
c.action do |args, options|
|
140
|
+
n = Netrc.read
|
141
|
+
user, pass = n["cnvrg.io"]
|
142
|
+
if user and pass
|
143
|
+
relogin = agree("You are already authenticated with email: #{user}, do you want to login again? (This will delete you're current login credentials")
|
144
|
+
if !relogin
|
145
|
+
exit(0)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
if options.reset
|
149
|
+
n["cnvrg.io"] = "", ""
|
150
|
+
|
151
|
+
end
|
152
|
+
login_process()
|
153
|
+
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def login_process()
|
159
|
+
n = Netrc.read
|
160
|
+
|
161
|
+
email = ask("Please enter your email")
|
162
|
+
email_regex = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
|
163
|
+
is_valid = email_regex.match(email)
|
164
|
+
while !is_valid do
|
165
|
+
email = ask("Please enter a valid email address:")
|
166
|
+
is_valid = email_regex.match(email)
|
167
|
+
end
|
168
|
+
|
169
|
+
password = ask("Please enter your password: ") { |q| q.echo = false }
|
170
|
+
#send API to login
|
171
|
+
token = sign_in(email, password)
|
172
|
+
count = 0
|
173
|
+
while token.nil? and count<3 do
|
174
|
+
do_retry = agree("Wrong email or password, try again?")
|
175
|
+
if do_retry
|
176
|
+
count +=1
|
177
|
+
email = ask("Please enter your email")
|
178
|
+
password = ask("Please enter your password: ") { |q| q.echo = false }
|
179
|
+
token = sign_in(email, password)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
if token.nil?
|
183
|
+
puts "Error: Too many sign in retries"
|
184
|
+
exit(0)
|
185
|
+
else
|
186
|
+
|
187
|
+
|
188
|
+
n.new_item_prefix = "# This entry was added automatically by CNVRG\n"
|
189
|
+
n["cnvrg.io"] = email, token
|
190
|
+
n.save
|
191
|
+
puts "Great, you're in."
|
192
|
+
return true
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def sign_in(email, password)
|
197
|
+
url = URI.parse("http://localhost:3000/api/v1/users/sign_in")
|
198
|
+
|
199
|
+
req = Net::HTTP::Post.new(url.path)
|
200
|
+
req.add_field("EMAIL", email)
|
201
|
+
req.add_field("PASSWORD", password)
|
202
|
+
|
203
|
+
response = Net::HTTP.new(url.host, url.port).start do |http|
|
204
|
+
http.request(req)
|
205
|
+
end
|
206
|
+
|
207
|
+
result = JSON.parse(response.body)
|
208
|
+
if result["status"] == 200
|
209
|
+
return result["token"]
|
210
|
+
else
|
211
|
+
return nil
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def verify_auth_exist
|
216
|
+
n = Netrc.read
|
217
|
+
user, pass = n["cnvrg.io"]
|
218
|
+
if user.nil? or pass.nil?
|
219
|
+
puts "Please login first, using \"cnvrg login\" command"
|
220
|
+
return false
|
221
|
+
end
|
222
|
+
return true
|
223
|
+
end
|
224
|
+
|
225
|
+
def get_logged_token
|
226
|
+
n = Netrc.read
|
227
|
+
user, token = n["cnvrg.io"]
|
228
|
+
return token
|
229
|
+
|
230
|
+
end
|
231
|
+
def run(is_start, body)
|
232
|
+
token = get_logged_token()
|
233
|
+
if is_start
|
234
|
+
url = URI.parse("http://localhost:3000/api/v1/cli/start_run")
|
235
|
+
else
|
236
|
+
url = URI.parse("http://localhost:3000/api/v1/cli/end_run")
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
req = Net::HTTP::Post.new(url.path)
|
241
|
+
req.add_field("AUTH_TOKEN", token)
|
242
|
+
req.body = body
|
243
|
+
response = Net::HTTP.new(url.host, url.port).start do |http|
|
244
|
+
http.request(req)
|
245
|
+
end
|
246
|
+
|
247
|
+
result = JSON.parse(response.body)
|
248
|
+
puts result
|
249
|
+
end
|
250
|
+
|
251
|
+
def new(project_name)
|
252
|
+
begin
|
253
|
+
`mkdir -p #{project_name} #{project_name}/data #{project_name}/models #{project_name}/notebooks #{project_name}/src #{project_name}/src/data #{project_name}/src/features #{project_name}/src/models #{project_name}/src/visualizations #{project_name}/.cnvrg`
|
254
|
+
`touch #{project_name}/README.md`
|
255
|
+
`touch #{project_name}/.cnvrgignore`
|
256
|
+
rescue
|
257
|
+
"Error"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def link_dir(project_name, user, host="cnvrg.io")
|
262
|
+
`touch #{project_name}/.cnvrg/project`
|
263
|
+
`echo "owner: #{user}\nproject_slug: #{project_name}\nhost: #{host}" >> #{project_name}/.cnvrg/project`
|
264
|
+
end
|
265
|
+
|
266
|
+
def download
|
267
|
+
|
268
|
+
status_output = status
|
269
|
+
downloadables = status_output["updated_on_server"].merge(status_output["deleted"])
|
270
|
+
|
271
|
+
|
272
|
+
downloadables.each do |d|
|
273
|
+
if d[-1] == "/"
|
274
|
+
# make dir
|
275
|
+
else
|
276
|
+
files << #download(d)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def upload
|
281
|
+
|
282
|
+
end
|
283
|
+
|
284
|
+
def generate_idx
|
285
|
+
|
286
|
+
idx = Hash.new(0)
|
287
|
+
list = Dir['**/**']
|
288
|
+
|
289
|
+
# remove files that are in CNVRGIGNORE
|
290
|
+
# list.select { |x| ! cnvrgignore.include? x }
|
291
|
+
|
292
|
+
list.each do |e|
|
293
|
+
if File.directory? e
|
294
|
+
idx[e+"/"] = nil
|
295
|
+
else
|
296
|
+
idx[e] = { sha1: Digest::SHA1.hexdigest(File.read(e)),
|
297
|
+
commit_time: nil }
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
File.open("hello/.cnvrg/idx.yml", 'w') { |f| f.write idx.to_yaml }
|
302
|
+
|
303
|
+
|
304
|
+
end
|
305
|
+
|
306
|
+
def status
|
307
|
+
url = URI.parse("http://localhost:3000/api/v1/users/yochze/projects/porject/status")
|
308
|
+
token = get_logged_token()
|
309
|
+
load_idx = YAML.load(File.read("hello/.cnvrg/idx.yml"))
|
310
|
+
req = Net::HTTP::Get.new(url, 'Content-Type' => 'application/json')
|
311
|
+
req.add_field("AUTH_TOKEN", token)
|
312
|
+
req.body = { snapshot: load_idx }.to_json
|
313
|
+
response = Net::HTTP.new(url.host, url.port).start do |http|
|
314
|
+
http.request(req)
|
315
|
+
end
|
316
|
+
|
317
|
+
result = JSON.parse(response.body)
|
318
|
+
|
319
|
+
result["status"]["added"].each do |a|
|
320
|
+
puts "A:\t#{a}"
|
321
|
+
end
|
322
|
+
|
323
|
+
result["status"]["updated_on_server"].each do |a|
|
324
|
+
puts "M:\t#{a}"
|
325
|
+
end
|
326
|
+
|
327
|
+
result["status"]["deleted"].each do |a|
|
328
|
+
puts "D:\t#{a}"
|
329
|
+
end
|
330
|
+
|
331
|
+
return result["status"]
|
332
|
+
end
|