bosh_cli 1.1761.0 → 1.1777.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/cli/runner.rb CHANGED
@@ -56,20 +56,24 @@ module Bosh::Cli
56
56
  exit_code = command.run(@args, @options)
57
57
  exit(exit_code)
58
58
  rescue OptionParser::ParseError => e
59
- say_err e.message
60
- say_err "Usage: bosh #{command.usage_with_params.columnize(60, 7)}"
59
+ say_err(e.message)
60
+ nl
61
+ say_err("Usage: bosh #{command.usage_with_params.columnize(60, 7)}")
62
+ nl
61
63
  if command.has_options?
62
64
  say(command.options_summary.indent(7))
63
65
  end
66
+ exit(1)
64
67
  end
65
68
 
66
69
  rescue OptionParser::ParseError => e
67
- say_err e.message
68
- say_err @option_parser.to_s
70
+ say_err(e.message)
71
+ say_err(@option_parser.to_s)
69
72
  exit(1)
73
+
70
74
  rescue Bosh::Cli::CliError => e
71
- say_err e.message
72
- puts ""
75
+ say_err(e.message)
76
+ nl
73
77
  exit(e.exit_code)
74
78
  end
75
79
 
@@ -3,6 +3,7 @@ module Bosh::Cli
3
3
  end
4
4
 
5
5
  require 'cli/task_tracking/task_tracker'
6
+ require 'cli/task_tracking/total_duration'
6
7
  require 'cli/task_tracking/task_log_renderer'
7
8
  require 'cli/task_tracking/null_task_log_renderer'
8
9
  require 'cli/task_tracking/stage_progress_bar'
@@ -2,25 +2,14 @@ module Bosh::Cli::TaskTracking
2
2
  class EventLogRenderer < TaskLogRenderer
3
3
  class InvalidEvent < StandardError; end
4
4
 
5
- class Task
6
- attr_accessor :name
7
- attr_accessor :progress
8
- attr_accessor :start_time
9
- attr_accessor :finish_time
10
-
11
- def initialize(name)
12
- @name = name
13
- @progress = 0
14
- @start_time = nil
15
- @finish_time = nil
16
- end
17
- end
5
+ extend Forwardable
6
+ def_delegators :@total_duration, :duration, :duration_known?, :started_at, :finished_at
18
7
 
19
8
  attr_reader :current_stage
20
9
  attr_reader :events_count
21
- attr_reader :started_at, :finished_at
22
10
 
23
11
  def initialize(options={})
12
+ @total_duration = TotalDuration.new
24
13
  @lock = Monitor.new
25
14
  @events_count = 0
26
15
  @seen_stages = Set.new
@@ -42,7 +31,7 @@ module Bosh::Cli::TaskTracking
42
31
 
43
32
  @lock.synchronize do
44
33
  # Handling the special "error" event
45
- if event["error"]
34
+ if event['error']
46
35
  done_with_stage if @current_stage
47
36
  add_error(event)
48
37
  return
@@ -66,11 +55,11 @@ module Bosh::Cli::TaskTracking
66
55
  # resuming the older stages rendering if we feel
67
56
  # that it's valuable.
68
57
 
69
- tags = event["tags"].is_a?(Array) ? event["tags"] : []
70
- stage_header = event["stage"]
58
+ tags = event['tags'].is_a?(Array) ? event['tags'] : []
59
+ stage_header = event['stage']
71
60
 
72
61
  if tags.size > 0
73
- stage_header += " " + tags.sort.join(", ").make_green
62
+ stage_header += ' ' + tags.sort.join(', ').make_green
74
63
  end
75
64
 
76
65
  unless @seen_stages.include?(stage_header)
@@ -91,7 +80,7 @@ module Bosh::Cli::TaskTracking
91
80
  @current_stage = header
92
81
  @seen_stages << @current_stage
93
82
 
94
- @stage_start_time = Time.at(event["time"]) rescue Time.now
83
+ @stage_start_time = Time.at(event['time']) rescue Time.now
95
84
  @local_start_time = adjusted_time(@stage_start_time)
96
85
 
97
86
  @tasks = {}
@@ -120,11 +109,11 @@ module Bosh::Cli::TaskTracking
120
109
  end
121
110
 
122
111
  def add_error(event)
