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.
- data/bin/bosh +0 -9
- data/lib/cli.rb +69 -64
- data/lib/cli/backup_destination_path.rb +33 -0
- data/lib/cli/base_command.rb +57 -56
- data/lib/cli/blob_manager.rb +12 -12
- data/lib/cli/changeset_helper.rb +6 -7
- data/lib/cli/client/director.rb +724 -0
- data/lib/cli/command_handler.rb +6 -7
- data/lib/cli/commands/backup.rb +39 -0
- data/lib/cli/commands/biff.rb +42 -21
- data/lib/cli/commands/blob_management.rb +1 -1
- data/lib/cli/commands/cloudcheck.rb +11 -13
- data/lib/cli/commands/deployment.rb +53 -37
- data/lib/cli/commands/help.rb +3 -2
- data/lib/cli/commands/job_management.rb +67 -103
- data/lib/cli/commands/job_rename.rb +6 -8
- data/lib/cli/commands/log_management.rb +78 -55
- data/lib/cli/commands/maintenance.rb +36 -30
- data/lib/cli/commands/misc.rb +72 -51
- data/lib/cli/commands/package.rb +2 -2
- data/lib/cli/commands/property_management.rb +10 -12
- data/lib/cli/commands/release.rb +236 -133
- data/lib/cli/commands/snapshot.rb +93 -0
- data/lib/cli/commands/ssh.rb +216 -213
- data/lib/cli/commands/stemcell.rb +46 -34
- data/lib/cli/commands/task.rb +2 -2
- data/lib/cli/commands/user.rb +27 -3
- data/lib/cli/commands/vm.rb +28 -0
- data/lib/cli/commands/vms.rb +81 -23
- data/lib/cli/config.rb +6 -2
- data/lib/cli/core_ext.rb +31 -30
- data/lib/cli/deployment_helper.rb +134 -159
- data/lib/cli/deployment_manifest.rb +66 -0
- data/lib/cli/deployment_manifest_compiler.rb +0 -3
- data/lib/cli/event_log_renderer.rb +10 -10
- data/lib/cli/file_with_progress_bar.rb +52 -0
- data/lib/cli/job_builder.rb +1 -1
- data/lib/cli/job_command_args.rb +23 -0
- data/lib/cli/job_property_collection.rb +4 -7
- data/lib/cli/job_property_validator.rb +22 -12
- data/lib/cli/job_state.rb +54 -0
- data/lib/cli/line_wrap.rb +54 -0
- data/lib/cli/packaging_helper.rb +10 -10
- data/lib/cli/release.rb +18 -15
- data/lib/cli/release_builder.rb +9 -4
- data/lib/cli/release_compiler.rb +9 -9
- data/lib/cli/release_tarball.rb +3 -6
- data/lib/cli/resurrection.rb +31 -0
- data/lib/cli/runner.rb +56 -30
- data/lib/cli/stemcell.rb +25 -10
- data/lib/cli/task_log_renderer.rb +1 -1
- data/lib/cli/task_tracker.rb +10 -9
- data/lib/cli/validation.rb +3 -1
- data/lib/cli/version.rb +1 -1
- data/lib/cli/version_calc.rb +5 -18
- data/lib/cli/versions_index.rb +1 -1
- data/lib/cli/vm_state.rb +43 -0
- data/lib/cli/yaml_helper.rb +26 -35
- metadata +75 -208
- data/Rakefile +0 -56
- data/lib/cli/director.rb +0 -628
- data/spec/assets/biff/bad_gateway_config.yml +0 -28
- data/spec/assets/biff/good_simple_config.yml +0 -63
- data/spec/assets/biff/good_simple_golden_config.yml +0 -63
- data/spec/assets/biff/good_simple_template.erb +0 -69
- data/spec/assets/biff/ip_out_of_range.yml +0 -63
- data/spec/assets/biff/multiple_subnets_config.yml +0 -40
- data/spec/assets/biff/network_only_template.erb +0 -34
- data/spec/assets/biff/no_cc_config.yml +0 -27
- data/spec/assets/biff/no_range_config.yml +0 -27
- data/spec/assets/biff/no_subnet_config.yml +0 -16
- data/spec/assets/biff/ok_network_config.yml +0 -30
- data/spec/assets/biff/properties_template.erb +0 -6
- data/spec/assets/config/atmos/config/final.yml +0 -6
- data/spec/assets/config/atmos/config/private.yml +0 -4
- data/spec/assets/config/bad-providers/config/final.yml +0 -5
- data/spec/assets/config/bad-providers/config/private.yml +0 -4
- data/spec/assets/config/deprecation/config/final.yml +0 -5
- data/spec/assets/config/deprecation/config/private.yml +0 -2
- data/spec/assets/config/local/config/final.yml +0 -5
- data/spec/assets/config/local/config/private.yml +0 -1
- data/spec/assets/config/s3/config/final.yml +0 -5
- data/spec/assets/config/s3/config/private.yml +0 -5
- data/spec/assets/config/swift-hp/config/final.yml +0 -6
- data/spec/assets/config/swift-hp/config/private.yml +0 -7
- data/spec/assets/config/swift-rackspace/config/final.yml +0 -6
- data/spec/assets/config/swift-rackspace/config/private.yml +0 -6
- data/spec/assets/deployment.MF +0 -0
- data/spec/assets/plugins/bosh/cli/commands/echo.rb +0 -43
- data/spec/assets/plugins/bosh/cli/commands/ruby.rb +0 -24
- 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 +0 -6
- data/spec/assets/release/jobs/cacher/monit +0 -1
- data/spec/assets/release/jobs/cleaner.tgz +0 -0
- data/spec/assets/release/jobs/cleaner/job.MF +0 -4
- data/spec/assets/release/jobs/cleaner/monit +0 -1
- data/spec/assets/release/jobs/sweeper.tgz +0 -0
- data/spec/assets/release/jobs/sweeper/config/test.conf +0 -1
- data/spec/assets/release/jobs/sweeper/job.MF +0 -5
- data/spec/assets/release/jobs/sweeper/monit +0 -1
- 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 +0 -17
- 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 +0 -1
- data/spec/assets/stemcell/stemcell.MF +0 -6
- 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 +0 -28
- data/spec/unit/base_command_spec.rb +0 -87
- data/spec/unit/biff_spec.rb +0 -172
- data/spec/unit/blob_manager_spec.rb +0 -288
- data/spec/unit/cache_spec.rb +0 -36
- data/spec/unit/cli_commands_spec.rb +0 -356
- data/spec/unit/config_spec.rb +0 -125
- data/spec/unit/core_ext_spec.rb +0 -81
- data/spec/unit/dependency_helper_spec.rb +0 -52
- data/spec/unit/deployment_manifest_compiler_spec.rb +0 -63
- data/spec/unit/deployment_manifest_spec.rb +0 -153
- data/spec/unit/director_spec.rb +0 -471
- data/spec/unit/director_task_spec.rb +0 -48
- data/spec/unit/event_log_renderer_spec.rb +0 -171
- data/spec/unit/hash_changeset_spec.rb +0 -73
- data/spec/unit/job_builder_spec.rb +0 -455
- data/spec/unit/job_property_collection_spec.rb +0 -111
- data/spec/unit/job_property_validator_spec.rb +0 -7
- data/spec/unit/job_rename_spec.rb +0 -200
- data/spec/unit/package_builder_spec.rb +0 -593
- data/spec/unit/release_builder_spec.rb +0 -120
- data/spec/unit/release_spec.rb +0 -173
- data/spec/unit/release_tarball_spec.rb +0 -29
- data/spec/unit/runner_spec.rb +0 -7
- data/spec/unit/ssh_spec.rb +0 -84
- data/spec/unit/stemcell_spec.rb +0 -17
- data/spec/unit/task_tracker_spec.rb +0 -131
- data/spec/unit/version_calc_spec.rb +0 -27
- data/spec/unit/versions_index_spec.rb +0 -144
data/lib/cli/commands/misc.rb
CHANGED
|
@@ -15,58 +15,53 @@ module Bosh::Cli::Command
|
|
|
15
15
|
usage "status"
|
|
16
16
|
desc "Show current status (current target, user, deployment info etc)"
|
|
17
17
|
def status
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if config.target
|
|
22
|
-
say("Updating director data...", " ")
|
|
18
|
+
say("Config".make_green)
|
|
19
|
+
print_value("", config.filename)
|
|
23
20
|
|
|
21
|
+
nl
|
|
22
|
+
say("Director".make_green)
|
|
23
|
+
if target.nil?
|
|
24
|
+
say(" not set".make_yellow)
|
|
25
|
+
else
|
|
24
26
|
begin
|
|
25
27
|
timeout(config.status_timeout || DEFAULT_STATUS_TIMEOUT) do
|
|
26
|
-
director = Bosh::Cli::Director.new(
|
|
28
|
+
director = Bosh::Cli::Client::Director.new(target)
|
|
27
29
|
status = director.get_status
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
print_value("Name", status["name"])
|
|
32
|
+
print_value("URL", target_url)
|
|
33
|
+
print_value("Version", status["version"])
|
|
34
|
+
print_value("User", username, "not logged in")
|
|
35
|
+
print_value("UUID", status["uuid"])
|
|
36
|
+
print_value("CPI", status["cpi"], "n/a")
|
|
37
|
+
print_feature_list(status["features"]) if status["features"]
|
|
38
|
+
|
|
39
|
+
unless options[:target]
|
|
40
|
+
config.target_name = status["name"]
|
|
41
|
+
config.target_version = status["version"]
|
|
42
|
+
config.target_uuid = status["uuid"]
|
|
43
|
+
config.save
|
|
44
|
+
end
|
|
36
45
|
end
|
|
37
46
|
rescue TimeoutError
|
|
38
|
-
say("timed out".
|
|
47
|
+
say(" timed out fetching director status".make_red)
|
|
39
48
|
rescue => e
|
|
40
|
-
say("error: #{e.message}")
|
|
49
|
+
say(" error fetching director status: #{e.message}".make_red)
|
|
41
50
|
end
|
|
42
|
-
nl
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
say("Director".green)
|
|
46
|
-
if target_url.nil?
|
|
47
|
-
say(" not set".yellow)
|
|
48
|
-
else
|
|
49
|
-
print_value("Name", config.target_name)
|
|
50
|
-
print_value("URL", target_url)
|
|
51
|
-
print_value("Version", config.target_version)
|
|
52
|
-
print_value("User", username, "not logged in")
|
|
53
|
-
print_value("UUID", config.target_uuid)
|
|
54
|
-
print_value("CPI", cpi, "n/a (update director)")
|
|
55
|
-
print_feature_list(features) if features
|
|
56
51
|
end
|
|
57
52
|
|
|
58
53
|
nl
|
|
59
|
-
say("Deployment".
|
|
54
|
+
say("Deployment".make_green)
|
|
60
55
|
|
|
61
56
|
if deployment
|
|
62
57
|
print_value("Manifest", deployment)
|
|
63
58
|
else
|
|
64
|
-
say(" not set".
|
|
59
|
+
say(" not set".make_yellow)
|
|
65
60
|
end
|
|
66
61
|
|
|
67
62
|
if in_release_dir?
|
|
68
63
|
nl
|
|
69
|
-
say("Release".
|
|
64
|
+
say("Release".make_green)
|
|
70
65
|
|
|
71
66
|
dev_version = Bosh::Cli::VersionsIndex.new(
|
|
72
67
|
File.join(work_dir, "dev_releases")).latest_version
|
|
@@ -87,7 +82,10 @@ module Bosh::Cli::Command
|
|
|
87
82
|
|
|
88
83
|
# bosh login
|
|
89
84
|
usage "login"
|
|
90
|
-
desc "Log in to currently targeted director"
|
|
85
|
+
desc "Log in to currently targeted director. " +
|
|
86
|
+
"The username and password can also be " +
|
|
87
|
+
"set in the BOSH_USER and BOSH_PASSWORD " +
|
|
88
|
+
"environment variables."
|
|
91
89
|
def login(username = nil, password = nil)
|
|
92
90
|
target_required
|
|
93
91
|
|
|
@@ -106,16 +104,20 @@ module Bosh::Cli::Command
|
|
|
106
104
|
end
|
|
107
105
|
logged_in = false
|
|
108
106
|
|
|
107
|
+
#Converts HighLine::String to String
|
|
108
|
+
username = username.to_s
|
|
109
|
+
password = password.to_s
|
|
110
|
+
|
|
109
111
|
director.user = username
|
|
110
112
|
director.password = password
|
|
111
113
|
|
|
112
114
|
if director.authenticated?
|
|
113
|
-
say("Logged in as `#{username}'".
|
|
115
|
+
say("Logged in as `#{username}'".make_green)
|
|
114
116
|
logged_in = true
|
|
115
117
|
elsif non_interactive?
|
|
116
|
-
err("Cannot log in as `#{username}'".
|
|
118
|
+
err("Cannot log in as `#{username}'".make_red)
|
|
117
119
|
else
|
|
118
|
-
say("Cannot log in as `#{username}', please try again".
|
|
120
|
+
say("Cannot log in as `#{username}', please try again".make_red)
|
|
119
121
|
login(username)
|
|
120
122
|
end
|
|
121
123
|
|
|
@@ -132,7 +134,7 @@ module Bosh::Cli::Command
|
|
|
132
134
|
target_required
|
|
133
135
|
config.set_credentials(target, nil, nil)
|
|
134
136
|
config.save
|
|
135
|
-
say("You are no longer logged in to `#{target}'".
|
|
137
|
+
say("You are no longer logged in to `#{target}'".make_yellow)
|
|
136
138
|
end
|
|
137
139
|
|
|
138
140
|
# bosh purge
|
|
@@ -143,7 +145,7 @@ module Bosh::Cli::Command
|
|
|
143
145
|
err("Cache directory overriden, please remove manually")
|
|
144
146
|
else
|
|
145
147
|
FileUtils.rm_rf(cache.cache_dir)
|
|
146
|
-
say("Purged cache".
|
|
148
|
+
say("Purged cache".make_green)
|
|
147
149
|
end
|
|
148
150
|
end
|
|
149
151
|
|
|
@@ -168,11 +170,11 @@ module Bosh::Cli::Command
|
|
|
168
170
|
|
|
169
171
|
director_url = normalize_url(director_url)
|
|
170
172
|
if target && director_url == normalize_url(target)
|
|
171
|
-
say("Target already set to `#{target_name.
|
|
173
|
+
say("Target already set to `#{target_name.make_green}'")
|
|
172
174
|
return
|
|
173
175
|
end
|
|
174
176
|
|
|
175
|
-
director = Bosh::Cli::Director.new(director_url)
|
|
177
|
+
director = Bosh::Cli::Client::Director.new(director_url)
|
|
176
178
|
|
|
177
179
|
begin
|
|
178
180
|
status = director.get_status
|
|
@@ -197,7 +199,7 @@ module Bosh::Cli::Command
|
|
|
197
199
|
end
|
|
198
200
|
|
|
199
201
|
config.save
|
|
200
|
-
say("Target set to `#{target_name.
|
|
202
|
+
say("Target set to `#{target_name.make_green}'")
|
|
201
203
|
|
|
202
204
|
if interactive? && !logged_in?
|
|
203
205
|
redirect("login")
|
|
@@ -229,7 +231,7 @@ module Bosh::Cli::Command
|
|
|
229
231
|
def set_alias(name, command)
|
|
230
232
|
config.set_alias(:cli, name, command.to_s.strip)
|
|
231
233
|
config.save
|
|
232
|
-
say("Alias `#{name.
|
|
234
|
+
say("Alias `#{name.make_green}' created for command `#{command.make_green}'")
|
|
233
235
|
end
|
|
234
236
|
|
|
235
237
|
# bosh aliases
|
|
@@ -255,9 +257,9 @@ module Bosh::Cli::Command
|
|
|
255
257
|
|
|
256
258
|
def print_value(label, value, if_none = nil)
|
|
257
259
|
if value
|
|
258
|
-
message = label.ljust(10) + value.
|
|
260
|
+
message = label.ljust(10) + ' ' + value.make_yellow
|
|
259
261
|
else
|
|
260
|
-
message = label.ljust(10) + (if_none || "n/a").
|
|
262
|
+
message = label.ljust(10) + ' ' + (if_none || "n/a").make_yellow
|
|
261
263
|
end
|
|
262
264
|
say(message.indent(2))
|
|
263
265
|
end
|
|
@@ -270,7 +272,7 @@ module Bosh::Cli::Command
|
|
|
270
272
|
else
|
|
271
273
|
name = config.target
|
|
272
274
|
end
|
|
273
|
-
say("Current target is #{name.
|
|
275
|
+
say("Current target is #{name.make_green}")
|
|
274
276
|
else
|
|
275
277
|
say(config.target)
|
|
276
278
|
end
|
|
@@ -310,7 +312,7 @@ module Bosh::Cli::Command
|
|
|
310
312
|
t << [name, dev_version.gsub(/\-dev$/, "").rjust(8),
|
|
311
313
|
final_version.to_s.rjust(8)]
|
|
312
314
|
rescue Bosh::Cli::InvalidIndex => e
|
|
313
|
-
say("Problem with #{entity} index for `#{name}': #{e.message}".
|
|
315
|
+
say("Problem with #{entity} index for `#{name}': #{e.message}".make_red)
|
|
314
316
|
end
|
|
315
317
|
else
|
|
316
318
|
say("Spec file `#{spec_file}' is invalid")
|
|
@@ -322,22 +324,41 @@ module Bosh::Cli::Command
|
|
|
322
324
|
|
|
323
325
|
def print_feature_list(features)
|
|
324
326
|
if features.respond_to?(:each)
|
|
325
|
-
features.each do |feature,
|
|
326
|
-
|
|
327
|
+
features.each do |feature, info|
|
|
328
|
+
# Old director only returns status as a Boolean
|
|
329
|
+
if info.kind_of?(Hash)
|
|
330
|
+
status = info["status"]
|
|
331
|
+
extras = info["extras"]
|
|
332
|
+
else
|
|
333
|
+
status = info
|
|
334
|
+
extras = nil
|
|
335
|
+
end
|
|
336
|
+
print_value(feature, format_feature_status(status, extras))
|
|
327
337
|
end
|
|
328
338
|
else
|
|
329
|
-
say("Unknown feature list: #{features.inspect}".
|
|
339
|
+
say("Unknown feature list: #{features.inspect}".make_red)
|
|
330
340
|
end
|
|
331
341
|
end
|
|
332
342
|
|
|
333
|
-
def format_feature_status(status)
|
|
343
|
+
def format_feature_status(status, extras)
|
|
334
344
|
if status.nil?
|
|
335
345
|
"n/a"
|
|
336
346
|
elsif status
|
|
337
|
-
"enabled"
|
|
347
|
+
"enabled #{format_feature_extras(extras)}"
|
|
338
348
|
else
|
|
339
349
|
"disabled"
|
|
340
350
|
end
|
|
341
351
|
end
|
|
352
|
+
|
|
353
|
+
def format_feature_extras(extras)
|
|
354
|
+
return "" if extras.nil? || extras.empty?
|
|
355
|
+
|
|
356
|
+
result = []
|
|
357
|
+
extras.each do |name, value|
|
|
358
|
+
result << "#{name}: #{value}"
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
"(#{result.join(", ")})"
|
|
362
|
+
end
|
|
342
363
|
end
|
|
343
364
|
end
|
data/lib/cli/commands/package.rb
CHANGED
|
@@ -22,12 +22,12 @@ module Bosh::Cli::Command
|
|
|
22
22
|
FileUtils.mkdir_p(package_dir)
|
|
23
23
|
|
|
24
24
|
generate_file(package_dir, "packaging") do
|
|
25
|
-
"# abort script on any command that
|
|
25
|
+
"# abort script on any command that exits " +
|
|
26
26
|
"with a non zero value\nset -e\n"
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
generate_file(package_dir, "pre_packaging") do
|
|
30
|
-
"# abort script on any command that
|
|
30
|
+
"# abort script on any command that exits " +
|
|
31
31
|
"with a non zero value\nset -e\n"
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
module Bosh::Cli::Command
|
|
4
4
|
class PropertyManagement < Base
|
|
5
|
-
include Bosh::Cli::DeploymentHelper
|
|
6
|
-
|
|
7
5
|
# bosh set property
|
|
8
6
|
usage "set property"
|
|
9
7
|
desc "Set deployment property"
|
|
@@ -19,14 +17,14 @@ module Bosh::Cli::Command
|
|
|
19
17
|
end
|
|
20
18
|
|
|
21
19
|
if existing_property
|
|
22
|
-
say("Current `#{name.
|
|
23
|
-
"`#{format_property(body["value"]).
|
|
20
|
+
say("Current `#{name.make_green}' value is " +
|
|
21
|
+
"`#{format_property(body["value"]).make_green}'")
|
|
24
22
|
else
|
|
25
23
|
say("This will be a new property")
|
|
26
24
|
end
|
|
27
25
|
|
|
28
26
|
prompt = "Are you sure you want to set property" +
|
|
29
|
-
" `#{name.
|
|
27
|
+
" `#{name.make_green}' to `#{format_property(value).make_green}'?"
|
|
30
28
|
|
|
31
29
|
unless confirmed?(prompt)
|
|
32
30
|
err("Canceled")
|
|
@@ -39,7 +37,7 @@ module Bosh::Cli::Command
|
|
|
39
37
|
end
|
|
40
38
|
|
|
41
39
|
if status == 204
|
|
42
|
-
say("Property `#{name.
|
|
40
|
+
say("Property `#{name.make_green}' set to `#{value.make_green}'")
|
|
43
41
|
else
|
|
44
42
|
err(director.parse_error_message(status, body))
|
|
45
43
|
end
|
|
@@ -53,7 +51,7 @@ module Bosh::Cli::Command
|
|
|
53
51
|
show_header
|
|
54
52
|
|
|
55
53
|
prompt = "Are you sure you want to unset property " +
|
|
56
|
-
"`#{name.
|
|
54
|
+
"`#{name.make_green}'?"
|
|
57
55
|
|
|
58
56
|
unless confirmed?(prompt)
|
|
59
57
|
err("Canceled")
|
|
@@ -62,7 +60,7 @@ module Bosh::Cli::Command
|
|
|
62
60
|
status, body = director.delete_property(@deployment_name, name)
|
|
63
61
|
|
|
64
62
|
if status == 204
|
|
65
|
-
say("Property `#{name.
|
|
63
|
+
say("Property `#{name.make_green}' has been unset")
|
|
66
64
|
else
|
|
67
65
|
err(director.parse_error_message(status, body))
|
|
68
66
|
end
|
|
@@ -77,8 +75,8 @@ module Bosh::Cli::Command
|
|
|
77
75
|
|
|
78
76
|
status, body = director.get_property(@deployment_name, name)
|
|
79
77
|
if status == 200
|
|
80
|
-
say("Property `#{name.
|
|
81
|
-
"`#{format_property(body["value"]).
|
|
78
|
+
say("Property `#{name.make_green}' value is " +
|
|
79
|
+
"`#{format_property(body["value"]).make_green}'")
|
|
82
80
|
else
|
|
83
81
|
err(director.parse_error_message(status, body))
|
|
84
82
|
end
|
|
@@ -128,8 +126,8 @@ module Bosh::Cli::Command
|
|
|
128
126
|
end
|
|
129
127
|
|
|
130
128
|
def show_header
|
|
131
|
-
say("Target #{target_name.
|
|
132
|
-
say("Deployment #{@deployment_name.
|
|
129
|
+
say("Target #{target_name.make_green}")
|
|
130
|
+
say("Deployment #{@deployment_name.make_green}")
|
|
133
131
|
nl
|
|
134
132
|
end
|
|
135
133
|
|
data/lib/cli/commands/release.rb
CHANGED
|
@@ -26,16 +26,15 @@ module Bosh::Cli::Command
|
|
|
26
26
|
|
|
27
27
|
# Initialize an empty blobs index
|
|
28
28
|
File.open(File.join("config", "blobs.yml"), "w") do |f|
|
|
29
|
-
|
|
29
|
+
Psych.dump({}, f)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
say("Release directory initialized".
|
|
32
|
+
say("Release directory initialized".make_green)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
# bosh create release
|
|
36
36
|
usage "create release"
|
|
37
|
-
desc "Create release (assumes current directory "
|
|
38
|
-
"to be a release repository)"
|
|
37
|
+
desc "Create release (assumes current directory to be a release repository)"
|
|
39
38
|
option "--force", "bypass git dirty state check"
|
|
40
39
|
option "--final", "create final release"
|
|
41
40
|
option "--with-tarball", "create release tarball"
|
|
@@ -67,54 +66,57 @@ module Bosh::Cli::Command
|
|
|
67
66
|
nl
|
|
68
67
|
|
|
69
68
|
if tarball.valid?
|
|
70
|
-
say("`#{tarball_path}' is a valid release".
|
|
69
|
+
say("`#{tarball_path}' is a valid release".make_green)
|
|
71
70
|
else
|
|
72
|
-
say("Validation errors:".
|
|
71
|
+
say("Validation errors:".make_red)
|
|
73
72
|
tarball.errors.each do |error|
|
|
74
73
|
say("- #{error}")
|
|
75
74
|
end
|
|
76
|
-
err("`#{tarball_path}' is not a valid release".
|
|
75
|
+
err("`#{tarball_path}' is not a valid release".make_red)
|
|
77
76
|
end
|
|
78
77
|
end
|
|
79
78
|
|
|
80
79
|
usage "upload release"
|
|
81
|
-
desc "Upload release"
|
|
80
|
+
desc "Upload release (release_file can be a local file or a remote URI)"
|
|
82
81
|
option "--rebase",
|
|
83
82
|
"Rebases this release onto the latest version",
|
|
84
83
|
"known by director (discards local job/package",
|
|
85
84
|
"versions in favor of versions assigned by director)"
|
|
85
|
+
option "--skip-if-exists", "skips upload if release already exists"
|
|
86
86
|
def upload(release_file = nil)
|
|
87
87
|
auth_required
|
|
88
88
|
|
|
89
89
|
upload_options = {
|
|
90
90
|
:rebase => options[:rebase],
|
|
91
|
-
:repack => true
|
|
91
|
+
:repack => true,
|
|
92
|
+
:skip_if_exists => options[:skip_if_exists],
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
if release_file.nil?
|
|
95
96
|
check_if_release_dir
|
|
96
97
|
release_file = release.latest_release_filename
|
|
97
98
|
if release_file.nil?
|
|
98
|
-
err("The information about latest generated release is missing, "
|
|
99
|
-
"please provide release filename")
|
|
99
|
+
err("The information about latest generated release is missing, please provide release filename")
|
|
100
100
|
end
|
|
101
|
-
unless confirmed?("Upload release "
|
|
102
|
-
"`#{File.basename(release_file).green}' " +
|
|
103
|
-
"to `#{target_name.green}'")
|
|
101
|
+
unless confirmed?("Upload release `#{File.basename(release_file).make_green}' to `#{target_name.make_green}'")
|
|
104
102
|
err("Canceled upload")
|
|
105
103
|
end
|
|
106
104
|
end
|
|
107
105
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
106
|
+
if release_file =~ /^#{URI::regexp}$/
|
|
107
|
+
upload_remote_release(release_file, upload_options)
|
|
108
|
+
else
|
|
109
|
+
unless File.exist?(release_file)
|
|
110
|
+
err("Release file doesn't exist")
|
|
111
|
+
end
|
|
111
112
|
|
|
112
|
-
|
|
113
|
+
file_type = `file --mime-type -b '#{release_file}'`
|
|
113
114
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
if file_type =~ /text\/(plain|yaml)/
|
|
116
|
+
upload_manifest(release_file, upload_options)
|
|
117
|
+
else
|
|
118
|
+
upload_tarball(release_file, upload_options)
|
|
119
|
+
end
|
|
118
120
|
end
|
|
119
121
|
end
|
|
120
122
|
|
|
@@ -123,7 +125,7 @@ module Bosh::Cli::Command
|
|
|
123
125
|
def reset
|
|
124
126
|
check_if_release_dir
|
|
125
127
|
|
|
126
|
-
say("Your dev release environment will be completely reset".
|
|
128
|
+
say("Your dev release environment will be completely reset".make_red)
|
|
127
129
|
if confirmed?
|
|
128
130
|
say("Removing dev_builds index...")
|
|
129
131
|
FileUtils.rm_rf(".dev_builds")
|
|
@@ -133,7 +135,7 @@ module Bosh::Cli::Command
|
|
|
133
135
|
say("Removing dev tarballs...")
|
|
134
136
|
FileUtils.rm_rf("dev_releases")
|
|
135
137
|
|
|
136
|
-
say("Release has been reset".
|
|
138
|
+
say("Release has been reset".make_green)
|
|
137
139
|
else
|
|
138
140
|
say("Canceled")
|
|
139
141
|
end
|
|
@@ -141,6 +143,7 @@ module Bosh::Cli::Command
|
|
|
141
143
|
|
|
142
144
|
usage "releases"
|
|
143
145
|
desc "Show the list of available releases"
|
|
146
|
+
option "--jobs", "include job templates"
|
|
144
147
|
def list
|
|
145
148
|
auth_required
|
|
146
149
|
releases = director.list_releases.sort do |r1, r2|
|
|
@@ -149,20 +152,16 @@ module Bosh::Cli::Command
|
|
|
149
152
|
|
|
150
153
|
err("No releases") if releases.empty?
|
|
151
154
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
version_cmp(v1, v2)
|
|
157
|
-
}.map { |v| ((r["in_use"] || []).include?(v)) ? "#{v}*" : v }
|
|
158
|
-
|
|
159
|
-
t << [r["name"], versions.join(", ")]
|
|
160
|
-
end
|
|
155
|
+
if releases.first.has_key? "release_versions"
|
|
156
|
+
releases_table = build_releases_table(releases, options)
|
|
157
|
+
elsif releases.first.has_key? "versions"
|
|
158
|
+
releases_table = build_releases_table_for_old_director(releases)
|
|
161
159
|
end
|
|
162
160
|
|
|
163
161
|
nl
|
|
164
|
-
say(releases_table)
|
|
162
|
+
say(releases_table.render)
|
|
165
163
|
say("(*) Currently deployed") if releases_table.to_s =~ /\*/
|
|
164
|
+
say("(+) Uncommitted changes") if releases_table.to_s =~ /^\|.*\+{1}.*\|$/
|
|
166
165
|
nl
|
|
167
166
|
say("Releases total: %d" % releases.size)
|
|
168
167
|
end
|
|
@@ -178,20 +177,20 @@ module Bosh::Cli::Command
|
|
|
178
177
|
desc << "/#{version}" if version
|
|
179
178
|
|
|
180
179
|
if force
|
|
181
|
-
say("Deleting `#{desc}' (FORCED DELETE, WILL IGNORE ERRORS)".
|
|
180
|
+
say("Deleting `#{desc}' (FORCED DELETE, WILL IGNORE ERRORS)".make_red)
|
|
182
181
|
else
|
|
183
|
-
say("Deleting `#{desc}'".
|
|
182
|
+
say("Deleting `#{desc}'".make_red)
|
|
184
183
|
end
|
|
185
184
|
|
|
186
185
|
if confirmed?
|
|
187
|
-
status, task_id = director.delete_release(
|
|
188
|
-
name, :force => force, :version => version)
|
|
186
|
+
status, task_id = director.delete_release(name, force: force, version: version)
|
|
189
187
|
task_report(status, task_id, "Deleted `#{desc}'")
|
|
190
188
|
else
|
|
191
|
-
say("Canceled deleting release".
|
|
189
|
+
say("Canceled deleting release".make_green)
|
|
192
190
|
end
|
|
193
191
|
end
|
|
194
192
|
|
|
193
|
+
|
|
195
194
|
protected
|
|
196
195
|
|
|
197
196
|
def upload_manifest(manifest_path, upload_options = {})
|
|
@@ -202,8 +201,7 @@ module Bosh::Cli::Command
|
|
|
202
201
|
blobstore = release.blobstore
|
|
203
202
|
tmpdir = Dir.mktmpdir
|
|
204
203
|
|
|
205
|
-
compiler = Bosh::Cli::ReleaseCompiler.new(
|
|
206
|
-
manifest_path, blobstore, package_matches)
|
|
204
|
+
compiler = Bosh::Cli::ReleaseCompiler.new(manifest_path, blobstore, package_matches)
|
|
207
205
|
need_repack = true
|
|
208
206
|
|
|
209
207
|
unless compiler.exists?
|
|
@@ -230,24 +228,29 @@ module Bosh::Cli::Command
|
|
|
230
228
|
err("Release is invalid, please fix, verify and upload again")
|
|
231
229
|
end
|
|
232
230
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
231
|
+
remote_release = get_remote_release(tarball.release_name) rescue nil
|
|
232
|
+
if remote_release && !rebase
|
|
233
|
+
if remote_release["versions"].include?(tarball.version)
|
|
234
|
+
if upload_options[:skip_if_exists]
|
|
235
|
+
say("Release `#{tarball.release_name}/#{tarball.version}' already exists. Skipping upload.")
|
|
236
|
+
return
|
|
237
|
+
else
|
|
238
|
+
err("This release version has already been uploaded")
|
|
239
|
+
end
|
|
239
240
|
end
|
|
241
|
+
end
|
|
240
242
|
|
|
243
|
+
begin
|
|
241
244
|
if repack
|
|
242
245
|
package_matches = match_remote_packages(tarball.manifest)
|
|
243
246
|
|
|
244
247
|
say("Checking if can repack release for faster upload...")
|
|
245
248
|
repacked_path = tarball.repack(package_matches)
|
|
249
|
+
|
|
246
250
|
if repacked_path.nil?
|
|
247
|
-
say("Uploading the whole release".
|
|
251
|
+
say("Uploading the whole release".make_green)
|
|
248
252
|
else
|
|
249
|
-
say("Release repacked "
|
|
250
|
-
"(new size is #{pretty_size(repacked_path)})".green)
|
|
253
|
+
say("Release repacked (new size is #{pretty_size(repacked_path)})".make_green)
|
|
251
254
|
tarball_path = repacked_path
|
|
252
255
|
end
|
|
253
256
|
end
|
|
@@ -257,7 +260,7 @@ module Bosh::Cli::Command
|
|
|
257
260
|
end
|
|
258
261
|
|
|
259
262
|
if rebase
|
|
260
|
-
say("Uploading release (#{"will be rebased".
|
|
263
|
+
say("Uploading release (#{"will be rebased".make_yellow})")
|
|
261
264
|
status, task_id = director.rebase_release(tarball_path)
|
|
262
265
|
task_report(status, task_id, "Release rebased")
|
|
263
266
|
else
|
|
@@ -267,6 +270,19 @@ module Bosh::Cli::Command
|
|
|
267
270
|
end
|
|
268
271
|
end
|
|
269
272
|
|
|
273
|
+
def upload_remote_release(release_location, upload_options = {})
|
|
274
|
+
nl
|
|
275
|
+
if upload_options[:rebase]
|
|
276
|
+
say("Using remote release `#{release_location}' (#{"will be rebased".make_yellow})")
|
|
277
|
+
status, task_id = director.rebase_remote_release(release_location)
|
|
278
|
+
task_report(status, task_id, "Release rebased")
|
|
279
|
+
else
|
|
280
|
+
say("Using remote release `#{release_location}'")
|
|
281
|
+
status, task_id = director.upload_remote_release(release_location)
|
|
282
|
+
task_report(status, task_id, "Release uploaded")
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
270
286
|
def create_from_manifest(manifest_file)
|
|
271
287
|
say("Recreating release from the manifest")
|
|
272
288
|
Bosh::Cli::ReleaseCompiler.compile(manifest_file, release.blobstore)
|
|
@@ -279,67 +295,84 @@ module Bosh::Cli::Command
|
|
|
279
295
|
manifest_only = !options[:with_tarball]
|
|
280
296
|
dry_run = options[:dry_run]
|
|
281
297
|
|
|
282
|
-
if final && !release.has_blobstore_secret?
|
|
283
|
-
|
|
298
|
+
err("Can't create final release without blobstore secret") if final && !release.has_blobstore_secret?
|
|
299
|
+
|
|
300
|
+
dirty_blob_check(force)
|
|
301
|
+
|
|
302
|
+
raise_dirty_state_error if dirty_state? && !force
|
|
303
|
+
|
|
304
|
+
if final
|
|
305
|
+
confirm_final_release(dry_run)
|
|
306
|
+
save_final_release_name if release.final_name.blank?
|
|
307
|
+
header("Building FINAL release".make_green)
|
|
308
|
+
else
|
|
309
|
+
save_dev_release_name if release.dev_name.blank?
|
|
310
|
+
header("Building DEV release".make_green)
|
|
284
311
|
end
|
|
285
312
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
blob_manager.print_status
|
|
289
|
-
if force
|
|
290
|
-
say("Proceeding with dirty blobs as '--force' is given".red)
|
|
291
|
-
else
|
|
292
|
-
err("Please use '--force' or upload new blobs")
|
|
293
|
-
end
|
|
313
|
+
if version_greater(release.min_cli_version, Bosh::Cli::VERSION)
|
|
314
|
+
err("You should use CLI >= #{release.min_cli_version} with this release, you have #{Bosh::Cli::VERSION}")
|
|
294
315
|
end
|
|
295
316
|
|
|
296
|
-
|
|
317
|
+
header("Building packages")
|
|
318
|
+
packages = build_packages(dry_run, final)
|
|
297
319
|
|
|
298
|
-
|
|
299
|
-
|
|
320
|
+
header("Building jobs")
|
|
321
|
+
jobs = build_jobs(packages.map(&:name), dry_run, final)
|
|
300
322
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
exit(1)
|
|
304
|
-
end
|
|
323
|
+
header("Building release")
|
|
324
|
+
release_builder = build_release(dry_run, final, jobs, manifest_only, packages)
|
|
305
325
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
326
|
+
header("Release summary")
|
|
327
|
+
show_summary(release_builder)
|
|
328
|
+
nl
|
|
329
|
+
|
|
330
|
+
return nil if dry_run
|
|
331
|
+
|
|
332
|
+
say("Release version: #{release_builder.version.to_s.make_green}")
|
|
333
|
+
say("Release manifest: #{release_builder.manifest_path.make_green}")
|
|
334
|
+
|
|
335
|
+
unless manifest_only
|
|
336
|
+
say("Release tarball (#{pretty_size(release_builder.tarball_path)}): " +
|
|
337
|
+
release_builder.tarball_path.make_green)
|
|
312
338
|
end
|
|
313
339
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
340
|
+
release.min_cli_version = Bosh::Cli::VERSION
|
|
341
|
+
release.save_config
|
|
342
|
+
|
|
343
|
+
release_builder.manifest_path
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
def confirm_final_release(dry_run)
|
|
347
|
+
confirmed = non_interactive? || agree("Are you sure you want to generate #{'final'.make_red} version? ")
|
|
348
|
+
if !dry_run && !confirmed
|
|
349
|
+
say("Canceled release generation".make_green)
|
|
350
|
+
exit(1)
|
|
317
351
|
end
|
|
352
|
+
end
|
|
318
353
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
release.final_name = name
|
|
354
|
+
def dirty_blob_check(force)
|
|
355
|
+
blob_manager.sync
|
|
356
|
+
if blob_manager.dirty?
|
|
357
|
+
blob_manager.print_status
|
|
358
|
+
if force
|
|
359
|
+
say("Proceeding with dirty blobs as '--force' is given".make_red)
|
|
326
360
|
else
|
|
327
|
-
|
|
361
|
+
err("Please use '--force' or upload new blobs")
|
|
328
362
|
end
|
|
329
|
-
release.save_config
|
|
330
363
|
end
|
|
364
|
+
end
|
|
331
365
|
|
|
332
|
-
|
|
333
|
-
|
|
366
|
+
def build_packages(dry_run, final)
|
|
334
367
|
packages = Bosh::Cli::PackageBuilder.discover(
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
368
|
+
work_dir,
|
|
369
|
+
:final => final,
|
|
370
|
+
:blobstore => release.blobstore,
|
|
371
|
+
:dry_run => dry_run
|
|
339
372
|
)
|
|
340
373
|
|
|
341
374
|
packages.each do |package|
|
|
342
|
-
say("Building #{package.name.
|
|
375
|
+
say("Building #{package.name.make_green}...")
|
|
343
376
|
package.build
|
|
344
377
|
nl
|
|
345
378
|
end
|
|
@@ -358,52 +391,58 @@ module Bosh::Cli::Command
|
|
|
358
391
|
nl
|
|
359
392
|
end
|
|
360
393
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
header("Building jobs")
|
|
364
|
-
jobs = Bosh::Cli::JobBuilder.discover(
|
|
365
|
-
work_dir,
|
|
366
|
-
:final => final,
|
|
367
|
-
:blobstore => release.blobstore,
|
|
368
|
-
:dry_run => dry_run,
|
|
369
|
-
:package_names => built_package_names
|
|
370
|
-
)
|
|
371
|
-
|
|
372
|
-
jobs.each do |job|
|
|
373
|
-
say("Building #{job.name.green}...")
|
|
374
|
-
job.build
|
|
375
|
-
nl
|
|
376
|
-
end
|
|
394
|
+
packages
|
|
395
|
+
end
|
|
377
396
|
|
|
378
|
-
|
|
379
|
-
|
|
397
|
+
def build_release(dry_run, final, jobs, manifest_only, packages)
|
|
398
|
+
release_builder = Bosh::Cli::ReleaseBuilder.new(release, packages, jobs, final: final,
|
|
399
|
+
commit_hash: commit_hash, uncommitted_changes: dirty_state?)
|
|
380
400
|
|
|
381
401
|
unless dry_run
|
|
382
402
|
if manifest_only
|
|
383
|
-
|
|
403
|
+
release_builder.build(:generate_tarball => false)
|
|
384
404
|
else
|
|
385
|
-
|
|
405
|
+
release_builder.build(:generate_tarball => true)
|
|
386
406
|
end
|
|
387
407
|
end
|
|
388
408
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
nl
|
|
392
|
-
|
|
393
|
-
return nil if dry_run
|
|
409
|
+
release_builder
|
|
410
|
+
end
|
|
394
411
|
|
|
395
|
-
|
|
396
|
-
|
|
412
|
+
def build_jobs(built_package_names, dry_run, final)
|
|
413
|
+
jobs = Bosh::Cli::JobBuilder.discover(
|
|
414
|
+
work_dir,
|
|
415
|
+
:final => final,
|
|
416
|
+
:blobstore => release.blobstore,
|
|
417
|
+
:dry_run => dry_run,
|
|
418
|
+
:package_names => built_package_names
|
|
419
|
+
)
|
|
397
420
|
|
|
398
|
-
|
|
399
|
-
say("
|
|
400
|
-
|
|
421
|
+
jobs.each do |job|
|
|
422
|
+
say("Building #{job.name.make_green}...")
|
|
423
|
+
job.build
|
|
424
|
+
nl
|
|
401
425
|
end
|
|
402
426
|
|
|
403
|
-
|
|
427
|
+
jobs
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
def save_final_release_name
|
|
431
|
+
release.final_name = DEFAULT_RELEASE_NAME
|
|
432
|
+
if interactive?
|
|
433
|
+
release.final_name = ask("Please enter final release name: ").to_s
|
|
434
|
+
err("Canceled release creation, no name given") if release.final_name.blank?
|
|
435
|
+
end
|
|
404
436
|
release.save_config
|
|
437
|
+
end
|
|
405
438
|
|
|
406
|
-
|
|
439
|
+
def save_dev_release_name
|
|
440
|
+
release.dev_name = DEFAULT_RELEASE_NAME
|
|
441
|
+
if interactive?
|
|
442
|
+
release.dev_name = ask("Please enter development release name: ").to_s
|
|
443
|
+
err("Canceled release creation, no name given") if release.dev_name.blank?
|
|
444
|
+
end
|
|
445
|
+
release.save_config
|
|
407
446
|
end
|
|
408
447
|
|
|
409
448
|
def git_init
|
|
@@ -432,9 +471,10 @@ module Bosh::Cli::Command
|
|
|
432
471
|
end
|
|
433
472
|
end
|
|
434
473
|
rescue Errno::ENOENT
|
|
435
|
-
say("Unable to run 'git init'".
|
|
474
|
+
say("Unable to run 'git init'".make_red)
|
|
436
475
|
end
|
|
437
476
|
|
|
477
|
+
|
|
438
478
|
private
|
|
439
479
|
|
|
440
480
|
# if we aren't already in a release directory, try going up two levels
|
|
@@ -503,8 +543,7 @@ module Bosh::Cli::Command
|
|
|
503
543
|
release.has_key?("jobs") &&
|
|
504
544
|
release.has_key?("packages")
|
|
505
545
|
raise Bosh::Cli::DirectorError,
|
|
506
|
-
"Cannot find version, jobs and packages info "
|
|
507
|
-
"in the director response, maybe old director?"
|
|
546
|
+
"Cannot find version, jobs and packages info in the director response, maybe old director?"
|
|
508
547
|
end
|
|
509
548
|
|
|
510
549
|
release
|
|
@@ -514,12 +553,76 @@ module Bosh::Cli::Command
|
|
|
514
553
|
director.match_packages(manifest_yaml)
|
|
515
554
|
rescue Bosh::Cli::DirectorError
|
|
516
555
|
msg = "You are using CLI >= 0.20 with director that doesn't support " +
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
556
|
+
"package matches.\nThis will result in uploading all packages " +
|
|
557
|
+
"and jobs to your director.\nIt is recommended to update your " +
|
|
558
|
+
"director or downgrade your CLI to 0.19.6"
|
|
520
559
|
|
|
521
|
-
say(msg.
|
|
560
|
+
say(msg.make_yellow)
|
|
522
561
|
exit(1) unless confirmed?
|
|
523
562
|
end
|
|
563
|
+
|
|
564
|
+
def build_releases_table_for_old_director(releases)
|
|
565
|
+
table do |t|
|
|
566
|
+
t.headings = "Name", "Versions"
|
|
567
|
+
releases.each do |release|
|
|
568
|
+
versions = release["versions"].sort { |v1, v2|
|
|
569
|
+
version_cmp(v1, v2)
|
|
570
|
+
}.map { |v| ((release["in_use"] || []).include?(v)) ? "#{v}*" : v }
|
|
571
|
+
|
|
572
|
+
t << [release["name"], versions.join(", ")]
|
|
573
|
+
end
|
|
574
|
+
end
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
# Builds table of release information
|
|
578
|
+
# Default headings: "Name", "Versions", "Commit Hash"
|
|
579
|
+
# Extra headings: options[:job] => "Jobs"
|
|
580
|
+
def build_releases_table(releases, options = {})
|
|
581
|
+
show_jobs = options[:jobs]
|
|
582
|
+
table do |t|
|
|
583
|
+
t.headings = "Name", "Versions", "Commit Hash"
|
|
584
|
+
t.headings << "Jobs" if show_jobs
|
|
585
|
+
releases.each do |release|
|
|
586
|
+
versions, commit_hashes = formatted_versions(release).transpose
|
|
587
|
+
row = [release["name"], versions.join("\n"), commit_hashes.join("\n")]
|
|
588
|
+
if show_jobs
|
|
589
|
+
jobs = formatted_jobs(release).transpose
|
|
590
|
+
row << jobs.join("\n")
|
|
591
|
+
end
|
|
592
|
+
t << row
|
|
593
|
+
end
|
|
594
|
+
end
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
def formatted_versions(release)
|
|
598
|
+
sort_versions(release["release_versions"]).map { |v| formatted_version_and_commit_hash(v) }
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
def sort_versions(versions)
|
|
602
|
+
versions.sort { |v1, v2| version_cmp(v1["version"], v2["version"]) }
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
def formatted_version_and_commit_hash(version)
|
|
606
|
+
version_number = version["version"] + (version["currently_deployed"] ? "*" : "")
|
|
607
|
+
commit_hash = version["commit_hash"] + (version["uncommitted_changes"] ? "+" : "")
|
|
608
|
+
[version_number, commit_hash]
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
def formatted_jobs(release)
|
|
612
|
+
sort_versions(release["release_versions"]).map do |v|
|
|
613
|
+
if job_names = v["job_names"]
|
|
614
|
+
[job_names.join(", ")]
|
|
615
|
+
else
|
|
616
|
+
["n/a "] # with enough whitespace to match "Jobs" header
|
|
617
|
+
end
|
|
618
|
+
end
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
def commit_hash
|
|
622
|
+
status = Bosh::Exec.sh('git show-ref --head --hash=8 2> /dev/null')
|
|
623
|
+
status.output.split.first
|
|
624
|
+
rescue Bosh::Exec::Error => e
|
|
625
|
+
'00000000'
|
|
626
|
+
end
|
|
524
627
|
end
|
|
525
|
-
end
|
|
628
|
+
end
|