bosh_cli 1.5.0.pre.1623 → 1.5.0.pre.1633

Sign up to get free protection for your applications and to get access to all the features.
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'
@@ -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
@@ -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
@@ -1,64 +1,57 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
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
- module Bosh
4
- module Cli
5
- class DirectorTask
13
+ def state
14
+ @director.get_task_state(@task_id)
15
+ end
6
16
 
7
- attr_accessor :offset
17
+ def result
18
+ @director.get_task_result(@task_id)
19
+ end
8
20
 
9
- def initialize(director, task_id, log_type = nil)
10
- @director = director
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
- def state
18
- @director.get_task_state(@task_id)
19
- end
24
+ @buf << body if body
20
25
 
21
- def result
22
- @director.get_task_result(@task_id)
26
+ if new_offset
27
+ @offset = new_offset
28
+ else
29
+ return flush_output
23
30
  end
24
31
 
25
- def output
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
- if last_nl.nil?
40
- result = nil
41
- elsif last_nl != @buf.size - 1
42
- result = @buf[0..last_nl]
43
- @buf = @buf[last_nl+1..-1]
44
- else
45
- result = @buf
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
- def cancel
59
- @director.cancel_task(@task_id)
60
- end
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
- # Copyright (c) 2009-2012 VMware, Inc.
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 do |line|
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 refresh
353
- clear_line
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 bar
362
- n_fillers = @total == 0 ? 0 : [(@bar_width *
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
- fillers = "#{@filler}" * n_fillers
366
- spaces = " " * [(@bar_width - n_fillers), 0].max
367
- "|#{fillers}#{spaces}|"
368
- end
369
-
370
- def clear_line
371
- @output.print("\r")
372
- @output.print(" " * @terminal_width)
373
- @output.print("\r")
374
- end
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
- # Copyright (c) 2009-2012 VMware, Inc.
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
- # Copyright (c) 2009-2012 VMware, Inc.
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
- # Null renderer doesn't output anything to screen, so it fits well
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Bosh
4
4
  module Cli
5
- VERSION = '1.5.0.pre.1623'
5
+ VERSION = '1.5.0.pre.1633'
6
6
  end
7
7
  end
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.1623
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-22 00:00:00.000000000 Z
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.1623
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.1623
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.1623
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.1623
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
- bf7b9f'
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/task_log_renderer.rb
330
- - lib/cli/task_tracker.rb
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
@@ -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