bosh_cli 1.0.3 → 1.5.0.pre.1113

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.
Files changed (144) hide show
  1. data/bin/bosh +0 -9
  2. data/lib/cli.rb +69 -64
  3. data/lib/cli/backup_destination_path.rb +33 -0
  4. data/lib/cli/base_command.rb +57 -56
  5. data/lib/cli/blob_manager.rb +12 -12
  6. data/lib/cli/changeset_helper.rb +6 -7
  7. data/lib/cli/client/director.rb +724 -0
  8. data/lib/cli/command_handler.rb +6 -7
  9. data/lib/cli/commands/backup.rb +39 -0
  10. data/lib/cli/commands/biff.rb +42 -21
  11. data/lib/cli/commands/blob_management.rb +1 -1
  12. data/lib/cli/commands/cloudcheck.rb +11 -13
  13. data/lib/cli/commands/deployment.rb +53 -37
  14. data/lib/cli/commands/help.rb +3 -2
  15. data/lib/cli/commands/job_management.rb +67 -103
  16. data/lib/cli/commands/job_rename.rb +6 -8
  17. data/lib/cli/commands/log_management.rb +78 -55
  18. data/lib/cli/commands/maintenance.rb +36 -30
  19. data/lib/cli/commands/misc.rb +72 -51
  20. data/lib/cli/commands/package.rb +2 -2
  21. data/lib/cli/commands/property_management.rb +10 -12
  22. data/lib/cli/commands/release.rb +236 -133
  23. data/lib/cli/commands/snapshot.rb +93 -0
  24. data/lib/cli/commands/ssh.rb +216 -213
  25. data/lib/cli/commands/stemcell.rb +46 -34
  26. data/lib/cli/commands/task.rb +2 -2
  27. data/lib/cli/commands/user.rb +27 -3
  28. data/lib/cli/commands/vm.rb +28 -0
  29. data/lib/cli/commands/vms.rb +81 -23
  30. data/lib/cli/config.rb +6 -2
  31. data/lib/cli/core_ext.rb +31 -30
  32. data/lib/cli/deployment_helper.rb +134 -159
  33. data/lib/cli/deployment_manifest.rb +66 -0
  34. data/lib/cli/deployment_manifest_compiler.rb +0 -3
  35. data/lib/cli/event_log_renderer.rb +10 -10
  36. data/lib/cli/file_with_progress_bar.rb +52 -0
  37. data/lib/cli/job_builder.rb +1 -1
  38. data/lib/cli/job_command_args.rb +23 -0
  39. data/lib/cli/job_property_collection.rb +4 -7
  40. data/lib/cli/job_property_validator.rb +22 -12
  41. data/lib/cli/job_state.rb +54 -0
  42. data/lib/cli/line_wrap.rb +54 -0
  43. data/lib/cli/packaging_helper.rb +10 -10
  44. data/lib/cli/release.rb +18 -15
  45. data/lib/cli/release_builder.rb +9 -4
  46. data/lib/cli/release_compiler.rb +9 -9
  47. data/lib/cli/release_tarball.rb +3 -6
  48. data/lib/cli/resurrection.rb +31 -0
  49. data/lib/cli/runner.rb +56 -30
  50. data/lib/cli/stemcell.rb +25 -10
  51. data/lib/cli/task_log_renderer.rb +1 -1
  52. data/lib/cli/task_tracker.rb +10 -9
  53. data/lib/cli/validation.rb +3 -1
  54. data/lib/cli/version.rb +1 -1
  55. data/lib/cli/version_calc.rb +5 -18
  56. data/lib/cli/versions_index.rb +1 -1
  57. data/lib/cli/vm_state.rb +43 -0
  58. data/lib/cli/yaml_helper.rb +26 -35
  59. metadata +75 -208
  60. data/Rakefile +0 -56
  61. data/lib/cli/director.rb +0 -628
  62. data/spec/assets/biff/bad_gateway_config.yml +0 -28
  63. data/spec/assets/biff/good_simple_config.yml +0 -63
  64. data/spec/assets/biff/good_simple_golden_config.yml +0 -63
  65. data/spec/assets/biff/good_simple_template.erb +0 -69
  66. data/spec/assets/biff/ip_out_of_range.yml +0 -63
  67. data/spec/assets/biff/multiple_subnets_config.yml +0 -40
  68. data/spec/assets/biff/network_only_template.erb +0 -34
  69. data/spec/assets/biff/no_cc_config.yml +0 -27
  70. data/spec/assets/biff/no_range_config.yml +0 -27
  71. data/spec/assets/biff/no_subnet_config.yml +0 -16
  72. data/spec/assets/biff/ok_network_config.yml +0 -30
  73. data/spec/assets/biff/properties_template.erb +0 -6
  74. data/spec/assets/config/atmos/config/final.yml +0 -6
  75. data/spec/assets/config/atmos/config/private.yml +0 -4
  76. data/spec/assets/config/bad-providers/config/final.yml +0 -5
  77. data/spec/assets/config/bad-providers/config/private.yml +0 -4
  78. data/spec/assets/config/deprecation/config/final.yml +0 -5
  79. data/spec/assets/config/deprecation/config/private.yml +0 -2
  80. data/spec/assets/config/local/config/final.yml +0 -5
  81. data/spec/assets/config/local/config/private.yml +0 -1
  82. data/spec/assets/config/s3/config/final.yml +0 -5
  83. data/spec/assets/config/s3/config/private.yml +0 -5
  84. data/spec/assets/config/swift-hp/config/final.yml +0 -6
  85. data/spec/assets/config/swift-hp/config/private.yml +0 -7
  86. data/spec/assets/config/swift-rackspace/config/final.yml +0 -6
  87. data/spec/assets/config/swift-rackspace/config/private.yml +0 -6
  88. data/spec/assets/deployment.MF +0 -0
  89. data/spec/assets/plugins/bosh/cli/commands/echo.rb +0 -43
  90. data/spec/assets/plugins/bosh/cli/commands/ruby.rb +0 -24
  91. data/spec/assets/release/jobs/cacher.tgz +0 -0
  92. data/spec/assets/release/jobs/cacher/config/file1.conf +0 -0
  93. data/spec/assets/release/jobs/cacher/config/file2.conf +0 -0
  94. data/spec/assets/release/jobs/cacher/job.MF +0 -6
  95. data/spec/assets/release/jobs/cacher/monit +0 -1
  96. data/spec/assets/release/jobs/cleaner.tgz +0 -0
  97. data/spec/assets/release/jobs/cleaner/job.MF +0 -4
  98. data/spec/assets/release/jobs/cleaner/monit +0 -1
  99. data/spec/assets/release/jobs/sweeper.tgz +0 -0
  100. data/spec/assets/release/jobs/sweeper/config/test.conf +0 -1
  101. data/spec/assets/release/jobs/sweeper/job.MF +0 -5
  102. data/spec/assets/release/jobs/sweeper/monit +0 -1
  103. data/spec/assets/release/packages/mutator.tar.gz +0 -0
  104. data/spec/assets/release/packages/stuff.tgz +0 -0
  105. data/spec/assets/release/release.MF +0 -17
  106. data/spec/assets/release_invalid_checksum.tgz +0 -0
  107. data/spec/assets/release_invalid_jobs.tgz +0 -0
  108. data/spec/assets/release_no_name.tgz +0 -0
  109. data/spec/assets/release_no_version.tgz +0 -0
  110. data/spec/assets/stemcell/image +0 -1
  111. data/spec/assets/stemcell/stemcell.MF +0 -6
  112. data/spec/assets/stemcell_invalid_mf.tgz +0 -0
  113. data/spec/assets/stemcell_no_image.tgz +0 -0
  114. data/spec/assets/valid_release.tgz +0 -0
  115. data/spec/assets/valid_stemcell.tgz +0 -0
  116. data/spec/spec_helper.rb +0 -28
  117. data/spec/unit/base_command_spec.rb +0 -87
  118. data/spec/unit/biff_spec.rb +0 -172
  119. data/spec/unit/blob_manager_spec.rb +0 -288
  120. data/spec/unit/cache_spec.rb +0 -36
  121. data/spec/unit/cli_commands_spec.rb +0 -356
  122. data/spec/unit/config_spec.rb +0 -125
  123. data/spec/unit/core_ext_spec.rb +0 -81
  124. data/spec/unit/dependency_helper_spec.rb +0 -52
  125. data/spec/unit/deployment_manifest_compiler_spec.rb +0 -63
  126. data/spec/unit/deployment_manifest_spec.rb +0 -153
  127. data/spec/unit/director_spec.rb +0 -471
  128. data/spec/unit/director_task_spec.rb +0 -48
  129. data/spec/unit/event_log_renderer_spec.rb +0 -171
  130. data/spec/unit/hash_changeset_spec.rb +0 -73
  131. data/spec/unit/job_builder_spec.rb +0 -455
  132. data/spec/unit/job_property_collection_spec.rb +0 -111
  133. data/spec/unit/job_property_validator_spec.rb +0 -7
  134. data/spec/unit/job_rename_spec.rb +0 -200
  135. data/spec/unit/package_builder_spec.rb +0 -593
  136. data/spec/unit/release_builder_spec.rb +0 -120
  137. data/spec/unit/release_spec.rb +0 -173
  138. data/spec/unit/release_tarball_spec.rb +0 -29
  139. data/spec/unit/runner_spec.rb +0 -7
  140. data/spec/unit/ssh_spec.rb +0 -84
  141. data/spec/unit/stemcell_spec.rb +0 -17
  142. data/spec/unit/task_tracker_spec.rb +0 -131
  143. data/spec/unit/version_calc_spec.rb +0 -27
  144. data/spec/unit/versions_index_spec.rb +0 -144
