bosh_cli 0.19.1 → 0.19.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -15,6 +15,7 @@ module Bosh::Cli
15
15
  config_file = @options[:config] || Bosh::Cli::DEFAULT_CONFIG_PATH
16
16
  @config = Config.new(config_file)
17
17
  @cache = Config.cache
18
+ @exit_code = 0
18
19
  end
19
20
 
20
21
  class << self
@@ -106,6 +107,42 @@ module Bosh::Cli
106
107
  ret + " %s" % target_version if ret
107
108
  end
108
109
 
110
+ # Sets or returns command exit code
111
+ # @param [optional,Integer] code If param is given, sets exit code. If
112
+ # it's nil, returns previously set exit_code
113
+ def exit_code(code = nil)
114
+ if code
115
+ @exit_code = code
116
+ else
117
+ @exit_code
118
+ end
119
+ end
120
+
121
+ # Prints director task completion report. Note that event log usually
122
+ # contains pretty detailed error report and other UI niceties, so most
123
+ # of the time this could just do nothing
124
+ # @param [Symbol] status Task status
125
+ def task_report(status, success_msg = nil, error_msg = nil)
126
+ case status
127
+ when :non_trackable
128
+ report = "Can't track director task".red
129
+ when :track_timeout
130
+ report = "Task tracking timeout".red
131
+ when :error
132
+ report = error_msg
133
+ when :done
134
+ report = success_msg
135
+ else
136
+ report = nil
137
+ end
138
+
139
+ if status != :done
140
+ exit_code(1)
141
+ end
142
+
143
+ say("\n#{report}") if report
144
+ end
145
+
109
146
  protected
110
147
 
111
148
  def auth_required
@@ -28,8 +28,12 @@ module Bosh::Cli::Command
28
28
  manifest = prepare_deployment_manifest
29
29
  deployment_name = manifest["name"]
30
30
 
31
- status, body = director.perform_cloud_scan(deployment_name)
32
- scan_failed(status, body) if status != :done
31
+ status, _ = director.perform_cloud_scan(deployment_name)
32
+
33
+ if status != :done
34
+ task_report(status)
35
+ exit(1)
36
+ end
33
37
 
34
38
  nl
35
39
  say("Scan is complete, checking if any problems found...")
@@ -69,36 +73,17 @@ module Bosh::Cli::Command
69
73
  hash
70
74
  end
71
75
 
72
- status, body = director.apply_resolutions(deployment_name, action_map)
73
- resolution_failed(status, body) if status != :done
74
- say("Cloudcheck is finished".green)
75
- end
76
-
77
- private
76
+ status, _ = director.apply_resolutions(deployment_name, action_map)
78
77
 
79
- def scan_failed(status, response)
80
- responses = {
81
- :non_trackable => "Unable to track cloud scan progress, " +
82
- "please update your director",
83
- :track_timeout => "Timed out while tracking cloud scan progress",
84
- :error => "Cloud scan error",
85
- :invalid => "Invalid cloud scan request"
86
- }
78
+ if status != :done
79
+ task_report(status)
80
+ exit(1)
81
+ end
87
82
 
88
- err(responses[status] || "Cloud scan failed: #{response}")
83
+ say("Cloudcheck is finished".green)
89
84
  end
90
85
 
91
- def resolution_failed(status, response)
92
- responses = {
93
- :non_trackable => "Unable to track problem resolution progress, " +
94
- "please update your director",
95
- :track_timeout => "Timed out while tracking problem resolution progress",
96
- :error => "Problem resolution error",
97
- :invalid => "Invalid problem resolution request"
98
- }
99
-
100
- err(responses[status] || "Problem resolution failed: #{response}")
101
- end
86
+ private
102
87
 
103
88
  def verify_problems
104
89
  err("Invalid problem list format") unless @problems.kind_of?(Enumerable)
@@ -150,7 +135,6 @@ module Bosh::Cli::Command
150
135
  nl
151
136
 
152
137
  @problems.each_with_index do |problem, index|
