bosh_cli 0.19.1 → 0.19.2
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.
- 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
|