@@ -39,25 +39,24 @@ module Bosh::Cli
39
39
  # @param [Array] args
40
40
  # @return [Integer] Command exit code
41
41
  def run(args, extra_options = {})
42
- handler = @klass.new(@runner)
42
+ command = @klass.new(@runner)
43
43
 
44
44
  @options.each do |(name, arguments)|
45
45
  @parser.on(name, *arguments) do |value|
46
- handler.add_option(format_option_name(name), value)
46
+ command.add_option(format_option_name(name), value)
47
47
  end
48
48
  end
49
49
 
50
50
  extra_options.each_pair do |name, value|
51
- handler.add_option(format_option_name(name), value)
51
+ command.add_option(format_option_name(name), value)
52
52
  end
53
53
 
54
54
  args = parse_options(args)
55
55
 
56
56
  begin
57
- handler.send(@method.name, *args)
58
- handler.exit_code
57
+ command.send(@method.name, *args)
58
+ command.exit_code
59
59
  rescue ArgumentError => e
60
- say(e.message)
61
60
  err("Usage: #{usage_with_params}")
62
61
  end
63
62
  end
@@ -97,7 +96,7 @@ module Bosh::Cli
97
96
  desc = desc.select { |word| word.is_a?(String) }
98
97
  column_width = terminal_width - padding - margin
