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 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