bosh_cli 1.1782.0 → 1.1798.0

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