99
98
 
100
- result << name.ljust(margin).yellow + " " +
99
+ result << name.ljust(margin).make_yellow + " " +
101
100
  desc.join(" ").columnize(
102
101
  column_width, [margin + 1, name.size + 1].max)
103
102
  end
@@ -0,0 +1,39 @@
1
+ module Bosh::Cli::Command
2
+ class Backup < Base
3
+
4
+ usage 'backup'
5
+ desc 'Backup BOSH'
6
+ option '--force', 'Overwrite if the backup file already exists'
7
+ def backup(path=nil)
8
+ auth_required
9
+ path = backup_destination_path(path)
10
+
11
+ status, task_id = director.create_backup
12
+
13
+ if status == :done
14
+ tmp_path = director.fetch_backup
15
+ FileUtils.mv(tmp_path, path)
16
+ say("Backup of BOSH director was put in `#{path.make_green}'.")
17
+ else
18
+ [status, task_id]
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def force?
25
+ !!options[:force]
26
+ end
27
+
28
+ def backup_destination_path(dest_path)
29
+ path = Bosh::Cli::BackupDestinationPath.new(director).create_from_path(dest_path)
30
+
31
+ if File.exists?(path) && !force?
32
+ err("There is already an existing file at `#{path}'. " +
33
+ 'To overwrite it use the --force option.')
34
+ end
35
+
36
+ path
37
+ end
38
+ end
39
+ end
@@ -1,6 +1,8 @@
1
1
  module Bosh::Cli::Command
2
2
  class Biff < Base
3
3
 
4
+ attr_reader :errors
5
+
4
6
  # Takes your current deployment configuration and uses some of its
5
7
  # configuration to populate the template file. The Network information is
6
8
  # used and then IPs for each job are automatically set. Once the template
@@ -18,7 +20,13 @@ module Bosh::Cli::Command
18
20
  setup(template)
19
21
 
20
22
  template_to_fill = ERB.new(File.read(@template_file), 0, "%<>-")
