bosh_cli 1.5.0.pre.1623 → 1.5.0.pre.1633
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.
- data/lib/cli.rb +1 -4
- data/lib/cli/client/director.rb +1 -1
- data/lib/cli/commands/task.rb +2 -2
- data/lib/cli/director_task.rb +43 -50
- data/lib/cli/task_tracking.rb +9 -0
- data/lib/cli/{event_log_renderer.rb → task_tracking/event_log_renderer.rb} +37 -70
- data/lib/cli/{null_renderer.rb → task_tracking/null_task_log_renderer.rb} +2 -6
- data/lib/cli/task_tracking/stage_progress_bar.rb +59 -0
- data/lib/cli/{task_log_renderer.rb → task_tracking/task_log_renderer.rb} +8 -8
- data/lib/cli/task_tracking/task_tracker.rb +148 -0
- data/lib/cli/version.rb +1 -1
- metadata +13 -11
- data/lib/cli/task_tracker.rb +0 -154
data/lib/cli.rb
CHANGED
@@ -59,11 +59,8 @@ require 'cli/packaging_helper'
|
|
59
59
|
require 'cli/package_builder'
|
60
60
|
require 'cli/job_builder'
|
61
61
|
require 'cli/changeset_helper'
|
62
|
-
require 'cli/task_tracker'
|
63
|
-
require 'cli/task_log_renderer'
|
64
|
-
require 'cli/event_log_renderer'
|
65
|
-
require 'cli/null_renderer'
|
66
62
|
require 'cli/deployment_manifest_compiler'
|
63
|
+
require 'cli/task_tracking'
|
67
64
|
|
68
65
|
require 'cli/release'
|
69
66
|
require 'cli/release_builder'
|
data/lib/cli/client/director.rb
CHANGED
@@ -570,7 +570,7 @@ module Bosh
|
|
570
570
|
if location =~ /\/tasks\/(\d+)\/?$/ # Looks like we received task URI
|
571
571
|
task_id = $1
|
572
572
|
if @track_tasks
|
573
|
-
tracker = Bosh::Cli::TaskTracker.new(self, task_id, track_opts)
|
573
|
+
tracker = Bosh::Cli::TaskTracking::TaskTracker.new(self, task_id, track_opts)
|
574
574
|
status = tracker.track
|
575
575
|
else
|
576
576
|
status = :running
|
data/lib/cli/commands/task.rb
CHANGED
@@ -57,7 +57,7 @@ module Bosh::Cli::Command
|
|
57
57
|
err("Task id must be a positive integer")
|
58
58
|
end
|
59
59
|
|
60
|
-
tracker = Bosh::Cli::TaskTracker.new(director, task_id, track_options)
|
60
|
+
tracker = Bosh::Cli::TaskTracking::TaskTracker.new(director, task_id, track_options)
|
61
61
|
tracker.track
|
62
62
|
end
|
63
63
|
|
@@ -132,4 +132,4 @@ module Bosh::Cli::Command
|
|
132
132
|
use_filter ? 1 : 2
|
133
133
|
end
|
134
134
|
end
|
135
|
-
end
|
135
|
+
end
|
data/lib/cli/director_task.rb
CHANGED
@@ -1,64 +1,57 @@
|
|
1
|
-
|
1
|
+
module Bosh::Cli
|
2
|
+
class DirectorTask
|
3
|
+
attr_accessor :offset
|
4
|
+
|
5
|
+
def initialize(director, task_id, log_type = nil)
|
6
|
+
@director = director
|
7
|
+
@task_id = task_id
|
8
|
+
@offset = 0
|
9
|
+
@log_type = log_type
|
10
|
+
@buf = ""
|
11
|
+
end
|
2
12
|
|
3
|
-
|
4
|
-
|
5
|
-
|
13
|
+
def state
|
14
|
+
@director.get_task_state(@task_id)
|
15
|
+
end
|
6
16
|
|
7
|
-
|
17
|
+
def result
|
18
|
+
@director.get_task_result(@task_id)
|
19
|
+
end
|
8
20
|
|
9
|
-
|
10
|
-
|
11
|
-
@task_id = task_id
|
12
|
-
@offset = 0
|
13
|
-
@log_type = log_type
|
14
|
-
@buf = ""
|
15
|
-
end
|
21
|
+
def output
|
22
|
+
body, new_offset = @director.get_task_output(@task_id, @offset, @log_type)
|
16
23
|
|
17
|
-
|
18
|
-
@director.get_task_state(@task_id)
|
19
|
-
end
|
24
|
+
@buf << body if body
|
20
25
|
|
21
|
-
|
22
|
-
@
|
26
|
+
if new_offset
|
27
|
+
@offset = new_offset
|
28
|
+
else
|
29
|
+
return flush_output
|
23
30
|
end
|
24
31
|
|
25
|
-
|
26
|
-
body, new_offset = @director.get_task_output(@task_id, @offset,
|
27
|
-
@log_type)
|
28
|
-
|
29
|
-
@buf << body if body
|
30
|
-
|
31
|
-
if new_offset
|
32
|
-
@offset = new_offset
|
33
|
-
else
|
34
|
-
return flush_output
|
35
|
-
end
|
36
|
-
|
37
|
-
last_nl = @buf.rindex("\n")
|
32
|
+
last_nl = @buf.rindex("\n")
|
38
33
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
@buf = ""
|
47
|
-
end
|
48
|
-
|
49
|
-
result
|
50
|
-
end
|
51
|
-
|
52
|
-
def flush_output
|
53
|
-
out = @buf
|
34
|
+
if last_nl.nil?
|
35
|
+
result = nil
|
36
|
+
elsif last_nl != @buf.size - 1
|
37
|
+
result = @buf[0..last_nl]
|
38
|
+
@buf = @buf[last_nl+1..-1]
|
39
|
+
else
|
40
|
+
result = @buf
|
54
41
|
@buf = ""
|
55
|
-
out.blank? ? nil : "#{out}\n"
|
56
42
|
end
|
57
43
|
|
58
|
-
|
59
|
-
|
60
|
-
|
44
|
+
result
|
45
|
+
end
|
46
|
+
|
47
|
+
def flush_output
|
48
|
+
out = @buf
|
49
|
+
@buf = ""
|
50
|
+
out.blank? ? nil : "#{out}\n"
|
51
|
+
end
|
52
|
+
|
53
|
+
def cancel
|
54
|
+
@director.cancel_task(@task_id)
|
61
55
|
end
|
62
56
|
end
|
63
57
|
end
|
64
|
-
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Bosh::Cli
|
2
|
+
module TaskTracking; end
|
3
|
+
end
|
4
|
+
|
5
|
+
require 'cli/task_tracking/task_tracker'
|
6
|
+
require 'cli/task_tracking/task_log_renderer'
|
7
|
+
require 'cli/task_tracking/null_task_log_renderer'
|
8
|
+
require 'cli/task_tracking/stage_progress_bar'
|
9
|
+
require 'cli/task_tracking/event_log_renderer'
|
@@ -1,8 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module Bosh::Cli
|
1
|
+
module Bosh::Cli::TaskTracking
|
4
2
|
class EventLogRenderer < TaskLogRenderer
|
5
|
-
|
6
3
|
class InvalidEvent < StandardError; end
|
7
4
|
|
8
5
|
class Task
|
@@ -23,7 +20,7 @@ module Bosh::Cli
|
|
23
20
|
attr_reader :events_count
|
24
21
|
attr_reader :started_at, :finished_at
|
25
22
|
|
26
|
-
def initialize
|
23
|
+
def initialize(options={})
|
27
24
|
@lock = Monitor.new
|
28
25
|
@events_count = 0
|
29
26
|
@seen_stages = Set.new
|
@@ -33,12 +30,11 @@ module Bosh::Cli
|
|
33
30
|
@progress_bars = {}
|
34
31
|
@pos = 0
|
35
32
|
@time_adjustment = 0
|
33
|
+
@stages_without_progress_bar = options[:stages_without_progress_bar] || []
|
36
34
|
end
|
37
35
|
|
38
36
|
def add_output(output)
|
39
|
-
output.to_s.split("\n").each
|
40
|
-
add_event(line)
|
41
|
-
end
|
37
|
+
output.to_s.split("\n").each { |line| add_event(line) }
|
42
38
|
end
|
43
39
|
|
44
40
|
def add_event(event_line)
|
@@ -52,6 +48,16 @@ module Bosh::Cli
|
|
52
48
|
return
|
53
49
|
end
|
54
50
|
|
51
|
+
if can_handle_event_without_progress_bar?(event)
|
52
|
+
if @current_stage
|
53
|
+
done_with_stage
|
54
|
+
@current_stage = nil
|
55
|
+
@buffer.print "\n"
|
56
|
+
end
|
57
|
+
handle_event_without_progress_bar(event)
|
58
|
+
return
|
59
|
+
end
|
60
|
+
|
55
61
|
# One way to handle old stages is to prevent them
|
56
62
|
# from appearing on screen altogether. That means
|
57
63
|
# that we can always render the current stage only
|
@@ -240,9 +246,9 @@ module Bosh::Cli
|
|
240
246
|
# to only have canaries.
|
241
247
|
@tasks_batch_size = @tasks.size
|
242
248
|
@non_canary_event_start_time = task.start_time
|
243
|
-
@batches_count = ((total - @done_tasks.size) /
|
244
|
-
@tasks_batch_size.to_f).ceil
|
249
|
+
@batches_count = ((total - @done_tasks.size) / @tasks_batch_size.to_f).ceil
|
245
250
|
end
|
251
|
+
|
246
252
|
when "finished", "failed"
|
247
253
|
@tasks.delete(event["index"])
|
248
254
|
@done_tasks << task
|
@@ -256,13 +262,11 @@ module Bosh::Cli
|
|
256
262
|
task_time = task.finish_time - task.start_time
|
257
263
|
|
258
264
|
n_done_tasks = @done_tasks.size.to_f
|
259
|
-
@running_avg = @running_avg * (n_done_tasks - 1) / n_done_tasks +
|
260
|
-
task_time.to_f / n_done_tasks
|
265
|
+
@running_avg = @running_avg * (n_done_tasks - 1) / n_done_tasks + task_time.to_f / n_done_tasks
|
261
266
|
|
262
267
|
progress = 1
|
263
268
|
progress_bar.finished_steps += 1
|
264
269
|
progress_bar.label = time_with_eta(task_time, @eta)
|
265
|
-
|
266
270
|
progress_bar.clear_line
|
267
271
|
|
268
272
|
task_name = task.name.to_s
|
@@ -277,13 +281,13 @@ module Bosh::Cli
|
|
277
281
|
status = task_name.make_yellow
|
278
282
|
end
|
279
283
|
@buffer.puts(" #{status} (#{format_time(task_time)})")
|
284
|
+
|
280
285
|
when "in_progress"
|
281
286
|
progress = [event["progress"].to_f / 100, 1].min
|
282
287
|
end
|
283
288
|
|
284
289
|
if @batches_count > 0 && @non_canary_event_start_time
|
285
|
-
@eta = adjusted_time(@non_canary_event_start_time +
|
286
|
-
@running_avg * @batches_count)
|
290
|
+
@eta = adjusted_time(@non_canary_event_start_time + @running_avg * @batches_count)
|
287
291
|
end
|
288
292
|
|
289
293
|
progress_bar_gain = progress - task.progress
|
@@ -316,76 +320,39 @@ module Bosh::Cli
|
|
316
320
|
end
|
317
321
|
end
|
318
322
|
|
319
|
-
# Expects time and eta to be adjusted
|
320
323
|
def time_with_eta(time, eta)
|
321
324
|
time_fmt = format_time(time)
|
322
325
|
eta_fmt = eta && eta > Time.now ? format_time(eta - Time.now) : "--:--:--"
|
323
|
-
|
324
326
|
"#{time_fmt} ETA: #{eta_fmt}"
|
325
327
|
end
|
326
328
|
|
327
329
|
def adjusted_time(time)
|
328
330
|
time + @time_adjustment.to_f
|
329
331
|
end
|
330
|
-
end
|
331
|
-
|
332
|
-
class StageProgressBar
|
333
|
-
attr_accessor :total
|
334
|
-
attr_accessor :title
|
335
|
-
attr_accessor :current
|
336
|
-
attr_accessor :label
|
337
|
-
attr_accessor :bar_visible
|
338
|
-
attr_accessor :finished_steps
|
339
|
-
attr_accessor :terminal_width
|
340
|
-
|
341
|
-
def initialize(output)
|
342
|
-
@output = output
|
343
|
-
@current = 0
|
344
|
-
@total = 100
|
345
|
-
@bar_visible = true
|
346
|
-
@finished_steps = 0
|
347
|
-
@filler = "o"
|
348
|
-
@terminal_width = calculate_terminal_width
|
349
|
-
@bar_width = (0.24 * @terminal_width).to_i # characters
|
350
|
-
end
|
351
332
|
|
352
|
-
def
|
353
|
-
|
354
|
-
bar_repr = @bar_visible ? bar : ""
|
355
|
-
title_width = (0.35 * @terminal_width).to_i
|
356
|
-
title = @title.truncate(title_width).ljust(title_width)
|
357
|
-
@output.print "#{title} #{bar_repr} #{@finished_steps}/#{@total}"
|
358
|
-
@output.print " #{@label}" if @label
|
333
|
+
def can_handle_event_without_progress_bar?(event)
|
334
|
+
@stages_without_progress_bar.include?(event["stage"])
|
359
335
|
end
|
360
336
|
|
361
|
-
def
|
362
|
-
|
363
|
-
(@current.to_f / @total.to_f)).floor, 0].max
|
337
|
+
def handle_event_without_progress_bar(event)
|
338
|
+
event_header = "#{event["stage"].downcase}#{header_for_tags(event["tags"])}: #{event["task"]}"
|
364
339
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
def calculate_terminal_width
|
377
|
-
if ENV["COLUMNS"].to_s =~ /^\d+$/
|
378
|
-
ENV["COLUMNS"].to_i
|
379
|
-
elsif !ENV["TERM"].blank?
|
380
|
-
width = `tput cols`
|
381
|
-
$?.exitstatus == 0 ? [width.to_i, 100].min : 80
|
382
|
-
else
|
383
|
-
80
|
340
|
+
case event["state"]
|
341
|
+
when "started"
|
342
|
+
@buffer.print(" Started #{event_header}\n")
|
343
|
+
when "finished"
|
344
|
+
@buffer.print(" Done #{event_header}\n")
|
345
|
+
when "failed"
|
346
|
+
event_data = event["data"] || {}
|
347
|
+
data_error = event_data["error"]
|
348
|
+
error_msg = data_error ? ": #{data_error.make_red}" : ""
|
349
|
+
@buffer.print(" Failed #{event_header}#{error_msg}\n")
|
384
350
|
end
|
385
|
-
rescue
|
386
|
-
80
|
387
351
|
end
|
388
352
|
|
353
|
+
def header_for_tags(tags)
|
354
|
+
tags = Array(tags)
|
355
|
+
tags.size > 0 ? " " + tags.sort.join(", ").make_green : ""
|
356
|
+
end
|
389
357
|
end
|
390
|
-
|
391
358
|
end
|
@@ -1,8 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module Bosh::Cli
|
4
|
-
class NullRenderer < TaskLogRenderer
|
5
|
-
|
1
|
+
module Bosh::Cli::TaskTracking
|
2
|
+
class NullTaskLogRenderer < TaskLogRenderer
|
6
3
|
def initialize
|
7
4
|
end
|
8
5
|
|
@@ -14,6 +11,5 @@ module Bosh::Cli
|
|
14
11
|
|
15
12
|
def finish(state)
|
16
13
|
end
|
17
|
-
|
18
14
|
end
|
19
15
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Bosh::Cli::TaskTracking
|
2
|
+
class StageProgressBar
|
3
|
+
attr_accessor :total
|
4
|
+
attr_accessor :title
|
5
|
+
attr_accessor :current
|
6
|
+
attr_accessor :label
|
7
|
+
attr_accessor :bar_visible
|
8
|
+
attr_accessor :finished_steps
|
9
|
+
attr_accessor :terminal_width
|
10
|
+
|
11
|
+
def initialize(output)
|
12
|
+
@output = output
|
13
|
+
@current = 0
|
14
|
+
@total = 100
|
15
|
+
@bar_visible = true
|
16
|
+
@finished_steps = 0
|
17
|
+
@filler = "o"
|
18
|
+
@terminal_width = calculate_terminal_width
|
19
|
+
@bar_width = (0.24 * @terminal_width).to_i # characters
|
20
|
+
end
|
21
|
+
|
22
|
+
def refresh
|
23
|
+
clear_line
|
24
|
+
bar_repr = @bar_visible ? bar : ""
|
25
|
+
title_width = (0.35 * @terminal_width).to_i
|
26
|
+
title = @title.truncate(title_width).ljust(title_width)
|
27
|
+
@output.print "#{title} #{bar_repr} #{@finished_steps}/#{@total}"
|
28
|
+
@output.print " #{@label}" if @label
|
29
|
+
end
|
30
|
+
|
31
|
+
def bar
|
32
|
+
n_fillers = @total == 0 ? 0 : [(@bar_width *
|
33
|
+
(@current.to_f / @total.to_f)).floor, 0].max
|
34
|
+
|
35
|
+
fillers = "#{@filler}" * n_fillers
|
36
|
+
spaces = " " * [(@bar_width - n_fillers), 0].max
|
37
|
+
"|#{fillers}#{spaces}|"
|
38
|
+
end
|
39
|
+
|
40
|
+
def clear_line
|
41
|
+
@output.print("\r")
|
42
|
+
@output.print(" " * @terminal_width)
|
43
|
+
@output.print("\r")
|
44
|
+
end
|
45
|
+
|
46
|
+
def calculate_terminal_width
|
47
|
+
if ENV["COLUMNS"].to_s =~ /^\d+$/
|
48
|
+
ENV["COLUMNS"].to_i
|
49
|
+
elsif !ENV["TERM"].blank?
|
50
|
+
width = `tput cols`
|
51
|
+
$?.exitstatus == 0 ? [width.to_i, 100].min : 80
|
52
|
+
else
|
53
|
+
80
|
54
|
+
end
|
55
|
+
rescue
|
56
|
+
80
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -1,15 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
module Bosh::Cli
|
1
|
+
module Bosh::Cli::TaskTracking
|
4
2
|
class TaskLogRenderer
|
3
|
+
EVENT_LOG_STAGES_WITHOUT_PROGRESS_BAR = [
|
4
|
+
'Updating job',
|
5
|
+
'Deleting unneeded instances',
|
6
|
+
]
|
5
7
|
|
6
8
|
def self.create_for_log_type(log_type)
|
7
9
|
if log_type == "event"
|
8
|
-
EventLogRenderer.new
|
10
|
+
EventLogRenderer.new(stages_without_progress_bar:
|
11
|
+
EVENT_LOG_STAGES_WITHOUT_PROGRESS_BAR)
|
9
12
|
elsif log_type == "result" || log_type == "none"
|
10
|
-
|
11
|
-
# in case we need to fetch task result log only, without rendering it
|
12
|
-
NullRenderer.new
|
13
|
+
NullTaskLogRenderer.new
|
13
14
|
else
|
14
15
|
TaskLogRenderer.new
|
15
16
|
end
|
@@ -44,6 +45,5 @@ module Bosh::Cli
|
|
44
45
|
refresh
|
45
46
|
@done = true
|
46
47
|
end
|
47
|
-
|
48
48
|
end
|
49
49
|
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
module Bosh::Cli::TaskTracking
|
2
|
+
# This class is responsible for tracking director tasks
|
3
|
+
class TaskTracker
|
4
|
+
MAX_POLLS = nil # not limited
|
5
|
+
DEFAULT_POLL_INTERVAL = 1 # second
|
6
|
+
|
7
|
+
attr_reader :output
|
8
|
+
attr_reader :renderer
|
9
|
+
|
10
|
+
# @param [Bosh::Cli::Client::Director] director
|
11
|
+
# @param [Integer] task_id
|
12
|
+
# @param [Hash] options
|
13
|
+
def initialize(director, task_id, options = {})
|
14
|
+
@director = director
|
15
|
+
@task_id = task_id
|
16
|
+
@options = options
|
17
|
+
|
18
|
+
@quiet = !!options[:quiet]
|
19
|
+
default_log_type = @quiet ? "none" : "event"
|
20
|
+
|
21
|
+
@log_type = options[:log_type] || default_log_type
|
22
|
+
|
23
|
+
@output = nil
|
24
|
+
@task = Bosh::Cli::DirectorTask.new(@director, @task_id, @log_type)
|
25
|
+
|
26
|
+
if options[:renderer]
|
27
|
+
@renderer = options[:renderer]
|
28
|
+
elsif options[:raw_output]
|
29
|
+
@renderer = TaskLogRenderer.new
|
30
|
+
else
|
31
|
+
@renderer = TaskLogRenderer.create_for_log_type(@log_type)
|
32
|
+
end
|
33
|
+
|
34
|
+
@poll_interval = Bosh::Cli::Config.poll_interval || DEFAULT_POLL_INTERVAL
|
35
|
+
end
|
36
|
+
|
37
|
+
# Tracks director task. Blocks until task is in one of the 'finished'
|
38
|
+
# states (done, error, cancelled). Handles Ctrl+C by prompting to cancel
|
39
|
+
# task.
|
40
|
+
# @return [Symbol] Task status
|
41
|
+
def track
|
42
|
+
nl
|
43
|
+
@renderer.time_adjustment = @director.get_time_difference
|
44
|
+
say("Director task #{@task_id.to_s.make_yellow}")
|
45
|
+
task_status = poll
|
46
|
+
|
47
|
+
print_task_summary(task_status)
|
48
|
+
|
49
|
+
task_status
|
50
|
+
end
|
51
|
+
|
52
|
+
def poll
|
53
|
+
polls = 0
|
54
|
+
|
55
|
+
while true
|
56
|
+
polls += 1
|
57
|
+
state = @task.state
|
58
|
+
output = @task.output
|
59
|
+
|
60
|
+
output_received(output)
|
61
|
+
@renderer.refresh
|
62
|
+
|
63
|
+
if finished?(state)
|
64
|
+
return state.to_sym
|
65
|
+
elsif MAX_POLLS && polls >= MAX_POLLS
|
66
|
+
return :track_timeout
|
67
|
+
end
|
68
|
+
|
69
|
+
sleep(@poll_interval)
|
70
|
+
end
|
71
|
+
|
72
|
+
:unknown
|
73
|
+
rescue Interrupt # Local ctrl-c handler
|
74
|
+
prompt_for_task_cancel
|
75
|
+
end
|
76
|
+
|
77
|
+
def prompt_for_debug_log
|
78
|
+
return unless interactive?
|
79
|
+
nl
|
80
|
+
confirm = ask("The task has returned an error status, " +
|
81
|
+
"do you want to see debug log? [Yn]: ")
|
82
|
+
if confirm.empty? || confirm =~ /y(es)?/i
|
83
|
+
self.class.new(@director, @task_id,
|
84
|
+
@options.merge(:log_type => "debug")).track
|
85
|
+
else
|
86
|
+
say("Please use 'bosh task #{@task_id}' command ".make_red +
|
87
|
+
"to see the debug log".make_red)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def prompt_for_task_cancel
|
92
|
+
return unless interactive?
|
93
|
+
nl
|
94
|
+
confirm = ask("Do you want to cancel task #{@task_id}? [yN] " +
|
95
|
+
"(^C again to detach): ")
|
96
|
+
|
97
|
+
if confirm =~ /y(es)?/i
|
98
|
+
say("Cancelling task #{@task_id}...")
|
99
|
+
@director.cancel_task(@task_id)
|
100
|
+
end
|
101
|
+
|
102
|
+
poll
|
103
|
+
rescue Interrupt
|
104
|
+
nl
|
105
|
+
err("Task #{@task_id} is still running")
|
106
|
+
end
|
107
|
+
|
108
|
+
def print_task_summary(task_status)
|
109
|
+
output_received(@task.flush_output)
|
110
|
+
@renderer.finish(task_status)
|
111
|
+
|
112
|
+
nl
|
113
|
+
say("Task #{@task_id} #{task_status.to_s.make_yellow}")
|
114
|
+
|
115
|
+
if task_status == :done && @renderer.duration_known?
|
116
|
+
say("Started\t\t#{@renderer.started_at.utc.to_s}")
|
117
|
+
say("Finished\t#{@renderer.finished_at.utc.to_s}")
|
118
|
+
say("Duration\t#{format_time(@renderer.duration).make_yellow}")
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def nl
|
125
|
+
super unless @quiet
|
126
|
+
end
|
127
|
+
|
128
|
+
def say(*args)
|
129
|
+
super unless @quiet
|
130
|
+
end
|
131
|
+
|
132
|
+
# @param [String] output Output received from director task
|
133
|
+
def output_received(output)
|
134
|
+
return if output.nil?
|
135
|
+
@output ||= ""
|
136
|
+
@output << output
|
137
|
+
@renderer.add_output(output)
|
138
|
+
end
|
139
|
+
|
140
|
+
def finished?(state)
|
141
|
+
%(done error cancelled).include?(state)
|
142
|
+
end
|
143
|
+
|
144
|
+
def interactive?
|
145
|
+
Bosh::Cli::Config.interactive
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
data/lib/cli/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bosh_cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.0.pre.
|
4
|
+
version: 1.5.0.pre.1633
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-12-
|
12
|
+
date: 2013-12-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bosh_common
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.5.0.pre.
|
21
|
+
version: 1.5.0.pre.1633
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 1.5.0.pre.
|
29
|
+
version: 1.5.0.pre.1633
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: json_pure
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,7 +114,7 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - ~>
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 1.5.0.pre.
|
117
|
+
version: 1.5.0.pre.1633
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -122,7 +122,7 @@ dependencies:
|
|
122
122
|
requirements:
|
123
123
|
- - ~>
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version: 1.5.0.pre.
|
125
|
+
version: 1.5.0.pre.1633
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: net-ssh
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -253,7 +253,7 @@ dependencies:
|
|
253
253
|
version: '0'
|
254
254
|
description: ! 'BOSH CLI
|
255
255
|
|
256
|
-
|
256
|
+
72d86c'
|
257
257
|
email: support@cloudfoundry.com
|
258
258
|
executables:
|
259
259
|
- bosh
|
@@ -304,7 +304,6 @@ files:
|
|
304
304
|
- lib/cli/director_task.rb
|
305
305
|
- lib/cli/download_with_progress.rb
|
306
306
|
- lib/cli/errors.rb
|
307
|
-
- lib/cli/event_log_renderer.rb
|
308
307
|
- lib/cli/file_with_progress_bar.rb
|
309
308
|
- lib/cli/job_builder.rb
|
310
309
|
- lib/cli/job_command_args.rb
|
@@ -313,7 +312,6 @@ files:
|
|
313
312
|
- lib/cli/job_state.rb
|
314
313
|
- lib/cli/line_wrap.rb
|
315
314
|
- lib/cli/name_version_pair.rb
|
316
|
-
- lib/cli/null_renderer.rb
|
317
315
|
- lib/cli/package_builder.rb
|
318
316
|
- lib/cli/packaging_helper.rb
|
319
317
|
- lib/cli/public_stemcell.rb
|
@@ -326,8 +324,12 @@ files:
|
|
326
324
|
- lib/cli/resurrection.rb
|
327
325
|
- lib/cli/runner.rb
|
328
326
|
- lib/cli/stemcell.rb
|
329
|
-
- lib/cli/
|
330
|
-
- lib/cli/
|
327
|
+
- lib/cli/task_tracking.rb
|
328
|
+
- lib/cli/task_tracking/event_log_renderer.rb
|
329
|
+
- lib/cli/task_tracking/null_task_log_renderer.rb
|
330
|
+
- lib/cli/task_tracking/stage_progress_bar.rb
|
331
|
+
- lib/cli/task_tracking/task_log_renderer.rb
|
332
|
+
- lib/cli/task_tracking/task_tracker.rb
|
331
333
|
- lib/cli/validation.rb
|
332
334
|
- lib/cli/version.rb
|
333
335
|
- lib/cli/version_calc.rb
|
data/lib/cli/task_tracker.rb
DELETED
@@ -1,154 +0,0 @@
|
|
1
|
-
# Copyright (c) 2009-2012 VMware, Inc.
|
2
|
-
|
3
|
-
module Bosh
|
4
|
-
module Cli
|
5
|
-
# This class is responsible for tracking director tasks
|
6
|
-
class TaskTracker
|
7
|
-
|
8
|
-
MAX_POLLS = nil # not limited
|
9
|
-
DEFAULT_POLL_INTERVAL = 1 # second
|
10
|
-
|
11
|
-
attr_reader :output
|
12
|
-
|
13
|
-
attr_reader :renderer
|
14
|
-
|
15
|
-
# @param [Bosh::Cli::Client::Director] director
|
16
|
-
# @param [Integer] task_id
|
17
|
-
# @param [Hash] options
|
18
|
-
def initialize(director, task_id, options = {})
|
19
|
-
@director = director
|
20
|
-
@task_id = task_id
|
21
|
-
@options = options
|
22
|
-
|
23
|
-
@quiet = !!options[:quiet]
|
24
|
-
default_log_type = @quiet ? "none" : "event"
|
25
|
-
|
26
|
-
@log_type = options[:log_type] || default_log_type
|
27
|
-
|
28
|
-
@output = nil
|
29
|
-
@task = Bosh::Cli::DirectorTask.new(@director, @task_id, @log_type)
|
30
|
-
|
31
|
-
if options[:renderer]
|
32
|
-
@renderer = options[:renderer]
|
33
|
-
elsif options[:raw_output]
|
34
|
-
@renderer = Bosh::Cli::TaskLogRenderer.new
|
35
|
-
else
|
36
|
-
@renderer = Bosh::Cli::TaskLogRenderer.create_for_log_type(@log_type)
|
37
|
-
end
|
38
|
-
|
39
|
-
@poll_interval = Config.poll_interval || DEFAULT_POLL_INTERVAL
|
40
|
-
end
|
41
|
-
|
42
|
-
# Tracks director task. Blocks until task is in one of the 'finished'
|
43
|
-
# states (done, error, cancelled). Handles Ctrl+C by prompting to cancel
|
44
|
-
# task.
|
45
|
-
# @return [Symbol] Task status
|
46
|
-
def track
|
47
|
-
nl
|
48
|
-
@renderer.time_adjustment = @director.get_time_difference
|
49
|
-
say("Director task #{@task_id.to_s.make_yellow}")
|
50
|
-
task_status = poll
|
51
|
-
|
52
|
-
print_task_summary(task_status)
|
53
|
-
|
54
|
-
task_status
|
55
|
-
end
|
56
|
-
|
57
|
-
def poll
|
58
|
-
polls = 0
|
59
|
-
|
60
|
-
while true
|
61
|
-
polls += 1
|
62
|
-
state = @task.state
|
63
|
-
output = @task.output
|
64
|
-
|
65
|
-
output_received(output)
|
66
|
-
@renderer.refresh
|
67
|
-
|
68
|
-
if finished?(state)
|
69
|
-
return state.to_sym
|
70
|
-
elsif MAX_POLLS && polls >= MAX_POLLS
|
71
|
-
return :track_timeout
|
72
|
-
end
|
73
|
-
|
74
|
-
sleep(@poll_interval)
|
75
|
-
end
|
76
|
-
|
77
|
-
:unknown
|
78
|
-
rescue Interrupt # Local ctrl-c handler
|
79
|
-
prompt_for_task_cancel
|
80
|
-
end
|
81
|
-
|
82
|
-
def prompt_for_debug_log
|
83
|
-
return unless interactive?
|
84
|
-
nl
|
85
|
-
confirm = ask("The task has returned an error status, " +
|
86
|
-
"do you want to see debug log? [Yn]: ")
|
87
|
-
if confirm.empty? || confirm =~ /y(es)?/i
|
88
|
-
self.class.new(@director, @task_id,
|
89
|
-
@options.merge(:log_type => "debug")).track
|
90
|
-
else
|
91
|
-
say("Please use 'bosh task #{@task_id}' command ".make_red +
|
92
|
-
"to see the debug log".make_red)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def prompt_for_task_cancel
|
97
|
-
return unless interactive?
|
98
|
-
nl
|
99
|
-
confirm = ask("Do you want to cancel task #{@task_id}? [yN] " +
|
100
|
-
"(^C again to detach): ")
|
101
|
-
|
102
|
-
if confirm =~ /y(es)?/i
|
103
|
-
say("Cancelling task #{@task_id}...")
|
104
|
-
@director.cancel_task(@task_id)
|
105
|
-
end
|
106
|
-
|
107
|
-
poll
|
108
|
-
rescue Interrupt
|
109
|
-
nl
|
110
|
-
err("Task #{@task_id} is still running")
|
111
|
-
end
|
112
|
-
|
113
|
-
def print_task_summary(task_status)
|
114
|
-
output_received(@task.flush_output)
|
115
|
-
@renderer.finish(task_status)
|
116
|
-
|
117
|
-
nl
|
118
|
-
say("Task #{@task_id} #{task_status.to_s.make_yellow}")
|
119
|
-
|
120
|
-
if task_status == :done && @renderer.duration_known?
|
121
|
-
say("Started\t\t#{@renderer.started_at.utc.to_s}")
|
122
|
-
say("Finished\t#{@renderer.finished_at.utc.to_s}")
|
123
|
-
say("Duration\t#{format_time(@renderer.duration).make_yellow}")
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
private
|
128
|
-
|
129
|
-
def nl
|
130
|
-
super unless @quiet
|
131
|
-
end
|
132
|
-
|
133
|
-
def say(*args)
|
134
|
-
super unless @quiet
|
135
|
-
end
|
136
|
-
|
137
|
-
# @param [String] output Output received from director task
|
138
|
-
def output_received(output)
|
139
|
-
return if output.nil?
|
140
|
-
@output ||= ""
|
141
|
-
@output << output
|
142
|
-
@renderer.add_output(output)
|
143
|
-
end
|
144
|
-
|
145
|
-
def finished?(state)
|
146
|
-
%(done error cancelled).include?(state)
|
147
|
-
end
|
148
|
-
|
149
|
-
def interactive?
|
150
|
-
Bosh::Cli::Config.interactive
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|