bosh_cli 1.1782.0 → 1.1798.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -594,6 +594,10 @@ module Bosh
594
594
 
595
595
  private
596
596
 
597
+ def director_name
598
+ @director_name ||= get_status['name']
599
+ end
600
+
597
601
  def request(method, uri, content_type = nil, payload = nil,
598
602
  headers = {}, options = {})
599
603
  headers = headers.dup
@@ -620,9 +624,9 @@ module Bosh
620
624
 
621
625
  if DIRECTOR_HTTP_ERROR_CODES.include?(response.code)
622
626
  if response.code == 404
623
- raise ResourceNotFound, parse_error_message(response.code, body)
627
+ raise ResourceNotFound, parse_error_message(response.code, body, uri)
624
628
  else
625
- raise DirectorError, parse_error_message(response.code, body)
629
+ raise DirectorError, parse_error_message(response.code, body, uri)
626
630
  end
627
631
  end
628
632
 
@@ -641,12 +645,15 @@ module Bosh
641
645
  raise DirectorError, "System call error while talking to director: #{e}"
642
646
  end
643
647
 
644
- def parse_error_message(status, body)
648
+ def parse_error_message(status, body, uri)
645
649
  parsed_body = JSON.parse(body.to_s) rescue {}
646
650
 
647
651
  if parsed_body['code'] && parsed_body['description']
648
652
  'Error %s: %s' % [parsed_body['code'],
649
653
  parsed_body['description']]
654
+ elsif status == 404
655
+ "The #{director_name} bosh director doesn't understand the following API call: #{uri}." +
656
+ " The bosh deployment may need to be upgraded."
650
657
  else
651
658
  'HTTP %s: %s' % [status, body]
652
659
  end
@@ -7,4 +7,5 @@ require 'cli/task_tracking/total_duration'
7
7
  require 'cli/task_tracking/task_log_renderer'
8
8
  require 'cli/task_tracking/null_task_log_renderer'
9
9
  require 'cli/task_tracking/stage_progress_bar'
10
+ require 'cli/task_tracking/stage_collection'
10
11
  require 'cli/task_tracking/event_log_renderer'
@@ -317,26 +317,51 @@ module Bosh::Cli::TaskTracking
317
317
  end
318
318
 
319
319
  def handle_event_without_progress_bar(event)
320
- event_header = "#{event['stage'].downcase}#{header_for_tags(event['tags'])}: #{event['task']}"
320
+ @total_duration.started_at = event['time']
321
+ @total_duration.finished_at = event['time']
322
+ stage_collection.update_with_event(event)
323
+ end
321
324
 
322
- case event['state']
323
- when 'started'
324
- @total_duration.started_at = event['time']
325
- @buffer.print(" Started #{event_header}\n")
326
- when 'finished'
327
- @total_duration.finished_at = event['time']
328
- @buffer.print(" Done #{event_header}\n")
329
- when 'failed'
330
- event_data = event['data'] || {}
331
- data_error = event_data['error']
332
- error_msg = data_error ? ": #{data_error.make_red}" : ''
333
- @buffer.print(" Failed #{event_header}#{error_msg}\n")
334
- end
325
+ def stage_collection
326
+ @stage_collection ||= StageCollection.new(
327
+ stage_started: ->(stage){
328
+ @buffer.print(" Started #{header_for_stage(stage)}\n")
329
+ },
330
+ stage_finished: ->(stage){
331
+ duration = stage.duration ? " (#{format_time(stage.duration)})" : ''
332
+ @buffer.print(" Done #{header_for_stage(stage)}#{duration}\n")
333
+ },
334
+ stage_failed: ->(stage){
335
+ duration = stage.duration ? " (#{format_time(stage.duration)})" : ''
336
+ @buffer.print(" Failed #{header_for_stage(stage)}#{duration}\n")
337
+ },
338
+
339
+ task_started: ->(task){
340
+ @buffer.print(" Started #{header_for_task(task)}\n")
341
+ },
342
+ task_finished: ->(task){
343
+ duration = task.duration ? " (#{format_time(task.duration)})" : ''
344
+ @buffer.print(" Done #{header_for_task(task)}#{duration}\n")
345
+ },
346
+ task_failed: ->(task){
347
+ error_msg = task.error
348
+ error_msg = ": #{error_msg.make_red}" if error_msg
349
+ duration = task.duration ? " (#{format_time(task.duration)})" : ''
350
+ @buffer.print(" Failed #{header_for_task(task)}#{duration}#{error_msg}\n")
351
+ },
352
+ )
353
+ end
354
+
355
+ def header_for_stage(stage)
356
+ tags = stage.tags
357
+ tags_str = tags.size > 0 ? ' ' + tags.sort.join(', ').make_green : ''
358
+ "#{stage.name.downcase}#{tags_str}"
335
359
  end
336
360
 
337
- def header_for_tags(tags)
338
- tags = Array(tags)
339
- tags.size > 0 ? ' ' + tags.sort.join(', ').make_green : ''
361
+ def header_for_task(task)
362
+ tags = task.stage.tags
363
+ tags_str = tags.size > 0 ? ' ' + tags.sort.join(', ').make_green : ''
364
+ "#{task.stage.name.downcase}#{tags_str}: #{task.name}"
340
365
  end
341
366
 
342
367
  class Task