21
- @template_output = template_to_fill.result(binding)
23
+ begin
24
+ @template_output = template_to_fill.result(binding)
25
+ rescue ArgumentError => ex
26
+ say(ex.message)
27
+ say(ex.backtrace.join("\n"))
28
+ err("Error rendering ERB")
29
+ end
22
30
 
23
31
  if @errors == 0
24
32
  print_string_diff(File.read(@deployment_file), @template_output)
@@ -80,9 +88,9 @@ module Bosh::Cli::Command
80
88
  removed = line[0..0] == "-"
81
89
 
82
90
  if added
83
- say(line.chomp.green)
91
+ say(line.chomp.make_green)
84
92
  elsif removed
85
- say(line.chomp.red)
93
+ say(line.chomp.make_red)
86
94
  else
87
95
  say(line)
88
96
  end
@@ -116,22 +124,11 @@ module Bosh::Cli::Command
116
124
  path_split = path.split(".")
117
125
  found_so_far = []
118
126
  path_split.each do |path_part|
119
- found = false
120
- if obj.is_a?(Array)
121
- obj.each do |data_val|
122
- if data_val["name"] == path_part
123
- obj = data_val
124
- found = true
125
- end
126
- end
127
- elsif !obj[path_part].nil?
128
- obj = obj[path_part]
129
- found = true
130
- end
127
+ obj = lookup(path_part, obj)
131
128
 
132
- unless found
129
+ unless obj
133
130
  @errors += 1
134
- say("Could not find #{path.red}.")
131
+ say("Could not find #{path.make_red}.")
135
132
  say("'#{@template_file}' has it but '#{@deployment_file}' does not.")
136
133
  #say("\nIt should exist in \n#{obj.to_yaml}\n")
137
134
  if starting_obj == @deployment_obj
@@ -150,6 +147,15 @@ module Bosh::Cli::Command
150
147
  obj
151
148
  end
152
149
 
150
+ def lookup(path, obj)
151
+ case obj
152
+ when Array
153
+ obj.find { |value| path == value['name'] }
154
+ when Hash
155
+ obj[path] if obj.has_key?(path)
156
+ end
157
+ end
158
+
153
159
  # Used by print_the_template_path so that it can prettily print just the
154
160
  # section of the template that the user is missing. E.x. if the user is
155
161
  # missing the job 'ccdb' then we want to not just print out 'ccdb' and
@@ -193,7 +199,7 @@ module Bosh::Cli::Command
193
199
  path = users_farthest_found_path.join('.')
194
200
  what_we_need = find(path, @template_obj)
195
201
  what_we_need = delete_all_except(what_we_need, delete_all_except_name)
196
- say("Add this to '#{path}':".red + "\n#{what_we_need.to_yaml}\n\n")
202
+ say("Add this to '#{path}':".make_red + "\n#{what_we_need.to_yaml}\n\n")
197
203
  end
198
204
 
199
205
  # Loads the template file as YAML. First, it replaces all of the ruby
@@ -204,7 +210,7 @@ module Bosh::Cli::Command
204
210
  temp_data = File.read(@template_file)
205
211
  temp_data.gsub!(/<%=.*%>/, "INSERT_DATA_HERE")
206
212
  temp_data.gsub!(/[ ]*<%.*%>[ ]*\n/, "")
207
- YAML::load(temp_data)
213
+ Psych::load(temp_data)
208
214
  end
209
215
 
210
216
  # Gets the network's network/mask for configuring things such as the
@@ -366,17 +372,32 @@ module Bosh::Cli::Command
366
372
  # @param [String] template The string path to the template that should be
367
373
  # used.
368
374
  def setup(template)
375
+ @errors = 0
369
376
  @template_file = template
370
377
  @deployment_file = deployment
371
378
  err("Deployment not set.") if @deployment_file.nil?
372
- @deployment_obj = load_yaml_file(@deployment_file)
379
+ @deployment_obj = load_yaml_file(deployment)
373
380
  @template_obj = load_template_as_yaml
374
381
  @ip_helper = create_ip_helper
375
- @errors = 0
376
382
  @dir_name = Dir.mktmpdir
377
383
  @temp_file_path_1 = "#{@dir_name}/bosh_biff_1"
378
384
  @temp_file_path_2 = "#{@dir_name}/bosh_biff_2"
379
385
  end
380
386
 
