bosh_cli 0.19.1 → 0.19.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/cli/commands/base.rb +37 -0
- data/lib/cli/commands/cloudcheck.rb +13 -29
- data/lib/cli/commands/deployment.rb +6 -27
- data/lib/cli/commands/job_management.rb +12 -17
- data/lib/cli/commands/job_rename.rb +29 -34
- data/lib/cli/commands/log_management.rb +1 -0
- data/lib/cli/commands/maintenance.rb +2 -2
- data/lib/cli/commands/misc.rb +6 -6
- data/lib/cli/commands/release.rb +33 -34
- data/lib/cli/commands/ssh.rb +4 -3
- data/lib/cli/commands/stemcell.rb +9 -29
- data/lib/cli/config.rb +2 -2
- data/lib/cli/core_ext.rb +4 -1
- data/lib/cli/deployment_helper.rb +1 -1
- data/lib/cli/director.rb +159 -73
- data/lib/cli/event_log_renderer.rb +49 -13
- data/lib/cli/release_compiler.rb +6 -9
- data/lib/cli/release_tarball.rb +10 -5
- data/lib/cli/runner.rb +36 -1
- data/lib/cli/task_log_renderer.rb +1 -1
- data/lib/cli/task_tracker.rb +13 -6
- data/lib/cli/version.rb +1 -1
- data/spec/unit/core_ext_spec.rb +5 -1
- data/spec/unit/director_spec.rb +40 -23
- data/spec/unit/job_rename_spec.rb +4 -0
- data/spec/unit/release_tarball_spec.rb +3 -1
- data/spec/unit/runner_spec.rb +20 -0
- data/spec/unit/task_tracker_spec.rb +0 -27
- metadata +4 -4
data/lib/cli/commands/ssh.rb
CHANGED
@@ -22,9 +22,10 @@ module Bosh::Cli::Command
|
|
22
22
|
args.shift
|
23
23
|
end
|
24
24
|
rescue ArgumentError, TypeError
|
25
|
+
# No index given
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
|
+
%w(public_key gateway_host gateway_user).each do |option|
|
28
29
|
pos = args.index("--#{option}")
|
29
30
|
if pos
|
30
31
|
options[option] = args[pos + 1]
|
@@ -98,13 +99,13 @@ module Bosh::Cli::Command
|
|
98
99
|
encrypt_password(password))
|
99
100
|
|
100
101
|
unless results && results.kind_of?(Array) && !results.empty?
|
101
|
-
err("Error setting up ssh, #{results.inspect}, "
|
102
|
+
err("Error setting up ssh, #{results.inspect}, " +
|
102
103
|
"check task logs for more details")
|
103
104
|
end
|
104
105
|
|
105
106
|
results.each do |result|
|
106
107
|
unless result.kind_of?(Hash)
|
107
|
-
err("Unexpected results #{results.inspect}, "
|
108
|
+
err("Unexpected results #{results.inspect}, " +
|
108
109
|
"check task logs for more details")
|
109
110
|
end
|
110
111
|
end
|
@@ -59,19 +59,9 @@ module Bosh::Cli::Command
|
|
59
59
|
|
60
60
|
say("\nUploading stemcell...\n")
|
61
61
|
|
62
|
-
status,
|
63
|
-
|
64
|
-
responses = {
|
65
|
-
:done => "Stemcell uploaded and created",
|
66
|
-
:non_trackable => "Uploaded stemcell but director at '#{target}' " +
|
67
|
-
"doesn't support creation tracking",
|
68
|
-
:track_timeout => "Uploaded stemcell but timed out out " +
|
69
|
-
"while tracking status",
|
70
|
-
:error => "Uploaded stemcell but received an error " +
|
71
|
-
"while tracking status",
|
72
|
-
}
|
62
|
+
status, _ = director.upload_stemcell(stemcell.stemcell_file)
|
73
63
|
|
74
|
-
|
64
|
+
task_report(status, "Stemcell uploaded and created")
|
75
65
|
end
|
76
66
|
|
77
67
|
def list
|
@@ -147,41 +137,31 @@ module Bosh::Cli::Command
|
|
147
137
|
|
148
138
|
url = yaml[stemcell_name]["url"]
|
149
139
|
size = yaml[stemcell_name]["size"]
|
150
|
-
|
151
|
-
|
140
|
+
progress_bar = ProgressBar.new(stemcell_name, size)
|
141
|
+
progress_bar.file_transfer_mode
|
152
142
|
File.open("#{stemcell_name}", "w") { |file|
|
153
143
|
@http_client.get(url) do |chunk|
|
154
144
|
file.write(chunk)
|
155
|
-
|
145
|
+
progress_bar.inc(chunk.size)
|
156
146
|
end
|
157
147
|
}
|
158
|
-
|
148
|
+
progress_bar.finish
|
159
149
|
puts("Download complete.")
|
160
150
|
end
|
161
151
|
|
162
152
|
def delete(name, version)
|
163
153
|
auth_required
|
164
154
|
|
165
|
-
say("You are going to delete stemcell `#{name}
|
155
|
+
say("You are going to delete stemcell `#{name}/#{version}'".red)
|
166
156
|
|
167
157
|
unless confirmed?
|
168
158
|
say("Canceled deleting stemcell".green)
|
169
159
|
return
|
170
160
|
end
|
171
161
|
|
172
|
-
status,
|
173
|
-
|
174
|
-
responses = {
|
175
|
-
:done => "Deleted stemcell #{name} (#{version})",
|
176
|
-
:non_trackable => "Stemcell delete in progress but director " +
|
177
|
-
"at '#{target}' doesn't support task tracking",
|
178
|
-
:track_timeout => "Timed out out while tracking " +
|
179
|
-
"stemcell deletion progress",
|
180
|
-
:error => "Attempted to delete stemcell but received an error " +
|
181
|
-
"while tracking status",
|
182
|
-
}
|
162
|
+
status, _ = director.delete_stemcell(name, version)
|
183
163
|
|
184
|
-
|
164
|
+
task_report(status, "Deleted stemcell `#{name}/#{version}'")
|
185
165
|
end
|
186
166
|
end
|
187
167
|
end
|
data/lib/cli/config.rb
CHANGED
@@ -107,8 +107,8 @@ module Bosh::Cli
|
|
107
107
|
# deployment file.
|
108
108
|
def set_deployment(deployment_file_path)
|
109
109
|
raise MissingTarget, "Must have a target set." if target.nil?
|
110
|
-
@config_file["deployment"] = {
|
111
|
-
@config_file["deployment"] ||= {
|
110
|
+
@config_file["deployment"] = {} if is_old_deployment_config?
|
111
|
+
@config_file["deployment"] ||= {}
|
112
112
|
@config_file["deployment"][target] = deployment_file_path
|
113
113
|
end
|
114
114
|
|
data/lib/cli/core_ext.rb
CHANGED
@@ -108,7 +108,10 @@ module BoshStringExtensions
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def colorize(color_code)
|
111
|
-
if Bosh::Cli::Config.
|
111
|
+
if Bosh::Cli::Config.output.tty? &&
|
112
|
+
Bosh::Cli::Config.colorize &&
|
113
|
+
COLOR_CODES[color_code]
|
114
|
+
|
112
115
|
"#{COLOR_CODES[color_code]}#{self}\e[0m"
|
113
116
|
else
|
114
117
|
self
|
@@ -163,7 +163,7 @@ module Bosh::Cli
|
|
163
163
|
end
|
164
164
|
|
165
165
|
if old_stemcells.size != new_stemcells.size
|
166
|
-
say("Stemcell update seems to be inconsistent with current " +
|
166
|
+
say("Stemcell update seems to be inconsistent with current ".red +
|
167
167
|
"deployment. Please carefully review changes above.".red)
|
168
168
|
unless confirmed?("Are you sure this configuration is correct?")
|
169
169
|
cancel_deployment
|
data/lib/cli/director.rb
CHANGED
@@ -47,12 +47,15 @@ module Bosh
|
|
47
47
|
|
48
48
|
def create_user(username, password)
|
49
49
|
payload = JSON.generate("username" => username, "password" => password)
|
50
|
-
response_code,
|
50
|
+
response_code, _ = post("/users", "application/json", payload)
|
51
51
|
response_code == 204
|
52
52
|
end
|
53
53
|
|
54
|
-
def upload_stemcell(filename)
|
55
|
-
|
54
|
+
def upload_stemcell(filename, options = {})
|
55
|
+
options = options.dup
|
56
|
+
options[:content_type] = "application/x-compressed"
|
57
|
+
|
58
|
+
upload_and_track(:post, "/stemcells", filename, options)
|
56
59
|
end
|
57
60
|
|
58
61
|
def get_version
|
@@ -92,6 +95,17 @@ module Bosh
|
|
92
95
|
get_json("/releases/#{name}")
|
93
96
|
end
|
94
97
|
|
98
|
+
def match_packages(manifest_yaml)
|
99
|
+
url = "/packages/matches"
|
100
|
+
status, body = post(url, "text/yaml", manifest_yaml)
|
101
|
+
|
102
|
+
if status == 200
|
103
|
+
JSON.parse(body)
|
104
|
+
else
|
105
|
+
err(parse_error_message(status, body))
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
95
109
|
def get_deployment(name)
|
96
110
|
status, body = get_json_with_status("/deployments/#{name}")
|
97
111
|
if status == 404
|
@@ -108,43 +122,65 @@ module Bosh
|
|
108
122
|
body
|
109
123
|
end
|
110
124
|
|
111
|
-
def upload_release(filename)
|
112
|
-
|
125
|
+
def upload_release(filename, options = {})
|
126
|
+
options = options.dup
|
127
|
+
options[:content_type] = "application/x-compressed"
|
128
|
+
|
129
|
+
upload_and_track(:post, "/releases", filename, options)
|
113
130
|
end
|
114
131
|
|
115
132
|
def delete_stemcell(name, version, options = {})
|
116
|
-
|
133
|
+
options = options.dup
|
134
|
+
request_and_track(:delete, "/stemcells/#{name}/#{version}", options)
|
117
135
|
end
|
118
136
|
|
119
137
|
def delete_deployment(name, options = {})
|
138
|
+
options = options.dup
|
139
|
+
force = options.delete(:force)
|
140
|
+
|
120
141
|
url = "/deployments/#{name}"
|
121
|
-
query_params = []
|
122
|
-
query_params << "force=true" if options[:force]
|
123
|
-
url += "?#{query_params.join("&")}" if query_params.size > 0
|
124
142
|
|
125
|
-
|
143
|
+
extras = []
|
144
|
+
extras << "force=true" if force
|
145
|
+
|
146
|
+
request_and_track(:delete, add_query_string(url, extras), options)
|
126
147
|
end
|
127
148
|
|
128
149
|
def delete_release(name, options = {})
|
129
|
-
|
150
|
+
options = options.dup
|
151
|
+
force = options.delete(:force)
|
152
|
+
version = options.delete(:version)
|
130
153
|
|
131
|
-
|
132
|
-
query_params << "force=true" if options[:force]
|
133
|
-
query_params << "version=#{options[:version]}" if options[:version]
|
154
|
+
url = "/releases/#{name}"
|
134
155
|
|
135
|
-
|
156
|
+
extras = []
|
157
|
+
extras << "force=true" if force
|
158
|
+
extras << "version=#{version}" if version
|
136
159
|
|
137
|
-
request_and_track(:delete, url)
|
160
|
+
request_and_track(:delete, add_query_string(url, extras), options)
|
138
161
|
end
|
139
162
|
|
140
163
|
def deploy(manifest_yaml, options = {})
|
164
|
+
options = options.dup
|
165
|
+
|
166
|
+
recreate = options.delete(:recreate)
|
167
|
+
options[:content_type] = "text/yaml"
|
168
|
+
options[:payload] = manifest_yaml
|
169
|
+
|
141
170
|
url = "/deployments"
|
142
|
-
|
143
|
-
|
171
|
+
|
172
|
+
extras = []
|
173
|
+
extras << "recreate=true" if recreate
|
174
|
+
|
175
|
+
request_and_track(:post, add_query_string(url, extras), options)
|
144
176
|
end
|
145
177
|
|
146
|
-
def setup_ssh(deployment_name, job, index, user,
|
178
|
+
def setup_ssh(deployment_name, job, index, user,
|
179
|
+
public_key, password, options = {})
|
180
|
+
options = options.dup
|
181
|
+
|
147
182
|
url = "/deployments/#{deployment_name}/ssh"
|
183
|
+
|
148
184
|
payload = {
|
149
185
|
"command" => "setup",
|
150
186
|
"deployment_name" => deployment_name,
|
@@ -159,17 +195,19 @@ module Bosh
|
|
159
195
|
}
|
160
196
|
}
|
161
197
|
|
162
|
-
|
163
|
-
|
164
|
-
JSON.generate(payload), :log_type => "result")
|
198
|
+
options[:payload] = JSON.generate(payload)
|
199
|
+
options[:content_type] = "application/json"
|
165
200
|
|
166
|
-
|
201
|
+
status, task_id = request_and_track(:post, url, options)
|
167
202
|
|
168
|
-
|
203
|
+
# TODO: this needs to be done in command handler, not in director.rb
|
204
|
+
return nil if status != :done
|
205
|
+
JSON.parse(get_task_result_log(task_id))
|
169
206
|
end
|
170
207
|
|
171
|
-
def cleanup_ssh(deployment_name, job, user_regex, indexes)
|
172
|
-
|
208
|
+
def cleanup_ssh(deployment_name, job, user_regex, indexes, options = {})
|
209
|
+
options = options.dup
|
210
|
+
|
173
211
|
url = "/deployments/#{deployment_name}/ssh"
|
174
212
|
|
175
213
|
payload = {
|
@@ -177,68 +215,90 @@ module Bosh
|
|
177
215
|
"deployment_name" => deployment_name,
|
178
216
|
"target" => {
|
179
217
|
"job" => job,
|
180
|
-
"indexes" => indexes.compact
|
218
|
+
"indexes" => (indexes || []).compact
|
181
219
|
},
|
182
220
|
"params" => { "user_regex" => user_regex }
|
183
221
|
}
|
184
222
|
|
185
|
-
|
186
|
-
|
223
|
+
options[:payload] = JSON.generate(payload)
|
224
|
+
options[:content_type] = "application/json"
|
225
|
+
|
226
|
+
request_and_track(:post, url, options)
|
187
227
|
end
|
188
228
|
|
189
229
|
def change_job_state(deployment_name, manifest_yaml,
|
190
|
-
|
230
|
+
job_name, index, new_state, options = {})
|
231
|
+
options = options.dup
|
232
|
+
|
191
233
|
url = "/deployments/#{deployment_name}/jobs/#{job_name}"
|
192
234
|
url += "/#{index}" if index
|
193
235
|
url += "?state=#{new_state}"
|
194
|
-
|
236
|
+
|
237
|
+
options[:payload] = manifest_yaml
|
238
|
+
options[:content_type] = "text/yaml"
|
239
|
+
|
240
|
+
request_and_track(:put, url, options)
|
195
241
|
end
|
196
242
|
|
243
|
+
# TODO: should pass 'force' with options, not as a separate argument
|
197
244
|
def rename_job(deployment_name, manifest_yaml, old_name, new_name,
|
198
|
-
force =
|
245
|
+
force = false, options = {})
|
246
|
+
options = options.dup
|
247
|
+
|
199
248
|
url = "/deployments/#{deployment_name}/jobs/#{old_name}"
|
200
249
|
|
201
|
-
|
202
|
-
|
250
|
+
extras = []
|
251
|
+
extras << "new_name=#{new_name}"
|
252
|
+
extras << "force=true" if force
|
203
253
|
|
204
|
-
|
205
|
-
|
206
|
-
|
254
|
+
options[:content_type] = "text/yaml"
|
255
|
+
options[:payload] = manifest_yaml
|
256
|
+
|
257
|
+
request_and_track(:put, add_query_string(url, extras), options)
|
207
258
|
end
|
208
259
|
|
209
|
-
def fetch_logs(deployment_name, job_name, index, log_type,
|
260
|
+
def fetch_logs(deployment_name, job_name, index, log_type,
|
261
|
+
filters = nil, options = {})
|
262
|
+
options = options.dup
|
263
|
+
|
210
264
|
url = "/deployments/#{deployment_name}/jobs/#{job_name}"
|
211
265
|
url += "/#{index}/logs?type=#{log_type}&filters=#{filters}"
|
212
266
|
|
213
|
-
status, task_id = request_and_track(:get, url)
|
214
|
-
|
267
|
+
status, task_id = request_and_track(:get, url, options)
|
268
|
+
|
269
|
+
# TODO: this should be done in command handler, not in director.rb
|
270
|
+
return nil if status != :done
|
215
271
|
get_task_result(task_id)
|
216
272
|
end
|
217
273
|
|
218
|
-
def fetch_vm_state(deployment_name)
|
274
|
+
def fetch_vm_state(deployment_name, options = {})
|
275
|
+
options = options.dup
|
276
|
+
|
219
277
|
url = "/deployments/#{deployment_name}/vms?format=full"
|
220
278
|
|
221
|
-
status, task_id,
|
222
|
-
request_and_track(:get, url, nil, nil, :log_type => "result")
|
279
|
+
status, task_id = request_and_track(:get, url, options)
|
223
280
|
|
224
|
-
|
281
|
+
# TODO: this should be done in command handler, not in director.rb
|
282
|
+
if status != :done
|
225
283
|
raise DirectorError, "Failed to fetch VMs information from director"
|
226
284
|
end
|
227
285
|
|
286
|
+
output = get_task_result_log(task_id)
|
287
|
+
|
228
288
|
output.to_s.split("\n").map do |vm_state|
|
229
289
|
JSON.parse(vm_state)
|
230
290
|
end
|
231
291
|
end
|
232
292
|
|
233
293
|
def download_resource(id)
|
234
|
-
status, tmp_file,
|
235
|
-
|
294
|
+
status, tmp_file, _ = get("/resources/#{id}",
|
295
|
+
nil, nil, {}, :file => true)
|
236
296
|
|
237
297
|
if status == 200
|
238
298
|
tmp_file
|
239
299
|
else
|
240
|
-
raise DirectorError,
|
241
|
-
|
300
|
+
raise DirectorError,
|
301
|
+
"Cannot download resource `#{id}': HTTP status #{status}"
|
242
302
|
end
|
243
303
|
end
|
244
304
|
|
@@ -269,9 +329,11 @@ module Bosh
|
|
269
329
|
get_json(url)
|
270
330
|
end
|
271
331
|
|
272
|
-
def perform_cloud_scan(deployment_name)
|
332
|
+
def perform_cloud_scan(deployment_name, options = {})
|
333
|
+
options = options.dup
|
273
334
|
url = "/deployments/#{deployment_name}/scans"
|
274
|
-
|
335
|
+
|
336
|
+
request_and_track(:post, url, options)
|
275
337
|
end
|
276
338
|
|
277
339
|
def list_problems(deployment_name)
|
@@ -279,14 +341,18 @@ module Bosh
|
|
279
341
|
get_json(url)
|
280
342
|
end
|
281
343
|
|
282
|
-
def apply_resolutions(deployment_name, resolutions)
|
344
|
+
def apply_resolutions(deployment_name, resolutions, options = {})
|
345
|
+
options = options.dup
|
346
|
+
|
283
347
|
url = "/deployments/#{deployment_name}/problems"
|
284
|
-
|
285
|
-
|
348
|
+
options[:content_type] = "application/json"
|
349
|
+
options[:payload] = JSON.generate("resolutions" => resolutions)
|
350
|
+
|
351
|
+
request_and_track(:put, url, options)
|
286
352
|
end
|
287
353
|
|
288
354
|
def get_current_time
|
289
|
-
|
355
|
+
_, _, headers = get("/info")
|
290
356
|
Time.parse(headers[:date]) rescue nil
|
291
357
|
end
|
292
358
|
|
@@ -320,11 +386,16 @@ module Bosh
|
|
320
386
|
get_task(task_id)["result"]
|
321
387
|
end
|
322
388
|
|
389
|
+
def get_task_result_log(task_id)
|
390
|
+
log, _ = get_task_output(task_id, 0, "result")
|
391
|
+
log
|
392
|
+
end
|
393
|
+
|
323
394
|
def get_task_output(task_id, offset, log_type = nil)
|
324
395
|
uri = "/tasks/#{task_id}/output"
|
325
396
|
uri += "?type=#{log_type}" if log_type
|
326
397
|
|
327
|
-
headers = {
|
398
|
+
headers = {"Range" => "bytes=#{offset}-"}
|
328
399
|
response_code, body, headers = get(uri, nil, nil, headers)
|
329
400
|
|
330
401
|
if response_code == 206 &&
|
@@ -349,20 +420,28 @@ module Bosh
|
|
349
420
|
end
|
350
421
|
end
|
351
422
|
|
352
|
-
|
353
|
-
|
354
|
-
|
423
|
+
# Perform director HTTP request and track director task (if request
|
424
|
+
# started one).
|
425
|
+
# @param [Symbol] method HTTP method
|
426
|
+
# @param [String] uri URI
|
427
|
+
# @param [Hash] options Request and tracking options
|
428
|
+
def request_and_track(method, uri, options = {})
|
429
|
+
options = options.dup
|
430
|
+
|
431
|
+
content_type = options.delete(:content_type)
|
432
|
+
payload = options.delete(:payload)
|
433
|
+
track_opts = options
|
434
|
+
|
435
|
+
http_status, _, headers = request(method, uri, content_type, payload)
|
355
436
|
location = headers[:location]
|
356
437
|
redirected = http_status == 302
|
357
438
|
task_id = nil
|
358
|
-
output = nil
|
359
439
|
|
360
440
|
if redirected
|
361
441
|
if location =~ /\/tasks\/(\d+)\/?$/ # Looks like we received task URI
|
362
442
|
task_id = $1
|
363
|
-
tracker = Bosh::Cli::TaskTracker.new(self, task_id,
|
443
|
+
tracker = Bosh::Cli::TaskTracker.new(self, task_id, track_opts)
|
364
444
|
status = tracker.track
|
365
|
-
output = tracker.output
|
366
445
|
else
|
367
446
|
status = :non_trackable
|
368
447
|
end
|
@@ -370,13 +449,12 @@ module Bosh
|
|
370
449
|
status = :failed
|
371
450
|
end
|
372
451
|
|
373
|
-
[status, task_id
|
452
|
+
[status, task_id]
|
374
453
|
end
|
375
454
|
|
376
|
-
def upload_and_track(
|
455
|
+
def upload_and_track(method, uri, filename, options = {})
|
377
456
|
file = FileWithProgressBar.open(filename, "r")
|
378
|
-
method
|
379
|
-
request_and_track(method, uri, content_type, file, options)
|
457
|
+
request_and_track(method, uri, options.merge(:payload => file))
|
380
458
|
ensure
|
381
459
|
file.stop_progress_bar if file
|
382
460
|
end
|
@@ -384,6 +462,8 @@ module Bosh
|
|
384
462
|
def request(method, uri, content_type = nil, payload = nil,
|
385
463
|
headers = {}, options = {})
|
386
464
|
headers = headers.dup
|
465
|
+
tmp_file = nil
|
466
|
+
|
387
467
|
headers["Content-Type"] = content_type if content_type
|
388
468
|
|
389
469
|
if options[:file]
|
@@ -429,16 +509,14 @@ module Bosh
|
|
429
509
|
end
|
430
510
|
|
431
511
|
def parse_error_message(status, body)
|
432
|
-
parsed_body = JSON.parse(body.to_s)
|
512
|
+
parsed_body = JSON.parse(body.to_s) rescue {}
|
433
513
|
|
434
514
|
if parsed_body["code"] && parsed_body["description"]
|
435
|
-
"
|
436
|
-
|
515
|
+
"Error %s: %s" % [parsed_body["code"],
|
516
|
+
parsed_body["description"]]
|
437
517
|
else
|
438
|
-
"
|
518
|
+
"HTTP %s: %s" % [status, body]
|
439
519
|
end
|
440
|
-
rescue JSON::ParserError
|
441
|
-
"Director error (HTTP %s): %s" % [status, body]
|
442
520
|
end
|
443
521
|
|
444
522
|
private
|
@@ -463,7 +541,7 @@ module Bosh
|
|
463
541
|
|
464
542
|
rescue HTTPClient::BadResponseError => e
|
465
543
|
err("Received bad HTTP response from director: #{e}")
|
466
|
-
rescue URI::Error, SocketError,
|
544
|
+
rescue URI::Error, SocketError, SystemCallError
|
467
545
|
raise # We handle these upstream
|
468
546
|
rescue => e
|
469
547
|
# httpclient (sadly) doesn't have a generic exception
|
@@ -478,13 +556,21 @@ module Bosh
|
|
478
556
|
end
|
479
557
|
|
480
558
|
def get_json_with_status(url)
|
481
|
-
status, body,
|
559
|
+
status, body, _ = get(url, "application/json")
|
482
560
|
body = JSON.parse(body) if status == 200
|
483
561
|
[status, body]
|
484
562
|
rescue JSON::ParserError
|
485
563
|
raise DirectorError, "Cannot parse director response: #{body}"
|
486
564
|
end
|
487
565
|
|
566
|
+
def add_query_string(url, parts)
|
567
|
+
if parts.size > 0
|
568
|
+
"#{url}?#{parts.join("&")}"
|
569
|
+
else
|
570
|
+
url
|
571
|
+
end
|
572
|
+
end
|
573
|
+
|
488
574
|
end
|
489
575
|
|
490
576
|
class FileWithProgressBar < ::File
|