@@ -0,0 +1,119 @@
1
+ module Bosh::Cli::TaskTracking
2
+ class StageCollection
3
+ attr_reader :stages
4
+
5
+ def initialize(callbacks)
6
+ @stages = []
7
+ @callbacks = callbacks
8
+ end
9
+
10
+ def update_with_event(event)
11
+ new_stage = Stage.new(event['stage'], event['tags'], event['total'], @callbacks)
12
+ unless found_stage = @stages.find { |s| s.name == new_stage.name && s.tags == new_stage.tags }
13
+ found_stage = new_stage
14
+ @stages << new_stage
15
+ end
16
+ found_stage.update_with_event(event)
17
+ found_stage
18
+ end
19
+ end
20
+
21
+ class Stage
22
+ attr_reader :name, :tags, :total, :tasks
23
+
24
+ def initialize(name, tags, total, callbacks)
25
+ @name = name
26
+ @tags = Array(tags)
27
+ @total = total
28
+ @callbacks = callbacks
29
+ @tasks = []
30
+ end
31
+
32
+ def update_with_event(event)
33
+ new_task = Task.new(self, event['task'], event['progress'], @callbacks)
34
+ unless found_task = @tasks.find { |t| t.name == new_task.name }
35
+ found_task = new_task
36
+ @tasks << new_task
37
+ end
38
+ fire_started_callback(event)
39
+ found_task.update_with_event(event)
40
+ fire_finished_callback(event)
41
+ fire_failed_callback(event)
42
+ found_task
43
+ end
44
+
45
+ def duration
46
+ total_duration = TotalDuration.new
47
+
48
+ task_start_times = @tasks.map(&:started_at)
49
+ task_end_times = @tasks.map(&:finished_at)
50
+
51
+ # If any task start time is nil, the start time for the entire stage is unknown.
52
+ total_duration.started_at = task_start_times.min unless task_start_times.include?(nil)
53
+ total_duration.finished_at = task_end_times.max unless task_end_times.include?(nil)
54
+
55
+ total_duration.duration
56
+ end
57
+
58
+ private
59
+
60
+ def fire_started_callback(event)
61
+ if event['state'] == 'started' && event['index'] == 1
62
+ callback = @callbacks[:stage_started]
63
+ callback.call(self) if callback
64
+ end
65
+ end
66
+
67
+ def fire_finished_callback(event)
68
+ if event['state'] == 'finished' && ((event['index'] == event['total']) || event['total'].nil?)
69
+ callback = @callbacks[:stage_finished]
70
+ callback.call(self) if callback
71
+ end
72
+ end
73
+
74
+ def fire_failed_callback(event)
75
+ if event['state'] == 'failed'
76
+ # If there are multiple failures do we need to only fire on the first one?
77
+ callback = @callbacks[:stage_failed]
78
+ callback.call(self) if callback
79
+ end
80
+ end
81
+ end
82
+
83
+ class Task
84
+ attr_reader :stage, :name, :state, :progress, :error
85
+
86
+ extend Forwardable
87
+ def_delegators :@total_duration, :duration, :started_at, :finished_at
88
+
89
+ def initialize(stage, name, progress, callbacks)
90
+ @stage = stage
91
+ @name = name
92
+ @progress = progress
93
+ @callbacks = callbacks
94
+ @total_duration = TotalDuration.new
95
+ end
96
+
97
+ def update_with_event(event)
98
+ @state = event['state']
99
+ @progress = event['progress']
100
+ @error = (event['data'] || {})['error']
101
+
102
+ @total_duration.started_at = event['time'] if @state == 'started'
103
+ @total_duration.finished_at = event['time'] if @state == 'finished' || @state == 'failed'
104
+
105
+ call_state_callback
106
+ end
107
+
108
+ private
109
+
110
+ def call_state_callback
111
+ callback = case @state
112
+ when 'started' then @callbacks[:task_started]
113
+ when 'finished' then @callbacks[:task_finished]
114
+ when 'failed' then @callbacks[:task_failed]
115
+ end
116
+ callback.call(self) if callback
117
+ end
118
+ end
119
+ end
@@ -1,5 +1,5 @@
1
1
  module Bosh
2
2
  module Cli
3
- VERSION = '1.1782.0'
3
+ VERSION = '1.1798.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.1782.0
4
+ version: 1.1798.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-16 00:00:00.000000000 Z
12
+ date: 2014-01-18 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.1782.0
21
+ version: 1.1798.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.1782.0
29
+ version: 1.1798.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.1782.0
117
+ version: 1.1798.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.1782.0
125
+ version: 1.1798.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
- 5aedfc'
272
+ 4c516b'
273
273
  email: support@cloudfoundry.com
274
274
  executables:
275
275
  - bosh
@@ -343,6 +343,7 @@ files:
343
343
  - lib/cli/task_tracking.rb
344
344
  - lib/cli/task_tracking/event_log_renderer.rb
345
345
  - lib/cli/task_tracking/null_task_log_renderer.rb
346
+ - lib/cli/task_tracking/stage_collection.rb
346
347
  - lib/cli/task_tracking/stage_progress_bar.rb
347
348
  - lib/cli/task_tracking/task_log_renderer.rb
348
349
  - lib/cli/task_tracking/task_tracker.rb
@@ -375,7 +376,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
375
376
  version: '0'
376
377
  segments:
377
378
  - 0
378
- hash: 1526214907771034034
379
+ hash: 2560420917753689708
379
380
  requirements: []
380
381
  rubyforge_project:
381
382
  rubygems_version: 1.8.23