387
+ # Generate a random string for passwords and tokens.
388
+ # Length is the length of the string.
389
+ # name is an optional name of a previously generated string. This is used
390
+ # to allow setting the same password for different components.
391
+ def random_string(length, name=nil)
392
+ random_string = SecureRandom.hex(length)[0...length]
393
+
394
+ @random_cache ||= {}
395
+ if name
396
+ @random_cache[name] ||= random_string
397
+ else
398
+ random_string
399
+ end
400
+ end
401
+
381
402
  end
382
403
  end
@@ -37,7 +37,7 @@ module Bosh::Cli::Command
37
37
 
38
38
  blob_manager.blobs_to_upload.each do |blob|
39
39
  nl
40
- if confirmed?("Upload blob #{blob.yellow}?")
40
+ if confirmed?("Upload blob #{blob.make_yellow}?")
41
41
  blob_manager.upload_blob(blob)
42
42
  end
43
43
  end
@@ -2,8 +2,6 @@
2
2
 
3
3
  module Bosh::Cli::Command
4
4
  class CloudCheck < Base
5
- include Bosh::Cli::DeploymentHelper
6
-
7
5
  # bosh cloudcheck
8
6
  usage "cloudcheck"
9
7
  desc "Cloud consistency check and interactive repair"
@@ -19,9 +17,10 @@ module Bosh::Cli::Command
19
17
  @auto_mode = options[:auto]
20
18
  @report_mode = options[:report]
21
19
 
22
- if non_interactive? && !@report_mode
20
+ if non_interactive? && !(@report_mode || @auto_mode)
23
21
  err ("Cloudcheck cannot be run in non-interactive mode\n" +
24
- "Please use `--auto' flag if you want automated resolutions")
22
+ "Please use `--auto' flag if you want automated resolutions " +
23
+ "or `--report' if you just want a report of the errors")
25
24
  end
26
25
 
27
26
  if @auto_mode && @report_mode
@@ -44,14 +43,14 @@ module Bosh::Cli::Command
44
43
 
45
44
  verify_problems
46
45
  nl
47
- say("Found #{pluralize(@problems.size, "problem")}".yellow)
46
+ say("Found #{pluralize(@problems.size, "problem")}".make_yellow)
48
47
  nl
49
48
 
50
49
  @resolutions = {}
51
50
 
52
51
  @problems.each_with_index do |problem, index|
53
52
  description = problem["description"].to_s.chomp(".") + "."
54
- say("Problem #{index+1} of #{@problems.size}: #{description}".yellow)
53
+ say("Problem #{index+1} of #{@problems.size}: #{description}".make_yellow)
55
54
  next if @report_mode
56
55
  if @auto_mode
57
56
  @resolutions[problem["id"]] = {
@@ -83,7 +82,7 @@ module Bosh::Cli::Command
83
82
  exit(1)
84
83
  end
85
84
 
86
- say("Cloudcheck is finished".green)
85
+ say("Cloudcheck is finished".make_green)
87
86
  end
88
87
 
89
88
  private
@@ -92,7 +91,7 @@ module Bosh::Cli::Command
92
91
  err("Invalid problem list format") unless @problems.kind_of?(Enumerable)
93
92
 
94
93
  if @problems.empty?
95
- say("No problems found".green)
94
+ say("No problems found".make_green)
96
95
  exit(0)
97
96
  end
98
97
 
@@ -126,26 +125,25 @@ module Bosh::Cli::Command
126
125
  choice.to_i <= resolutions.size
127
126
  break
128
127
  end
129
- say("Please enter a number between 1 and #{resolutions.size}".red)
128
+ say("Please enter a number between 1 and #{resolutions.size}".make_red)
130
129
  end
131
130
 
132
131
  resolutions[choice.to_i-1] # -1 accounts for 0-based indexing
133
132
  end
134
133
 
135
134
  def confirm_resolutions
136
- say("Below is the list of resolutions you've provided".yellow)
137
- say("Please make sure everything is fine and confirm your changes".yellow)
135
+ say("Below is the list of resolutions you've provided".make_yellow)
136
+ say("Please make sure everything is fine and confirm your changes".make_yellow)
138
137
  nl
139
138
 
140
139
  @problems.each_with_index do |problem, index|
141
140
  plan = @resolutions[problem["id"]]["plan"]
142
141
  padding = " " * ((index+1).to_s.size + 4)
143
142
  say(" #{index+1}. #{problem["description"]}")
144
- say("#{padding}#{plan.to_s.yellow}")
143
+ say("#{padding}#{plan.to_s.make_yellow}")
145
144
  nl
146
145
  end
147
146
 
148
- # TODO: allow editing resolutions?
149
147
  cancel unless confirmed?("Apply resolutions?")
150
148
  end
151
149
 
@@ -2,8 +2,6 @@
2
2
 
3
3
  module Bosh::Cli::Command
4
4
  class Deployment < Base
5
- include Bosh::Cli::DeploymentHelper
6
-
7
5
  # bosh deployment
8
6
  usage "deployment"
9
7
  desc "Get/set current deployment"
@@ -34,7 +32,7 @@ module Bosh::Cli::Command
34
32
  end
35
33
 
36
34
  if target
37
- old_director = Bosh::Cli::Director.new(target, username, password)
35
+ old_director = Bosh::Cli::Client::Director.new(target, username, password)
38
36
  old_director_uuid = old_director.get_status["uuid"] rescue nil
39
37
  else
40
38
  old_director_uuid = nil
@@ -52,7 +50,7 @@ module Bosh::Cli::Command
52
50
  "Please find your director IP or hostname and target it first.")