153
- description = problem["description"]
154
138
  plan = @resolutions[problem["id"]]["plan"]
155
139
  padding = " " * ((index+1).to_s.size + 4)
156
140
  say(" #{index+1}. #{problem["description"]}")
@@ -85,20 +85,9 @@ module Bosh::Cli::Command
85
85
  cancel_deployment
86
86
  end
87
87
 
88
- status, body = director.deploy(manifest_yaml, :recreate => recreate)
89
-
90
- responses = {
91
- :done => "Deployed #{desc}",
92
- :non_trackable => "Started deployment but director at `#{target}' " +
93
- "doesn't support deployment tracking",
94
- :track_timeout => "Started deployment but timed out out " +
95
- "while tracking status",
96
- :error => "Started deployment but received an error " +
97
- "while tracking status",
98
- :invalid => "Deployment is invalid, please fix it and deploy again"
99
- }
100
-
101
- say(responses[status] || "Cannot deploy: #{body}")
88
+ status, _ = director.deploy(manifest_yaml, :recreate => recreate)
89
+
90
+ task_report(status, "Deployed #{desc}")
102
91
  end
103
92
 
104
93
  def delete(name, *options)
@@ -113,19 +102,9 @@ module Bosh::Cli::Command
113
102
  return
114
103
  end
115
104
 
116
- status, message = director.delete_deployment(name, :force => force)
117
-
118
- responses = {
119
- :done => "Deleted deployment '#{name}'",
120
- :non_trackable => "Deployment delete in progress but director " +
121
- "at '#{target}' doesn't support task tracking",
122
- :track_timeout => "Timed out out while tracking deployment " +
123
- "deletion progress",
124
- :error => "Attempted to delete deployment but received " +
125
- "an error while tracking status",
126
- }
105
+ status, _ = director.delete_deployment(name, :force => force)
127
106
 
128
- say(responses[status] || "Cannot delete deployment: #{message}")
107
+ task_report(status, "Deleted deployment `#{name}'")
129
108
  end
130
109
 
131
110
  def list
@@ -136,7 +115,7 @@ module Bosh::Cli::Command
136
115
  err("No deployments") if deployments.size == 0
137
116
 
138
117
  deployments_table = table do |t|
139
- t.headings = ["Name"]
118
+ t.headings = %w(Name)
140
119
  deployments.each do |r|
141
120
  t << [r["name"]]
142
121
  end
@@ -45,9 +45,12 @@ module Bosh::Cli::Command
45
45
 
46
46
  job = args.shift
47
47
  index = args.shift
48
- deployment_desc = "`#{deployment.green}' to `#{target_name.green}'"
49
48
  job_desc = index ? "#{job}(#{index})" : "#{job}"
50
49
 
50
+ op_desc = nil
51
+ new_state = nil
52
+ completion_desc = nil
53
+
51
54
  case operation
52
55
  when :start
53
56
  op_desc = "start #{job_desc}"
@@ -73,6 +76,8 @@ module Bosh::Cli::Command
73
76
  op_desc = "recreate #{job_desc}"
74
77
  new_state = "recreate"
75
78
  completion_desc = "#{job_desc.green} has been recreated"
79
+ else
80
+ err("Unknown operation: `#{operation}'")
76
81
  end
77
82
 
78
83
  say("You are about to #{op_desc.green}")
@@ -95,22 +100,12 @@ module Bosh::Cli::Command
95
100
 
96
101
  say("Performing `#{op_desc}'...")
97
102
 
98
- status, body = director.change_job_state(manifest["name"],
99
- manifest_yaml,
100
- job, index, new_state)
101
-
102
- responses = {
103
- :done => completion_desc,
104
- :non_trackable => "Started deployment but director at '#{target}' " +
105
- "doesn't support deployment tracking",
106
- :track_timeout => "Started deployment but timed out out "+
107
- "while tracking status",
108
- :error => "Started deployment but received an error " +
109
- "while tracking status",
110
- :invalid => "Deployment is invalid, please fix it and deploy again"
111
- }
112
-
113
- say(responses[status] || "Cannot deploy: #{body}")
103
+ status, _ =
104
+ director.change_job_state(manifest["name"],
105
+ manifest_yaml,
106
+ job, index, new_state)
107
+
108
+ task_report(status, completion_desc)
114
109
  end
