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.
- data/lib/cli/commands/base.rb +37 -0
- data/lib/cli/commands/cloudcheck.rb +13 -29
- data/lib/cli/commands/deployment.rb +6 -27
- data/lib/cli/commands/job_management.rb +12 -17
- data/lib/cli/commands/job_rename.rb +29 -34
- data/lib/cli/commands/log_management.rb +1 -0
- data/lib/cli/commands/maintenance.rb +2 -2
- data/lib/cli/commands/misc.rb +6 -6
- data/lib/cli/commands/release.rb +33 -34
- data/lib/cli/commands/ssh.rb +4 -3
- data/lib/cli/commands/stemcell.rb +9 -29
- data/lib/cli/config.rb +2 -2
- data/lib/cli/core_ext.rb +4 -1
- data/lib/cli/deployment_helper.rb +1 -1
- data/lib/cli/director.rb +159 -73
- data/lib/cli/event_log_renderer.rb +49 -13
- data/lib/cli/release_compiler.rb +6 -9
- data/lib/cli/release_tarball.rb +10 -5
- data/lib/cli/runner.rb +36 -1
- data/lib/cli/task_log_renderer.rb +1 -1
- data/lib/cli/task_tracker.rb +13 -6
- data/lib/cli/version.rb +1 -1
- data/spec/unit/core_ext_spec.rb +5 -1
- data/spec/unit/director_spec.rb +40 -23
- data/spec/unit/job_rename_spec.rb +4 -0
- data/spec/unit/release_tarball_spec.rb +3 -1
- data/spec/unit/runner_spec.rb +20 -0
- data/spec/unit/task_tracker_spec.rb +0 -27
- metadata +4 -4
data/lib/cli/commands/base.rb
CHANGED
@@ -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,
|
32
|
-
|
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,
|
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
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
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
|
-
|
83
|
+
say("Cloudcheck is finished".green)
|
89
84
|
end
|
90
85
|
|
91
|
-
|
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,
|
89
|
-
|
90
|
-
|
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,
|
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
|
-
|
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 =
|
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,
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
status,
|
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
|
45
|
-
"new job name
|
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
|
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
|
57
|
-
"
|
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
|
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
|
69
|
-
"to rename job
|
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
|
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
|
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
|
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
|
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
|
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
|
|
@@ -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
|
-
|
124
|
-
say(" #{
|
123
|
+
result = director.get_task_result(task_id)
|
124
|
+
say(" #{result.to_s.red}")
|
125
125
|
end
|
126
126
|
|
127
127
|
status == :done
|
data/lib/cli/commands/misc.rb
CHANGED
@@ -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
|
57
|
-
|
58
|
-
|
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
|
64
|
-
|
65
|
-
|
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")
|
data/lib/cli/commands/release.rb
CHANGED
@@ -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
|
-
|
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
|
146
|
-
|
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(
|
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,
|
167
|
-
|
168
|
-
|
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
|
204
|
-
force
|
202
|
+
final = flags.delete("--final")
|
203
|
+
force = flags.delete("--force")
|
205
204
|
manifest_only = !flags.delete("--with-tarball")
|
206
|
-
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,
|
407
|
+
status, _ = director.delete_release(name, :force => force,
|
409
408
|
:version => version)
|
410
|
-
|
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
|