123
- error = event["error"] || {}
124
- code = error["code"]
125
- message = error["message"]
112
+ error = event['error'] || {}
113
+ code = error['code']
114
+ message = error['message']
126
115
 
127
- error = "Error"
116
+ error = 'Error'
128
117
  error += " #{code}" if code
129
118
  error += ": #{message}" if message
130
119
 
@@ -153,15 +142,6 @@ module Bosh::Cli::TaskTracking
153
142
  end
154
143
  end
155
144
 
156
- def duration_known?
157
- @started_at && @finished_at
158
- end
159
-
160
- def duration
161
- return unless duration_known?
162
- @finished_at - @started_at
163
- end
164
-
165
145
  private
166
146
 
167
147
  def append_stage_header
@@ -172,23 +152,23 @@ module Bosh::Cli::TaskTracking
172
152
  return unless @in_progress
173
153
 
174
154
  if @last_event
175
- completion_time = Time.at(@last_event["time"]) rescue Time.now
155
+ completion_time = Time.at(@last_event['time']) rescue Time.now
176
156
  else
177
157
  completion_time = Time.now
178
158
  end
179
159
 
180
160
  if state.nil?
181
- state = @stage_has_error ? "error" : "done"
161
+ state = @stage_has_error ? 'error' : 'done'
182
162
  end
183
163
 
184
164
  case state.to_s
185
- when "done"
186
- progress_bar.title = "Done".make_green
165
+ when 'done'
166
+ progress_bar.title = 'Done'.make_green
187
167
  progress_bar.finished_steps = progress_bar.total
188
- when "error"
189
- progress_bar.title = "Error".make_red
168
+ when 'error'
169
+ progress_bar.title = 'Error'.make_red
190
170
  else
191
- progress_bar.title = "Not done".make_yellow
171
+ progress_bar.title = 'Not done'.make_yellow
192
172
  end
193
173
 
194
174
  progress_bar.bar_visible = false
@@ -208,34 +188,34 @@ module Bosh::Cli::TaskTracking
208
188
  validate_event(event)
209
189
 
210
190
  progress = 0
211
- total = event["total"].to_i
191
+ total = event['total'].to_i
212
192
 
213
- if event["state"] == "started"
214
- task = Task.new(event["task"])
193
+ if event['state'] == 'started'
194
+ task = Task.new(event['task'])
215
195
  else
216
- task = @tasks[event["index"]]
196
+ task = @tasks[event['index']]
217
197
  end
218
198
 
219
- event_data = event["data"] || {}
199
+ event_data = event['data'] || {}
220
200
  # Ignoring out-of-order events
221
201
  return if task.nil?
222
202
 
223
203
  @events_count += 1
224
204
  @last_event = event
225
205
 
226
- case event["state"]
227
- when "started"
206
+ case event['state']
207
+ when 'started'
208
+ @total_duration.started_at = event['time']
209
+
228
210
  begin
229
- task.start_time = Time.at(event["time"])
230
- # Treat first "started" event as task start time
231
- @started_at = task.start_time if @started_at.nil?
211
+ task.start_time = Time.at(event['time'])
232
212
  rescue
233
213
  task.start_time = Time.now
234
214
  end
235
215
 
236
216
  task.progress = 0
237
217
 
238
- @tasks[event["index"]] = task
218
+ @tasks[event['index']] = task
239
219
 
240
220
  if @tasks.size > @tasks_batch_size
241
221
  # Heuristics here: we assume that local maximum of
@@ -249,12 +229,14 @@ module Bosh::Cli::TaskTracking
249
229
  @batches_count = ((total - @done_tasks.size) / @tasks_batch_size.to_f).ceil
250
230
  end
251
231
 
252
- when "finished", "failed"
253
- @tasks.delete(event["index"])
232
+ when 'finished', 'failed'
233
+ @tasks.delete(event['index'])
254
234
  @done_tasks << task
255
235
 
236
+ @total_duration.finished_at = event['time']
237
+
256
238
  begin
257
- task.finish_time = @finished_at = Time.at(event["time"])
239
+ task.finish_time = Time.at(event['time'])
258
240
  rescue
259
241
  task.finish_time = Time.now
260
242
  end
@@ -274,16 +256,16 @@ module Bosh::Cli::TaskTracking
274
256
  task_name = task_name[0..0].to_s.downcase + task_name[1..-1].to_s
275
257
  end
276
258
 
