bosh_cli 1.0.3 → 1.5.0.pre.1113
Sign up to get free protection for your applications and to get access to all the features.
- 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
|