53
51
  end
54
52
 
55
- new_director = Bosh::Cli::Director.new(
53
+ new_director = Bosh::Cli::Client::Director.new(
56
54
  new_target_url, username, password)
57
55
 
58
56
  status = new_director.get_status
@@ -61,11 +59,11 @@ module Bosh::Cli::Command
61
59
  config.target_name = status["name"]
62
60
  config.target_version = status["version"]
63
61
  config.target_uuid = status["uuid"]
64
- say("#{"WARNING!".red} Your target has been " +
65
- "changed to `#{target.red}'!")
62
+ say("#{"WARNING!".make_red} Your target has been " +
63
+ "changed to `#{target.make_red}'!")
66
64
  end
67
65
 
68
- say("Deployment set to `#{manifest_filename.green}'")
66
+ say("Deployment set to `#{manifest_filename.make_green}'")
69
67
  config.set_deployment(manifest_filename)
70
68
  config.save
71
69
  end
@@ -91,11 +89,11 @@ module Bosh::Cli::Command
91
89
  :yaml => true, :resolve_properties => true)
92
90
 
93
91
  if interactive?
94
- inspect_deployment_changes(YAML.load(manifest_yaml))
95
- say("Please review all changes carefully".yellow)
92
+ inspect_deployment_changes(Psych.load(manifest_yaml))
93
+ say("Please review all changes carefully".make_yellow)
96
94
  end
97
95
 
98
- desc = "`#{File.basename(deployment).green}' to `#{target_name.green}'"
96
+ desc = "`#{File.basename(deployment).make_green}' to `#{target_name.make_green}'"
99
97
 
100
98
  unless confirmed?("Deploying #{desc}")
101
99
  cancel_deployment
@@ -114,12 +112,12 @@ module Bosh::Cli::Command
114
112
  auth_required
115
113
  force = !!options[:force]
116
114
 
117
- say("\nYou are going to delete deployment `#{name}'.".red)
115
+ say("\nYou are going to delete deployment `#{name}'.".make_red)
118
116
  nl
119
- say("THIS IS A VERY DESTRUCTIVE OPERATION AND IT CANNOT BE UNDONE!\n".red)
117
+ say("THIS IS A VERY DESTRUCTIVE OPERATION AND IT CANNOT BE UNDONE!\n".make_red)
120
118
 
121
119
  unless confirmed?
122
- say("Canceled deleting deployment".green)
120
+ say("Canceled deleting deployment".make_green)
123
121
  return
124
122
  end
125
123
 
@@ -145,7 +143,7 @@ module Bosh::Cli::Command
145
143
  end
146
144
  if release_name == release.dev_name || release_name == release.final_name
147
145
  nl
148
- say("Analyzing release directory...".yellow)
146
+ say("Analyzing release directory...".make_yellow)
149
147
  else
150
148
  err("This release was not found in deployment manifest")
151
149
  end
@@ -171,7 +169,7 @@ module Bosh::Cli::Command
171
169
 
172
170
  unless validator.jobs_without_properties.empty?
173
171
  nl
174
- say("Legacy jobs (no properties defined): ".yellow)
172
+ say("Legacy jobs (no properties defined): ".make_yellow)
175
173
  validator.jobs_without_properties.sort { |a, b|
176
174
  a.name <=> b.name
177
175
  }.each do |job|