277
- if event["state"] == "failed"
278
- status = [task_name.make_red, event_data["error"]].compact.join(": ")
259
+ if event['state'] == 'failed'
260
+ status = [task_name.make_red, event_data['error']].compact.join(': ')
279
261
  @stage_has_error = true
280
262
  else
281
263
  status = task_name.make_yellow
282
264
  end
283
265
  @buffer.puts(" #{status} (#{format_time(task_time)})")
284
266
 
285
- when "in_progress"
286
- progress = [event["progress"].to_f / 100, 1].min
267
+ when 'in_progress'
268
+ progress = [event['progress'].to_f / 100, 1].min
287
269
  end
288
270
 
289
271
  if @batches_count > 0 && @non_canary_event_start_time
@@ -294,7 +276,7 @@ module Bosh::Cli::TaskTracking
294
276
  task.progress = progress
295
277
 
296
278
  progress_bar.total = total
297
- progress_bar.title = @tasks.values.map { |t| t.name }.sort.join(", ")
279
+ progress_bar.title = @tasks.values.map { |t| t.name }.sort.join(', ')
298
280
 
299
281
  progress_bar.current += progress_bar_gain
300
282
  progress_bar.refresh
@@ -309,20 +291,20 @@ module Bosh::Cli::TaskTracking
309
291
  end
310
292
  event
311
293
  rescue JSON::JSONError
312
- raise InvalidEvent, "Cannot parse event, invalid JSON"
294
+ raise InvalidEvent, 'Cannot parse event, invalid JSON'
313
295
  end
314
296
 
315
297
  def validate_event(event)
316
- unless event["time"] && event["stage"] && event["task"] &&
317
- event["index"] && event["total"] && event["state"]
318
- raise InvalidEvent, "Invalid event structure: stage, time, task, " +
319
- "index, total, state are all required"
298
+ unless event['time'] && event['stage'] && event['task'] &&
299
+ event['index'] && event['total'] && event['state']
300
+ raise InvalidEvent, 'Invalid event structure: stage, time, task, ' +
301
+ 'index, total, state are all required'
320
302
  end
321
303
  end
322
304
 
323
305
  def time_with_eta(time, eta)
324
306
  time_fmt = format_time(time)
325
- eta_fmt = eta && eta > Time.now ? format_time(eta - Time.now) : "--:--:--"
307
+ eta_fmt = eta && eta > Time.now ? format_time(eta - Time.now) : '--:--:--'
326
308
  "#{time_fmt} ETA: #{eta_fmt}"
327
309
  end
328
310
 
@@ -331,28 +313,44 @@ module Bosh::Cli::TaskTracking
331
313
  end
332
314
 
333
315
  def can_handle_event_without_progress_bar?(event)
334
- @stages_without_progress_bar.include?(event["stage"])
316
+ @stages_without_progress_bar.include?(event['stage'])
335
317
  end
336
318
 
337
319
  def handle_event_without_progress_bar(event)
338
- event_header = "#{event["stage"].downcase}#{header_for_tags(event["tags"])}: #{event["task"]}"
320
+ event_header = "#{event['stage'].downcase}#{header_for_tags(event['tags'])}: #{event['task']}"
339
321
 
340
- case event["state"]
341
- when "started"
322
+ case event['state']
323
+ when 'started'
324
+ @total_duration.started_at = event['time']
342
325
  @buffer.print(" Started #{event_header}\n")
343
- when "finished"
326
+ when 'finished'
327
+ @total_duration.finished_at = event['time']
344
328
  @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}" : ""
329
+ when 'failed'
330
+ event_data = event['data'] || {}
331
+ data_error = event_data['error']
332
+ error_msg = data_error ? ": #{data_error.make_red}" : ''
349
333
  @buffer.print(" Failed #{event_header}#{error_msg}\n")
350
334
  end
351
335
  end
352
336
 
353
337
  def header_for_tags(tags)
354
338
  tags = Array(tags)
355
- tags.size > 0 ? " " + tags.sort.join(", ").make_green : ""
339
+ tags.size > 0 ? ' ' + tags.sort.join(', ').make_green : ''
340
+ end
341
+
342
+ class Task
343
+ attr_accessor :name
344
+ attr_accessor :progress
345
+ attr_accessor :start_time
346
+ attr_accessor :finish_time
347
+
348
+ def initialize(name)
349
+ @name = name
350
+ @progress = 0
351
+ @start_time = nil
352
+ @finish_time = nil
353
+ end
356
354
  end
