bosh_cli 0.16
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/README +4 -0
- data/Rakefile +55 -0
- data/bin/bosh +17 -0
- data/lib/cli.rb +76 -0
- data/lib/cli/cache.rb +44 -0
- data/lib/cli/changeset_helper.rb +142 -0
- data/lib/cli/command_definition.rb +52 -0
- data/lib/cli/commands/base.rb +245 -0
- data/lib/cli/commands/biff.rb +300 -0
- data/lib/cli/commands/blob.rb +125 -0
- data/lib/cli/commands/cloudcheck.rb +169 -0
- data/lib/cli/commands/deployment.rb +147 -0
- data/lib/cli/commands/job.rb +42 -0
- data/lib/cli/commands/job_management.rb +117 -0
- data/lib/cli/commands/log_management.rb +81 -0
- data/lib/cli/commands/maintenance.rb +131 -0
- data/lib/cli/commands/misc.rb +240 -0
- data/lib/cli/commands/package.rb +112 -0
- data/lib/cli/commands/property_management.rb +125 -0
- data/lib/cli/commands/release.rb +469 -0
- data/lib/cli/commands/ssh.rb +271 -0
- data/lib/cli/commands/stemcell.rb +184 -0
- data/lib/cli/commands/task.rb +213 -0
- data/lib/cli/commands/user.rb +28 -0
- data/lib/cli/commands/vms.rb +53 -0
- data/lib/cli/config.rb +154 -0
- data/lib/cli/core_ext.rb +145 -0
- data/lib/cli/dependency_helper.rb +62 -0
- data/lib/cli/deployment_helper.rb +263 -0
- data/lib/cli/deployment_manifest_compiler.rb +28 -0
- data/lib/cli/director.rb +633 -0
- data/lib/cli/director_task.rb +64 -0
- data/lib/cli/errors.rb +48 -0
- data/lib/cli/event_log_renderer.rb +351 -0
- data/lib/cli/job_builder.rb +226 -0
- data/lib/cli/package_builder.rb +254 -0
- data/lib/cli/packaging_helper.rb +248 -0
- data/lib/cli/release.rb +176 -0
- data/lib/cli/release_builder.rb +215 -0
- data/lib/cli/release_compiler.rb +178 -0
- data/lib/cli/release_tarball.rb +272 -0
- data/lib/cli/runner.rb +771 -0
- data/lib/cli/stemcell.rb +83 -0
- data/lib/cli/task_log_renderer.rb +40 -0
- data/lib/cli/templates/help_message.erb +75 -0
- data/lib/cli/validation.rb +42 -0
- data/lib/cli/version.rb +7 -0
- data/lib/cli/version_calc.rb +48 -0
- data/lib/cli/versions_index.rb +126 -0
- data/lib/cli/yaml_helper.rb +62 -0
- data/spec/assets/biff/bad_gateway_config.yml +28 -0
- data/spec/assets/biff/good_simple_config.yml +63 -0
- data/spec/assets/biff/good_simple_golden_config.yml +63 -0
- data/spec/assets/biff/good_simple_template.erb +69 -0
- data/spec/assets/biff/multiple_subnets_config.yml +40 -0
- data/spec/assets/biff/network_only_template.erb +34 -0
- data/spec/assets/biff/no_cc_config.yml +27 -0
- data/spec/assets/biff/no_range_config.yml +27 -0
- data/spec/assets/biff/no_subnet_config.yml +16 -0
- data/spec/assets/biff/ok_network_config.yml +30 -0
- data/spec/assets/biff/properties_template.erb +6 -0
- data/spec/assets/deployment.MF +0 -0
- data/spec/assets/plugins/bosh/cli/commands/echo.rb +43 -0
- data/spec/assets/plugins/bosh/cli/commands/ruby.rb +24 -0
- data/spec/assets/release/jobs/cacher.tgz +0 -0
- data/spec/assets/release/jobs/cacher/config/file1.conf +0 -0
- data/spec/assets/release/jobs/cacher/config/file2.conf +0 -0
- data/spec/assets/release/jobs/cacher/job.MF +6 -0
- data/spec/assets/release/jobs/cacher/monit +1 -0
- data/spec/assets/release/jobs/cleaner.tgz +0 -0
- data/spec/assets/release/jobs/cleaner/job.MF +4 -0
- data/spec/assets/release/jobs/cleaner/monit +1 -0
- data/spec/assets/release/jobs/sweeper.tgz +0 -0
- data/spec/assets/release/jobs/sweeper/config/test.conf +1 -0
- data/spec/assets/release/jobs/sweeper/job.MF +5 -0
- data/spec/assets/release/jobs/sweeper/monit +1 -0
- data/spec/assets/release/packages/mutator.tar.gz +0 -0
- data/spec/assets/release/packages/stuff.tgz +0 -0
- data/spec/assets/release/release.MF +17 -0
- data/spec/assets/release_invalid_checksum.tgz +0 -0
- data/spec/assets/release_invalid_jobs.tgz +0 -0
- data/spec/assets/release_no_name.tgz +0 -0
- data/spec/assets/release_no_version.tgz +0 -0
- data/spec/assets/stemcell/image +1 -0
- data/spec/assets/stemcell/stemcell.MF +6 -0
- data/spec/assets/stemcell_invalid_mf.tgz +0 -0
- data/spec/assets/stemcell_no_image.tgz +0 -0
- data/spec/assets/valid_release.tgz +0 -0
- data/spec/assets/valid_stemcell.tgz +0 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/unit/base_command_spec.rb +66 -0
- data/spec/unit/biff_spec.rb +135 -0
- data/spec/unit/cache_spec.rb +36 -0
- data/spec/unit/cli_commands_spec.rb +481 -0
- data/spec/unit/config_spec.rb +139 -0
- data/spec/unit/core_ext_spec.rb +77 -0
- data/spec/unit/dependency_helper_spec.rb +52 -0
- data/spec/unit/deployment_manifest_compiler_spec.rb +63 -0
- data/spec/unit/director_spec.rb +511 -0
- data/spec/unit/director_task_spec.rb +48 -0
- data/spec/unit/event_log_renderer_spec.rb +171 -0
- data/spec/unit/hash_changeset_spec.rb +73 -0
- data/spec/unit/job_builder_spec.rb +454 -0
- data/spec/unit/package_builder_spec.rb +567 -0
- data/spec/unit/release_builder_spec.rb +65 -0
- data/spec/unit/release_spec.rb +66 -0
- data/spec/unit/release_tarball_spec.rb +33 -0
- data/spec/unit/runner_spec.rb +140 -0
- data/spec/unit/ssh_spec.rb +78 -0
- data/spec/unit/stemcell_spec.rb +17 -0
- data/spec/unit/version_calc_spec.rb +27 -0
- data/spec/unit/versions_index_spec.rb +132 -0
- metadata +338 -0
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
|
2
|
+
|
|
3
|
+
module Bosh::Cli::Command
|
|
4
|
+
class Release < Base
|
|
5
|
+
DEFAULT_RELEASE_NAME = "bosh-release"
|
|
6
|
+
|
|
7
|
+
include Bosh::Cli::DependencyHelper
|
|
8
|
+
include Bosh::Cli::VersionCalc
|
|
9
|
+
|
|
10
|
+
def init(base=nil, *options)
|
|
11
|
+
flags = options.inject({}) { |h, option| h[option] = true; h }
|
|
12
|
+
git = flags.delete("--git")
|
|
13
|
+
|
|
14
|
+
if base
|
|
15
|
+
FileUtils.mkdir_p(base) unless Dir.exist?(base)
|
|
16
|
+
Dir.chdir(base)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
err("Release already initialized") if in_release_dir?
|
|
20
|
+
|
|
21
|
+
git_init if git
|
|
22
|
+
|
|
23
|
+
%w[jobs packages src blobs].each do |dir|
|
|
24
|
+
FileUtils.mkdir(dir)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# initialize an empty blob_index file
|
|
28
|
+
blobs = {}
|
|
29
|
+
File.open("blob_index.yml", "w") do |f|
|
|
30
|
+
YAML.dump(blobs, f)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
say("Release directory initialized".green)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def git_init
|
|
37
|
+
out = %x{git init 2>&1}
|
|
38
|
+
if $? != 0
|
|
39
|
+
say("error running 'git init':\n#{out}")
|
|
40
|
+
else
|
|
41
|
+
File.open(".gitignore", "w") do |f|
|
|
42
|
+
f.puts("config/dev.yml\nconfig/private.yml")
|
|
43
|
+
f.puts("blobs\nreleases/*.tgz")
|
|
44
|
+
f.puts("dev_releases\n.dev_builds")
|
|
45
|
+
f.puts(".final_builds/jobs/**/*.tgz")
|
|
46
|
+
f.puts(".final_builds/packages/**/*.tgz")
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
rescue Errno::ENOENT
|
|
50
|
+
say("Unable to run 'git init'".red)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def verify(tarball_path, *options)
|
|
54
|
+
tarball = Bosh::Cli::ReleaseTarball.new(tarball_path)
|
|
55
|
+
|
|
56
|
+
say("\nVerifying release...")
|
|
57
|
+
tarball.validate
|
|
58
|
+
nl
|
|
59
|
+
|
|
60
|
+
if tarball.valid?
|
|
61
|
+
say("'%s' is a valid release" % [tarball_path] )
|
|
62
|
+
else
|
|
63
|
+
say("'%s' is not a valid release:" % [tarball_path] )
|
|
64
|
+
for error in tarball.errors
|
|
65
|
+
say("- %s" % [error])
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def upload(release_file = nil)
|
|
71
|
+
auth_required
|
|
72
|
+
|
|
73
|
+
if release_file.nil?
|
|
74
|
+
check_if_release_dir
|
|
75
|
+
release_file = release.latest_release_filename
|
|
76
|
+
if release_file.nil?
|
|
77
|
+
err("The information about latest generated release is missing, " +
|
|
78
|
+
"please provide release filename")
|
|
79
|
+
end
|
|
80
|
+
unless confirmed?("Upload release " +
|
|
81
|
+
"`#{File.basename(release_file).green}' " +
|
|
82
|
+
"to `#{target_name.green}'")
|
|
83
|
+
err("Canceled upload")
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
file_type = `file --mime-type -b '#{release_file}'`
|
|
88
|
+
|
|
89
|
+
if file_type =~ /text\/(plain|yaml)/
|
|
90
|
+
upload_manifest(release_file)
|
|
91
|
+
else # Just assume tarball
|
|
92
|
+
upload_tarball(release_file)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def upload_manifest(manifest_path)
|
|
97
|
+
manifest = load_yaml_file(manifest_path)
|
|
98
|
+
remote_release = get_remote_release(manifest["name"]) rescue nil
|
|
99
|
+
blobstore = release.blobstore
|
|
100
|
+
tmpdir = Dir.mktmpdir
|
|
101
|
+
|
|
102
|
+
at_exit { FileUtils.rm_rf(tmpdir) }
|
|
103
|
+
|
|
104
|
+
compiler = Bosh::Cli::ReleaseCompiler.new(manifest_path,
|
|
105
|
+
blobstore, remote_release)
|
|
106
|
+
need_repack = true
|
|
107
|
+
|
|
108
|
+
unless compiler.exists?
|
|
109
|
+
compiler.tarball_path = File.join(tmpdir, "release.tgz")
|
|
110
|
+
compiler.compile
|
|
111
|
+
need_repack = false
|
|
112
|
+
end
|
|
113
|
+
upload_tarball(compiler.tarball_path, :repack => need_repack)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def upload_tarball(tarball_path, options = {})
|
|
117
|
+
tarball = Bosh::Cli::ReleaseTarball.new(tarball_path)
|
|
118
|
+
# Trying to repack release by default
|
|
119
|
+
repack = options.has_key?(:repack) ? !!options[:repack] : true
|
|
120
|
+
|
|
121
|
+
say("\nVerifying release...")
|
|
122
|
+
tarball.validate(:allow_sparse => true)
|
|
123
|
+
nl
|
|
124
|
+
|
|
125
|
+
unless tarball.valid?
|
|
126
|
+
err("Release is invalid, please fix, verify and upload again")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
begin
|
|
130
|
+
remote_release = get_remote_release(tarball.release_name)
|
|
131
|
+
if remote_release["versions"].include?(tarball.version)
|
|
132
|
+
err("This release version has already been uploaded")
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
if repack
|
|
136
|
+
say("Checking if can repack release for faster upload...")
|
|
137
|
+
repacked_path = tarball.repack(remote_release)
|
|
138
|
+
if repacked_path.nil?
|
|
139
|
+
say("Uploading the whole release".green)
|
|
140
|
+
else
|
|
141
|
+
say("Release repacked " +
|
|
142
|
+
"(new size is #{pretty_size(repacked_path)})".green)
|
|
143
|
+
tarball_path = repacked_path
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
rescue Bosh::Cli::DirectorError
|
|
147
|
+
# It's OK for director to choke on getting
|
|
148
|
+
# a release info (think new releases)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
say("\nUploading release...\n")
|
|
152
|
+
status, message = director.upload_release(tarball_path)
|
|
153
|
+
|
|
154
|
+
responses = {
|
|
155
|
+
:done => "Release uploaded and updated",
|
|
156
|
+
:non_trackable => "Uploaded release but director at #{target} " +
|
|
157
|
+
"doesn't support update tracking",
|
|
158
|
+
:track_timeout => "Uploaded release but timed out out " +
|
|
159
|
+
"while tracking status",
|
|
160
|
+
:error => "Uploaded release but received an error while tracking status"
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
say(responses[status] || "Cannot upload release: #{message}")
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def create(*options)
|
|
167
|
+
check_if_release_dir
|
|
168
|
+
if options.size == 1 && File.file?(options[0])
|
|
169
|
+
create_from_manifest(options[0])
|
|
170
|
+
release_filename = options[0]
|
|
171
|
+
else
|
|
172
|
+
release_filename = create_from_spec(*options)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
if release_filename
|
|
176
|
+
release.latest_release_filename = release_filename
|
|
177
|
+
release.save_config
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def create_from_manifest(manifest_file)
|
|
182
|
+
say("Recreating release from the manifest")
|
|
183
|
+
Bosh::Cli::ReleaseCompiler.compile(manifest_file, release.blobstore)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def create_from_spec(*options)
|
|
187
|
+
flags = options.inject({}) { |h, option| h[option] = true; h }
|
|
188
|
+
|
|
189
|
+
final = flags.delete("--final")
|
|
190
|
+
force = flags.delete("--force")
|
|
191
|
+
manifest_only = !flags.delete("--with-tarball")
|
|
192
|
+
dry_run = flags.delete("--dry-run")
|
|
193
|
+
|
|
194
|
+
if final && !release.has_blobstore_secret?
|
|
195
|
+
say("Can't create final release without blobstore secret".red)
|
|
196
|
+
exit(1)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
if flags.size > 0
|
|
200
|
+
say("Unknown flags: #{flags.keys.join(", ")}".red)
|
|
201
|
+
show_usage
|
|
202
|
+
exit(1)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
if !force
|
|
206
|
+
check_dirty_blobs
|
|
207
|
+
check_if_dirty_state
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
confirmation = "Are you sure you want to " +
|
|
211
|
+
"generate #{'final'.red} version? "
|
|
212
|
+
|
|
213
|
+
if final && !dry_run && !confirmed?(confirmation)
|
|
214
|
+
say("Canceled release generation".green)
|
|
215
|
+
exit(1)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
packages = []
|
|
219
|
+
jobs = []
|
|
220
|
+
|
|
221
|
+
if final
|
|
222
|
+
header("Building FINAL release".green)
|
|
223
|
+
release_name = release.final_name
|
|
224
|
+
else
|
|
225
|
+
release_name = release.dev_name
|
|
226
|
+
header("Building DEV release".green)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
if version_greater(release.min_cli_version, Bosh::Cli::VERSION)
|
|
230
|
+
err("You should use CLI >= #{release.min_cli_version} " +
|
|
231
|
+
"with this release, you have #{Bosh::Cli::VERSION}")
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
if release_name.blank?
|
|
235
|
+
confirmation = "Please enter %s release name: " % [
|
|
236
|
+
final ? "final" : "development"]
|
|
237
|
+
name = interactive? ? ask(confirmation).to_s : DEFAULT_RELEASE_NAME
|
|
238
|
+
err("Canceled release creation, no name given") if name.blank?
|
|
239
|
+
if final
|
|
240
|
+
release.final_name = name
|
|
241
|
+
else
|
|
242
|
+
release.dev_name = name
|
|
243
|
+
end
|
|
244
|
+
release.save_config
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
header("Building packages")
|
|
248
|
+
Dir[File.join(work_dir, "packages", "*", "spec")].each do |package_spec|
|
|
249
|
+
package = Bosh::Cli::PackageBuilder.new(package_spec, work_dir,
|
|
250
|
+
final, release.blobstore)
|
|
251
|
+
package.dry_run = dry_run
|
|
252
|
+
say("Building #{package.name.green}...")
|
|
253
|
+
package.build
|
|
254
|
+
packages << package
|
|
255
|
+
nl
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
if packages.size > 0
|
|
259
|
+
package_index = packages.inject({}) do |index, package|
|
|
260
|
+
index[package.name] = package.dependencies
|
|
261
|
+
index
|
|
262
|
+
end
|
|
263
|
+
sorted_packages = tsort_packages(package_index)
|
|
264
|
+
header("Resolving dependencies")
|
|
265
|
+
say("Dependencies resolved, correct build order is:")
|
|
266
|
+
for package_name in sorted_packages
|
|
267
|
+
say("- %s" % [package_name])
|
|
268
|
+
end
|
|
269
|
+
nl
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
built_package_names = packages.map { |package| package.name }
|
|
273
|
+
|
|
274
|
+
header("Building jobs")
|
|
275
|
+
Dir[File.join(work_dir, "jobs", "*")].each do |job_dir|
|
|
276
|
+
next unless File.directory?(job_dir)
|
|
277
|
+
prepare_script = File.join(job_dir, "prepare")
|
|
278
|
+
job_spec = File.join(job_dir, "spec")
|
|
279
|
+
|
|
280
|
+
if File.exists?(prepare_script)
|
|
281
|
+
say("Found prepare script in `#{File.basename(job_dir)}'")
|
|
282
|
+
Bosh::Cli::JobBuilder.run_prepare_script(prepare_script)
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
job = Bosh::Cli::JobBuilder.new(job_spec, work_dir, final,
|
|
286
|
+
release.blobstore, built_package_names)
|
|
287
|
+
job.dry_run = dry_run
|
|
288
|
+
say("Building #{job.name.green}...")
|
|
289
|
+
job.build
|
|
290
|
+
jobs << job
|
|
291
|
+
nl
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
builder = Bosh::Cli::ReleaseBuilder.new(release, packages,
|
|
295
|
+
jobs, :final => final)
|
|
296
|
+
|
|
297
|
+
unless dry_run
|
|
298
|
+
if manifest_only
|
|
299
|
+
builder.build(:generate_tarball => false)
|
|
300
|
+
else
|
|
301
|
+
builder.build(:generate_tarball => true)
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
header("Release summary")
|
|
306
|
+
show_summary(builder)
|
|
307
|
+
nl
|
|
308
|
+
|
|
309
|
+
return nil if dry_run
|
|
310
|
+
|
|
311
|
+
say("Release version: #{builder.version.to_s.green}")
|
|
312
|
+
say("Release manifest: #{builder.manifest_path.green}")
|
|
313
|
+
|
|
314
|
+
unless manifest_only
|
|
315
|
+
say("Release tarball (#{pretty_size(builder.tarball_path)}): " +
|
|
316
|
+
builder.tarball_path.green)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
release.min_cli_version = Bosh::Cli::VERSION
|
|
320
|
+
release.save_config
|
|
321
|
+
|
|
322
|
+
builder.manifest_path
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def reset
|
|
326
|
+
check_if_release_dir
|
|
327
|
+
|
|
328
|
+
say("Your dev release environment will be completely reset".red)
|
|
329
|
+
if confirmed?
|
|
330
|
+
say("Removing dev_builds index...")
|
|
331
|
+
FileUtils.rm_rf(".dev_builds")
|
|
332
|
+
say("Clearing dev name...")
|
|
333
|
+
release.dev_name = nil
|
|
334
|
+
release.save_config
|
|
335
|
+
say("Removing dev tarballs...")
|
|
336
|
+
FileUtils.rm_rf("dev_releases")
|
|
337
|
+
|
|
338
|
+
say("Release has been reset".green)
|
|
339
|
+
else
|
|
340
|
+
say("Canceled")
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def list
|
|
345
|
+
auth_required
|
|
346
|
+
releases = director.list_releases.sort do |r1, r2|
|
|
347
|
+
r1["name"] <=> r2["name"]
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
err("No releases") if releases.empty?
|
|
351
|
+
|
|
352
|
+
releases_table = table do |t|
|
|
353
|
+
t.headings = "Name", "Versions"
|
|
354
|
+
releases.each do |r|
|
|
355
|
+
versions = r["versions"].sort do |v1, v2|
|
|
356
|
+
version_cmp(v1, v2)
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
t << [r["name"], versions.join(", ")]
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
nl
|
|
364
|
+
say(releases_table)
|
|
365
|
+
nl
|
|
366
|
+
say("Releases total: %d" % releases.size)
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def delete(name, *options)
|
|
370
|
+
auth_required
|
|
371
|
+
force = options.include?("--force")
|
|
372
|
+
options.delete("--force")
|
|
373
|
+
version = options.shift
|
|
374
|
+
|
|
375
|
+
desc = "release `#{name}'"
|
|
376
|
+
desc << " version #{version}" if version
|
|
377
|
+
|
|
378
|
+
if force
|
|
379
|
+
say("Deleting #{desc} (FORCED DELETE, WILL IGNORE ERRORS)".red)
|
|
380
|
+
elsif options.size > 0
|
|
381
|
+
err("Unknown option, currently only '--force' is supported")
|
|
382
|
+
else
|
|
383
|
+
say("Deleting #{desc}".red)
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
if confirmed?
|
|
387
|
+
status, body = director.delete_release(name, :force => force,
|
|
388
|
+
:version => version)
|
|
389
|
+
responses = {
|
|
390
|
+
:done => "Deleted #{desc}",
|
|
391
|
+
:non_trackable => "Started deleting release but director " +
|
|
392
|
+
"at '#{target}' doesn't support " +
|
|
393
|
+
"deployment tracking",
|
|
394
|
+
:track_timeout => "Started deleting release but timed out out " +
|
|
395
|
+
"while tracking status",
|
|
396
|
+
:error => "Started deleting release but received an error " +
|
|
397
|
+
"while tracking status",
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
say(responses[status] || "Cannot delete release: #{body}")
|
|
401
|
+
else
|
|
402
|
+
say("Canceled deleting release".green)
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
private
|
|
407
|
+
|
|
408
|
+
def show_summary(builder)
|
|
409
|
+
packages_table = table do |t|
|
|
410
|
+
t.headings = %w(Name Version Notes Fingerprint)
|
|
411
|
+
builder.packages.each do |package|
|
|
412
|
+
t << artefact_summary(package)
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
jobs_table = table do |t|
|
|
417
|
+
t.headings = %w(Name Version Notes Fingerprint)
|
|
418
|
+
builder.jobs.each do |job|
|
|
419
|
+
t << artefact_summary(job)
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
say("Packages")
|
|
424
|
+
say(packages_table)
|
|
425
|
+
nl
|
|
426
|
+
say("Jobs")
|
|
427
|
+
say(jobs_table)
|
|
428
|
+
|
|
429
|
+
affected_jobs = builder.affected_jobs
|
|
430
|
+
|
|
431
|
+
if affected_jobs.size > 0
|
|
432
|
+
nl
|
|
433
|
+
say("Jobs affected by changes in this release")
|
|
434
|
+
|
|
435
|
+
affected_jobs_table = table do |t|
|
|
436
|
+
t.headings = %w(Name Version)
|
|
437
|
+
affected_jobs.each do |job|
|
|
438
|
+
t << [job.name, job.version]
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
say(affected_jobs_table)
|
|
443
|
+
end
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
def artefact_summary(artefact)
|
|
447
|
+
result = []
|
|
448
|
+
result << artefact.name
|
|
449
|
+
result << artefact.version
|
|
450
|
+
result << artefact.notes.join(", ")
|
|
451
|
+
result << artefact.fingerprint
|
|
452
|
+
result
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
def get_remote_release(name)
|
|
456
|
+
release = director.get_release(name)
|
|
457
|
+
|
|
458
|
+
unless release.is_a?(Hash) &&
|
|
459
|
+
release.has_key?("jobs") &&
|
|
460
|
+
release.has_key?("packages")
|
|
461
|
+
raise Bosh::Cli::DirectorError,
|
|
462
|
+
"Cannot find version, jobs and packages info " +
|
|
463
|
+
"in the director response, maybe old director?"
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
release
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
end
|