@@ -181,17 +179,17 @@ module Bosh::Cli::Command
181
179
 
182
180
  if validator.template_errors.empty?
183
181
  nl
184
- say("No template errors found".green)
182
+ say("No template errors found".make_green)
185
183
  else
186
184
  nl
187
- say("Template errors: ".yellow)
185
+ say("Template errors: ".make_yellow)
188
186
  validator.template_errors.each do |error|
189
187
  nl
190
188
  path = Pathname.new(error.template_path)
191
189
  rel_path = path.relative_path_from(Pathname.new(release.dir))
192
190
 
193
191
  say(" - #{rel_path}:")
194
- say(" line #{error.line}:".yellow + " #{error.exception.to_s}")
192
+ say(" line #{error.line}:".make_yellow + " #{error.exception.to_s}")
195
193
  end
196
194
  end
197
195
  end
@@ -208,23 +206,12 @@ module Bosh::Cli::Command
208
206
  deployments_table = table do |t|
209
207
  t.headings = %w(Name Release(s) Stemcell(s))
210
208
  deployments.each do |d|
211
- deployment = director.get_deployment(d["name"])
212
-
213
- row = if (deployment["manifest"])
214
- manifest = YAML.load(deployment["manifest"])
215
-
216
- stemcells = manifest["resource_pools"].map { |rp|
217
- rp["stemcell"].values_at("name", "version").join("/")
218
- }.sort.uniq
219
-
220
- releases = manifest["releases"] || [manifest["release"]]
221
- releases = releases.map { |rl|
222
- rl.values_at("name", "version").join("/")
223
- }.sort
224
-
225
- [manifest["name"], releases.join("\n"), stemcells.join("\n")]
209
+ row = if (d.has_key?("releases") && d.has_key?("stemcells"))
210
+ row_for_deployments_table(d)
226
211
  else
227
- [d["name"], "n/a", "n/a"]
212
+ # backwards compatible but slow: pull down each deployment
213
+ # manifest to get releases and stemcells in use
214
+ row_for_deployments_table_by_manifest(d["name"])
228
215
  end
229
216
 
230
217
  t.add_row(row)
@@ -255,18 +242,17 @@ module Bosh::Cli::Command
255
242
  File.open(save_as, "w") do |f|
256
243
  f.write(deployment["manifest"])
257
244
  end
258
- say("Deployment manifest saved to `#{save_as}'".green)
245
+ say("Deployment manifest saved to `#{save_as}'".make_green)
259
246
  else
260
247
  say(deployment["manifest"])
261
248
  end
262
249
  end
263
250
 
264
251
  private
265
-
266
252
  def show_current
267
253
  if deployment
268
254
  if interactive?
269
- say("Current deployment is `#{deployment.green}'")
255
+ say("Current deployment is `#{deployment.make_green}'")
270
256
  else
271
257
  say(deployment)
272
258
  end
@@ -275,5 +261,35 @@ module Bosh::Cli::Command
275
261
  end
276
262
  end
277
263
 
264
+ def row_for_deployments_table(deployment)
265
+ stemcells = names_and_versions_from(deployment["stemcells"])
266
+ releases = names_and_versions_from(deployment["releases"])
267
+
268
+ [deployment["name"], releases.join("\n"), stemcells.join("\n")]
269
+ end
270
+
271
+ def row_for_deployments_table_by_manifest(deployment_name)
272
+ raw_manifest = director.get_deployment(deployment_name)
273
+ if (raw_manifest.has_key?("manifest"))
274
+ manifest = Psych.load(raw_manifest["manifest"])
275
+
276
+ stemcells = manifest["resource_pools"].map { |rp|
277
+ rp["stemcell"].values_at("name", "version").join("/")
278
+ }.sort.uniq
279
+
280
+ releases = manifest["releases"] || [manifest["release"]]
281
+ releases = names_and_versions_from(releases)
282
+
283
+ [manifest["name"], releases.join("\n"), stemcells.join("\n")]
284
+ else
285
+ [deployment_name, "n/a", "n/a"]
286
+ end
287
+ end
288
+
289
+ def names_and_versions_from(arr)
290
+ arr.map { |hash|
291
+ hash.values_at("name", "version").join("/")
292
+ }.sort
293
+ end
278
294
  end
279
295
  end