357
355
  end
358
356
  end
@@ -14,14 +14,14 @@ module Bosh::Cli::TaskTracking
14
14
  @total = 100
15
15
  @bar_visible = true
16
16
  @finished_steps = 0
17
- @filler = "o"
17
+ @filler = 'o'
18
18
  @terminal_width = calculate_terminal_width
19
19
  @bar_width = (0.24 * @terminal_width).to_i # characters
20
20
  end
21
21
 
22
22
  def refresh
23
23
  clear_line
24
- bar_repr = @bar_visible ? bar : ""
24
+ bar_repr = @bar_visible ? bar : ''
25
25
  title_width = (0.35 * @terminal_width).to_i
26
26
  title = @title.truncate(title_width).ljust(title_width)
27
27
  @output.print "#{title} #{bar_repr} #{@finished_steps}/#{@total}"
@@ -33,20 +33,20 @@ module Bosh::Cli::TaskTracking
33
33
  (@current.to_f / @total.to_f)).floor, 0].max
34
34
 
35
35
  fillers = "#{@filler}" * n_fillers
36
- spaces = " " * [(@bar_width - n_fillers), 0].max
36
+ spaces = ' ' * [(@bar_width - n_fillers), 0].max
37
37
  "|#{fillers}#{spaces}|"
38
38
  end
39
39
 
40
40
  def clear_line
41
41
  @output.print("\r")
42
- @output.print(" " * @terminal_width)
42
+ @output.print(' ' * @terminal_width)
43
43
  @output.print("\r")
44
44
  end
45
45
 
46
46
  def calculate_terminal_width
47
- if ENV["COLUMNS"].to_s =~ /^\d+$/
48
- ENV["COLUMNS"].to_i
49
- elsif !ENV["TERM"].blank?
47
+ if ENV['COLUMNS'].to_s =~ /^\d+$/
48
+ ENV['COLUMNS'].to_i
49
+ elsif !ENV['TERM'].blank?
50
50
  width = `tput cols`
51
51
  $?.exitstatus == 0 ? [width.to_i, 100].min : 80
52
52
  else
@@ -6,10 +6,10 @@ module Bosh::Cli::TaskTracking
6
6
  ]
7
7
 
8
8
  def self.create_for_log_type(log_type)
9
- if log_type == "event"
9
+ if log_type == 'event'
10
10
  EventLogRenderer.new(stages_without_progress_bar:
11
11
  EVENT_LOG_STAGES_WITHOUT_PROGRESS_BAR)
12
- elsif log_type == "result" || log_type == "none"
12
+ elsif log_type == 'result' || log_type == 'none'
13
13
  NullTaskLogRenderer.new
14
14
  else
15
15
  TaskLogRenderer.new
@@ -23,7 +23,7 @@ module Bosh::Cli::TaskTracking
23
23
  @out = Bosh::Cli::Config.output || $stdout
24
24
  @out.sync = true
25
25
  @lock = Mutex.new
26
- @output = ""
26
+ @output = ''
27
27
  @time_adjustment = 0
28
28
  @duration = nil
29
29
  end
@@ -38,7 +38,7 @@ module Bosh::Cli::TaskTracking
38
38
 
39
39
  def refresh
40
40
  @out.print(@output)
41
- @output = ""
41
+ @output = ''
42
42
  end
43
43
 
44
44
  def finish(state)
@@ -16,7 +16,7 @@ module Bosh::Cli::TaskTracking
16
16
  @options = options
17
17
 
18
18
  @quiet = !!options[:quiet]
19
- default_log_type = @quiet ? "none" : "event"
19
+ default_log_type = @quiet ? 'none' : 'event'
20
20
 
21
21
  @log_type = options[:log_type] || default_log_type
22
22
 
@@ -77,14 +77,14 @@ module Bosh::Cli::TaskTracking
77
77
  def prompt_for_debug_log
78
78
  return unless interactive?
79
79
  nl
80
- confirm = ask("The task has returned an error status, " +
81
- "do you want to see debug log? [Yn]: ")
80
+ confirm = ask('The task has returned an error status, ' +
81
+ 'do you want to see debug log? [Yn]: ')
82
82
  if confirm.empty? || confirm =~ /y(es)?/i