115
110
 
116
111
  end
@@ -14,25 +14,20 @@ module Bosh::Cli::Command
14
14
  old_name = args.shift
15
15
  new_name = args.shift
16
16
 
17
+ say("You are about to rename #{old_name.green} to #{new_name.green}")
18
+
19
+ unless confirmed?
20
+ nl
21
+ say("Job rename canceled".green)
22
+ return
23
+ end
24
+
17
25
  sanity_check_job_rename(manifest_yaml, old_name, new_name)
18
26
 
19
- say("You are about to rename #{old_name.green} to " +
20
- "#{new_name.green} #{force}")
21
-
22
- status, body = director.rename_job(manifest["name"], manifest_yaml,
23
- old_name, new_name, force)
24
- responses = {
25
- :done => "Rename successful",
26
- :non_trackable => "Started deployment but director at '#{target}' " +
27
- "doesn't support deployment tracking",
28
- :track_timeout => "Started deployment but timed out out "+
29
- "while tracking status",
30
- :error => "Started deployment but received an error " +
31
- "while tracking status",
32
- :invalid => "Deployment is invalid, please fix it and deploy again"
33
- }
34
-
35
- say(responses[status] || "Cannot deploy: #{body}")
27
+ status, _ = director.rename_job(manifest["name"], manifest_yaml,
28
+ old_name, new_name, force)
29
+
30
+ task_report(status, "Rename successful")
36
31
  end
37
32
 
38
33
  def sanity_check_job_rename(manifest_yaml, old_name, new_name)
@@ -41,55 +36,55 @@ module Bosh::Cli::Command
41
36
  manifest = YAML.load(manifest_yaml)
42
37
  new_jobs = manifest["jobs"].map { |job| job["name"] }
43
38
  unless new_jobs.include?(new_name)
44
- err "Please update your deployment manifest to include the " +
45
- "new job name #{new_name.green}"
39
+ err("Please update your deployment manifest to include the " +
40
+ "new job name `#{new_name}'")
46
41
  end
47
42
 
48
43
  if new_jobs.include?(old_name)
49
- err "Old name #{old_name.green} is still being used in the " +
50
- "deployment file"
44
+ err("Old name `#{old_name}' is still being used in the " +
45
+ "deployment file")
51
46
  end
52
47
 
53
48
  # Make sure that the old deployment manifest contains the old job
54
49
  current_deployment = director.get_deployment(manifest["name"])
55
50
  if current_deployment["manifest"].nil?
56
- err "Director could not find manifest for deployment " +
57
- "#{manifest["name"]}"
51
+ err("Director could not find manifest for deployment " +
52
+ "`#{manifest["name"]}'")
58
53
  end
59
54
 
60
55
  current_manifest = YAML.load(current_deployment["manifest"])
61
56
  jobs = current_manifest["jobs"].map { |job| job["name"] }
62
57
  unless jobs.include?(old_name)
63
- err "Trying to rename a non existent job #{old_name}"
58
+ err("Trying to rename a non existent job `#{old_name}'")
64
59
  end
65
60
 
66
61
  # Technically we could allow this
67
62
  if jobs.include?(new_name)
68
- err "Trying to reuse an existing job name #{new_name} " +
69
- "to rename job #{old_name}"
63
+ err("Trying to reuse an existing job name `#{new_name}' " +
64
+ "to rename job `#{old_name}'")
70
65
  end
71
66
 
72
67
  # Make sure that only one job has been renamed
73
68
  added_jobs = new_jobs - jobs
74
69
 
75
70
  if added_jobs.size > 1
76
- err "Cannot rename more than one job, you are trying to " +
77
- "add #{added_jobs.inspect}"
71
+ err("Cannot rename more than one job, you are trying to " +
72
+ "add #{added_jobs.inspect}")
78
73
  end