83
83
  self.class.new(@director, @task_id,
84
- @options.merge(:log_type => "debug")).track
84
+ @options.merge(:log_type => 'debug')).track
85
85
  else
86
86
  say("Please use 'bosh task #{@task_id}' command ".make_red +
87
- "to see the debug log".make_red)
87
+ 'to see the debug log'.make_red)
88
88
  end
89
89
  end
90
90
 
@@ -92,7 +92,7 @@ module Bosh::Cli::TaskTracking
92
92
  return unless interactive?
93
93
  nl
94
94
  confirm = ask("Do you want to cancel task #{@task_id}? [yN] " +
95
- "(^C again to detach): ")
95
+ '(^C again to detach): ')
96
96
 
97
97
  if confirm =~ /y(es)?/i
98
98
  say("Cancelling task #{@task_id}...")
@@ -113,6 +113,7 @@ module Bosh::Cli::TaskTracking
113
113
  say("Task #{@task_id} #{task_status.to_s.make_yellow}")
114
114
 
115
115
  if task_status == :done && @renderer.duration_known?
116
+ nl
116
117
  say("Started\t\t#{@renderer.started_at.utc.to_s}")
117
118
  say("Finished\t#{@renderer.finished_at.utc.to_s}")
118
119
  say("Duration\t#{format_time(@renderer.duration).make_yellow}")
@@ -132,13 +133,13 @@ module Bosh::Cli::TaskTracking
132
133
  # @param [String] output Output received from director task
133
134
  def output_received(output)
134
135
  return if output.nil?
135
- @output ||= ""
136
+ @output ||= ''
136
137
  @output << output
137
138
  @renderer.add_output(output)
138
139
  end
139
140
 
140
141
  def finished?(state)
141
- %(done error cancelled).include?(state)
142
+ 'done error cancelled'.include?(state)
142
143
  end
143
144
 
144
145
  def interactive?
@@ -0,0 +1,23 @@
1
+ module Bosh::Cli::TaskTracking
2
+ class TotalDuration
3
+ attr_reader :started_at, :finished_at
4
+
5
+ def started_at=(time)
6
+ if !@started_at
7
+ @started_at = Time.at(time) rescue nil
8
+ end
9
+ end
10
+
11
+ def finished_at=(time)
12
+ (@finished_at = Time.at(time)) rescue nil
13
+ end
14
+
15
+ def duration
16
+ @finished_at - @started_at if duration_known?
17
+ end
18
+
19
+ def duration_known?
20
+ !!(@finished_at && @started_at)
21
+ end
22
+ end
23
+ end
data/lib/cli/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Bosh
2
2
  module Cli
3
- VERSION = '1.1761.0'
3
+ VERSION = '1.1777.0'
4
4
  end
5
5
  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.1761.0
4
+ version: 1.1777.0
5
5
  prerelease:
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: 2014-01-10 00:00:00.000000000 Z
12
+ date: 2014-01-15 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.1761.0
21
+ version: 1.1777.0
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.1761.0
29
+ version: 1.1777.0
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.1761.0
117
+ version: 1.1777.0
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.1761.0
125
+ version: 1.1777.0
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: net-ssh
128
128
  requirement: !ruby/object:Gem::Requirement
@@ -269,7 +269,7 @@ dependencies:
269
269
  version: '0'
270
270
  description: ! 'BOSH CLI
271
271
 
272
- 826c69'
272
+ 0308a9'
273
273
  email: support@cloudfoundry.com
274
274
  executables:
275
275
  - bosh
@@ -346,6 +346,7 @@ files:
346
346
  - lib/cli/task_tracking/stage_progress_bar.rb
347
347
  - lib/cli/task_tracking/task_log_renderer.rb
348
348
  - lib/cli/task_tracking/task_tracker.rb
349
+ - lib/cli/task_tracking/total_duration.rb
349
350
  - lib/cli/validation.rb
350
351
  - lib/cli/version.rb
351
352
  - lib/cli/version_calc.rb
@@ -374,7 +375,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
374
375
  version: '0'
375
376
  segments:
376
377
  - 0
377
- hash: -459032974552856888
378
+ hash: 4248709114918295253
378
379
  requirements: []
379
380
  rubyforge_project:
380
381
  rubygems_version: 1.8.23