79
74
 
80
75
  if added_jobs.first != new_name
81
- err "Manifest does not include new job #{new_name}"
76
+ err("Manifest does not include new job `#{new_name}'")
82
77
  end
83
78
 
84
79
  renamed_jobs = jobs - new_jobs
85
80
 
86
81
  if renamed_jobs.size > 1
87
- err "Cannot rename more than one job, you have changes to " +
88
- "#{renamed_jobs}"
82
+ err("Cannot rename more than one job, you have changes to " +
83
+ "#{renamed_jobs}")
89
84
  end
90
85
 
91
86
  if renamed_jobs.first != old_name
92
- err "Manifest does not rename old job #{old_name}"
87
+ err("Manifest does not rename old job `#{old_name}'")
93
88
  end
94
89
 
95
90
 
@@ -107,8 +102,8 @@ module Bosh::Cli::Command
107
102
  # Now the manifests should be the same
108
103
  manifest = YAML.load(manifest_yaml)
109
104
  if deployment_changed?(current_manifest.dup, manifest.dup)
110
- err "You cannot have any other changes to your manifest during " +
111
- "rename. Please revert the above changes and retry."
105
+ err("You cannot have any other changes to your manifest during " +
106
+ "rename. Please revert the above changes and retry.")
112
107
  end
113
108
  end
114
109
 
@@ -11,6 +11,7 @@ module Bosh::Cli::Command
11
11
  job = args.shift
12
12
  index = args.shift
13
13
  filters = nil
14
+ log_type = nil
14
15
 
15
16
  for_job = args.delete("--job")
16
17
  for_agent = args.delete("--agent")
@@ -120,8 +120,8 @@ module Bosh::Cli::Command
120
120
  refresh(" #{desc.yellow.ljust(40)}#{responses[status]}\n")
121
121
 
122
122
  if status == :error
123
- task = director.get_task(task_id)
124
- say(" #{task["result"].red}")
123
+ result = director.get_task_result(task_id)
124
+ say(" #{result.to_s.red}")
125
125
  end
126
126
 
127
127
  status == :done
@@ -53,16 +53,16 @@ module Bosh::Cli::Command
53
53
  File.join(work_dir, "releases")).latest_version
54
54
 
55
55
  say("Dev name: %s" % [dev_name ? dev_name.green : "not set".red])
56
- say("Dev version: %s" % [dev_version && dev_version > 0 ?
57
- dev_version.to_s.green : "
58
- no versions yet".red])
56
+ say("Dev version: %s" % [dev_version ?
57
+ dev_version.to_s.green :
58
+ "no versions yet".red])
59
59
  say("\n")
60
60
  say("Final name: %s" % [final_name ?
61
61
  final_name.green :
62
62
  "not set".red])
63
- say("Final version: %s" % [final_version && final_version > 0 ?
64
- final_version.to_s.green :
65
- "no versions yet".red])
63
+ say("Final version: %s" % [final_version ?
64
+ final_version.to_s.green :
65
+ "no versions yet".red])
66
66
 
67
67
  say("\n")
68
68
  say("Packages")
@@ -110,13 +110,16 @@ module Bosh::Cli::Command
110
110
  def upload_manifest(manifest_path)
111
111
  manifest = load_yaml_file(manifest_path)
112
112
  remote_release = get_remote_release(manifest["name"]) rescue nil
113
+ remote_jobs = remote_release["jobs"] if remote_release
114
+ remote_packages_sha1 = match_remote_packages(File.read(manifest_path))
113
115
  blobstore = release.blobstore
114
116
  tmpdir = Dir.mktmpdir
115
117
 
116
118
  at_exit { FileUtils.rm_rf(tmpdir) }
117
119
 
118
- compiler = Bosh::Cli::ReleaseCompiler.new(manifest_path,
119
- blobstore, remote_release)
120
+ compiler = Bosh::Cli::ReleaseCompiler.new(manifest_path, blobstore,
121
+ remote_jobs,
122
+ remote_packages_sha1)
120
123
  need_repack = true
121
124
 
122
125
  unless compiler.exists?
@@ -141,14 +144,19 @@ module Bosh::Cli::Command
141
144
  end
142
145
 
143
146
  begin
144
- remote_release = get_remote_release(tarball.release_name)
145
- if remote_release["versions"].include?(tarball.version)
146
- err("This release version has already been uploaded")
147
+ remote_release = get_remote_release(tarball.release_name) rescue nil
148
+ if remote_release
149
+ if remote_release["versions"].include?(tarball.version)
150
+ err("This release version has already been uploaded")
151
+ end
152
+ remote_jobs = remote_release["jobs"]
147
153
  end
148
154
 
149
155
  if repack
156
+ remote_packages_sha1 = match_remote_packages(tarball.manifest)
157
+
150
158
  say("Checking if can repack release for faster upload...")
151
- repacked_path = tarball.repack(remote_release)
159
+ repacked_path = tarball.repack(remote_jobs, remote_packages_sha1)
152
160
  if repacked_path.nil?
153
161
  say("Uploading the whole release".green)
154
162
  else
@@ -163,18 +171,9 @@ module Bosh::Cli::Command
163
171
  end
164
172
 
165
173
  say("\nUploading release...\n")
166
- status, message = director.upload_release(tarball_path)
167
-
168
- responses = {
169
- :done => "Release uploaded and updated",
170
- :non_trackable => "Uploaded release but director at #{target} " +
171
- "doesn't support update tracking",
172
- :track_timeout => "Uploaded release but timed out out " +
173
- "while tracking status",
174
- :error => "Uploaded release but received an error while tracking status"
175
- }
176
-
177
- say(responses[status] || "Cannot upload release: #{message}")
174
+ status, _ = director.upload_release(tarball_path)
175
+
176
+ task_report(status, "Release uploaded")
178
177
  end
179
178
 
180
179
  def create(*options)
@@ -200,10 +199,10 @@ module Bosh::Cli::Command
200
199
  def create_from_spec(*options)
201
200
  flags = options.inject({}) { |h, option| h[option] = true; h }
202
201
 
203
- final = flags.delete("--final")
204
- force = flags.delete("--force")
202
+ final = flags.delete("--final")
203
+ force = flags.delete("--force")
205
204
  manifest_only = !flags.delete("--with-tarball")
206
- dry_run = flags.delete("--dry-run")
205
+ dry_run = flags.delete("--dry-run")
207
206
 
208
207
  if final && !release.has_blobstore_secret?
209
208
  say("Can't create final release without blobstore secret".red)
@@ -405,20 +404,9 @@ module Bosh::Cli::Command
405
404
  end
406
405
 
407
406
  if confirmed?
408
- status, body = director.delete_release(name, :force => force,
407
+ status, _ = director.delete_release(name, :force => force,
409
408
  :version => version)
410
- responses = {
411
- :done => "Deleted #{desc}",
412
- :non_trackable => "Started deleting release but director " +
413
- "at '#{target}' doesn't support " +
414
- "deployment tracking",
415
- :track_timeout => "Started deleting release but timed out out " +
416
- "while tracking status",
417
- :error => "Started deleting release but received an error " +
418
- "while tracking status",
419
- }
420
-
421
- say(responses[status] || "Cannot delete release: #{body}")
409
+ task_report(status, "Deleted #{desc}")
422
410
  else
423
411
  say("Canceled deleting release".green)
424
412
  end
@@ -486,5 +474,16 @@ module Bosh::Cli::Command
486
474
 
487
475
  release
488
476
  end
477
+
478
+ def match_remote_packages(manifest_yaml)
479
+ # Catch exceptions to be friendly to old directors
480
+ result = director.match_packages(manifest_yaml) rescue []
481
+
482
+ unless result.is_a?(Array)
483
+ say("Cannot find existing packages info " +
484
+ "in the director response, maybe old director?")
485
+ end
486
+ result
487
+ end
489
488
  end
490
489
  end