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
@@ -9,9 +9,7 @@ module Bosh::Cli::Command
|
|
9
9
|
|
10
10
|
# The URL of the public stemcell index.
|
11
11
|
PUBLIC_STEMCELL_INDEX_URL =
|
12
|
-
"https://blob.cfblob.com/
|
13
|
-
"1e121204e4e86ee151bc04f6a19ce46b22?uid=bb6a0c89ef4048a8a0f814e2538" +
|
14
|
-
"5d1c5/user1&expires=1893484800&signature=NJuAr9c8eOid7dKFmOEN7bmzAlI="
|
12
|
+
"https://s3.amazonaws.com/blob.cfblob.com/stemcells/public_stemcells_index.yml"
|
15
13
|
|
16
14
|
DEFAULT_PUB_STEMCELL_TAG = "stable"
|
17
15
|
ALL_STEMCELLS_TAG = "all"
|
@@ -27,9 +25,9 @@ module Bosh::Cli::Command
|
|
27
25
|
nl
|
28
26
|
|
29
27
|
if stemcell.valid?
|
30
|
-
say("`#{tarball_path}' is a valid stemcell".
|
28
|
+
say("`#{tarball_path}' is a valid stemcell".make_green)
|
31
29
|
else
|
32
|
-
say("Validation errors:".
|
30
|
+
say("Validation errors:".make_red)
|
33
31
|
stemcell.errors.each do |error|
|
34
32
|
say("- %s" % [error])
|
35
33
|
end
|
@@ -39,38 +37,50 @@ module Bosh::Cli::Command
|
|
39
37
|
|
40
38
|
# bosh upload stemcell
|
41
39
|
usage "upload stemcell"
|
42
|
-
desc "Upload stemcell"
|
43
|
-
def upload(
|
40
|
+
desc "Upload stemcell (stemcell_location can be a local file or a remote URI)"
|
41
|
+
def upload(stemcell_location)
|
44
42
|
auth_required
|
45
43
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
44
|
+
stemcell_type = stemcell_location =~ /^#{URI::regexp}$/ ? "remote" : "local"
|
45
|
+
if stemcell_type == "local"
|
46
|
+
stemcell = Bosh::Cli::Stemcell.new(stemcell_location, cache)
|
47
|
+
|
48
|
+
nl
|
49
|
+
say("Verifying stemcell...")
|
50
|
+
stemcell.validate
|
51
|
+
nl
|
52
|
+
|
53
|
+
unless stemcell.valid?
|
54
|
+
err("Stemcell is invalid, please fix, verify and upload again")
|
55
|
+
end
|
56
|
+
|
57
|
+
say("Checking if stemcell already exists...")
|
58
|
+
name = stemcell.manifest["name"]
|
59
|
+
version = stemcell.manifest["version"]
|
60
|
+
|
61
|
+
if exists?(name, version)
|
62
|
+
err("Stemcell `#{name}/#{version}' already exists, " +
|
63
|
+
"increment the version if it has changed")
|
64
|
+
else
|
65
|
+
say("No")
|
66
|
+
end
|
67
|
+
|
68
|
+
stemcell_location = stemcell.stemcell_file
|
52
69
|
|
53
|
-
|
54
|
-
|
70
|
+
nl
|
71
|
+
say("Uploading stemcell...")
|
72
|
+
nl
|
73
|
+
else
|
74
|
+
nl
|
75
|
+
say("Using remote stemcell `#{stemcell_location}'")
|
55
76
|
end
|
56
77
|
|
57
|
-
|
58
|
-
|
59
|
-
version = stemcell.manifest["version"]
|
60
|
-
|
61
|
-
if exists?(name, version)
|
62
|
-
err("Stemcell `#{name}/#{version}' already exists, " +
|
63
|
-
"increment the version if it has changed")
|
78
|
+
if stemcell_type == "local"
|
79
|
+
status, task_id = director.upload_stemcell(stemcell_location)
|
64
80
|
else
|
65
|
-
|
81
|
+
status, task_id = director.upload_remote_stemcell(stemcell_location)
|
66
82
|
end
|
67
83
|
|
68
|
-
nl
|
69
|
-
say("Uploading stemcell...")
|
70
|
-
nl
|
71
|
-
|
72
|
-
status, task_id = director.upload_stemcell(stemcell.stemcell_file)
|
73
|
-
|
74
84
|
task_report(status, task_id, "Stemcell uploaded and created")
|
75
85
|
end
|
76
86
|
|
@@ -170,15 +180,17 @@ module Bosh::Cli::Command
|
|
170
180
|
err("The downloaded file sha1 `#{file_sha1}' does not match the " +
|
171
181
|
"expected sha1 `#{sha1}'")
|
172
182
|
else
|
173
|
-
say("Download complete".
|
183
|
+
say("Download complete".make_green)
|
174
184
|
end
|
175
185
|
end
|
176
186
|
|
177
187
|
# bosh delete stemcell
|
178
188
|
usage "delete stemcell"
|
179
189
|
desc "Delete stemcell"
|
190
|
+
option "--force", "ignore errors while deleting the stemcell"
|
180
191
|
def delete(name, version)
|
181
192
|
auth_required
|
193
|
+
force = !!options[:force]
|
182
194
|
|
183
195
|
say("Checking if stemcell exists...")
|
184
196
|
|
@@ -186,14 +198,14 @@ module Bosh::Cli::Command
|
|
186
198
|
err("Stemcell `#{name}/#{version}' does not exist")
|
187
199
|
end
|
188
200
|
|
189
|
-
say("You are going to delete stemcell `#{name}/#{version}'".
|
201
|
+
say("You are going to delete stemcell `#{name}/#{version}'".make_red)
|
190
202
|
|
191
203
|
unless confirmed?
|
192
|
-
say("Canceled deleting stemcell".
|
204
|
+
say("Canceled deleting stemcell".make_green)
|
193
205
|
return
|
194
206
|
end
|
195
207
|
|
196
|
-
status, task_id = director.delete_stemcell(name, version)
|
208
|
+
status, task_id = director.delete_stemcell(name, version, :force => force)
|
197
209
|
|
198
210
|
task_report(status, task_id, "Deleted stemcell `#{name}/#{version}'")
|
199
211
|
end
|
@@ -232,7 +244,7 @@ module Bosh::Cli::Command
|
|
232
244
|
if status_code != HTTP::Status::OK
|
233
245
|
err("Received HTTP #{status_code} from #{PUBLIC_STEMCELL_INDEX_URL}.")
|
234
246
|
end
|
235
|
-
|
247
|
+
Psych.load(response.body)
|
236
248
|
end
|
237
249
|
|
238
250
|
end
|
data/lib/cli/commands/task.rb
CHANGED
@@ -118,9 +118,9 @@ module Bosh::Cli::Command
|
|
118
118
|
def show_tasks_table(tasks)
|
119
119
|
return if tasks.empty?
|
120
120
|
tasks_table = table do |t|
|
121
|
-
t.headings = "#", "State", "Timestamp", "Description", "Result"
|
121
|
+
t.headings = "#", "State", "Timestamp", "User", "Description", "Result"
|
122
122
|
tasks.map do |task|
|
123
|
-
t << [task["id"], task["state"], Time.at(task["timestamp"]).utc,
|
123
|
+
t << [task["id"], task["state"], Time.at(task["timestamp"]).utc, task["user"],
|
124
124
|
task["description"].to_s, task["result"].to_s.truncate(80)]
|
125
125
|
end
|
126
126
|
end
|
data/lib/cli/commands/user.rb
CHANGED
@@ -10,9 +10,12 @@ module Bosh::Cli::Command
|
|
10
10
|
auth_required
|
11
11
|
|
12
12
|
if interactive?
|
13
|
-
username = ask("Enter username: ") if username.blank?
|
13
|
+
username = ask("Enter new username: ") if username.blank?
|
14
14
|
if password.blank?
|
15
|
-
password = ask("Enter password: ") { |q| q.echo = "*" }
|
15
|
+
password = ask("Enter new password: ") { |q| q.echo = "*" }
|
16
|
+
password_confirmation = ask("Verify new password: ") { |q| q.echo = "*" }
|
17
|
+
|
18
|
+
err("Passwords do not match") if password != password_confirmation
|
16
19
|
end
|
17
20
|
end
|
18
21
|
|
@@ -21,11 +24,32 @@ module Bosh::Cli::Command
|
|
21
24
|
end
|
22
25
|
|
23
26
|
if director.create_user(username, password)
|
24
|
-
say("User `#{username}' has been created".
|
27
|
+
say("User `#{username}' has been created".make_green)
|
25
28
|
else
|
26
29
|
err("Error creating user")
|
27
30
|
end
|
28
31
|
end
|
29
32
|
|
33
|
+
usage "delete user"
|
34
|
+
desc "Deletes the user from the director"
|
35
|
+
def delete(username = nil)
|
36
|
+
auth_required
|
37
|
+
|
38
|
+
if interactive?
|
39
|
+
username ||= ask("Username to delete: ")
|
40
|
+
end
|
41
|
+
|
42
|
+
if username.blank?
|
43
|
+
err("Please provide a username to delete")
|
44
|
+
end
|
45
|
+
|
46
|
+
if confirmed?("Are you sure you would like to delete the user `#{username}'?")
|
47
|
+
if director.delete_user(username)
|
48
|
+
say("User `#{username}' has been deleted".make_green)
|
49
|
+
else
|
50
|
+
err("Unable to delete user")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
30
54
|
end
|
31
55
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'cli/job_command_args'
|
2
|
+
require 'cli/resurrection'
|
3
|
+
|
4
|
+
module Bosh::Cli
|
5
|
+
module Command
|
6
|
+
class Vm < Base
|
7
|
+
usage 'vm resurrection'
|
8
|
+
desc 'Enable/Disable resurrection for a given vm'
|
9
|
+
def resurrection_state(job=nil, index=nil, new_state)
|
10
|
+
if job.nil? && index.nil?
|
11
|
+
resurrection = Resurrection.new(new_state)
|
12
|
+
|
13
|
+
director.change_vm_resurrection_for_all(resurrection.paused?)
|
14
|
+
else
|
15
|
+
job_args = JobCommandArgs.new([job, index])
|
16
|
+
job, index, _ = job_args.to_a
|
17
|
+
resurrection = Resurrection.new(new_state)
|
18
|
+
|
19
|
+
job_must_exist_in_deployment(job)
|
20
|
+
index = valid_index_for(job, index, integer_index: true)
|
21
|
+
|
22
|
+
manifest = prepare_deployment_manifest
|
23
|
+
director.change_vm_resurrection(manifest['name'], job, index, resurrection.paused?)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/cli/commands/vms.rb
CHANGED
@@ -2,45 +2,103 @@
|
|
2
2
|
|
3
3
|
module Bosh::Cli::Command
|
4
4
|
class Vms < Base
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
option
|
5
|
+
usage 'vms'
|
6
|
+
desc 'List all VMs in a deployment'
|
7
|
+
option '--details', 'Return detailed VM information'
|
8
|
+
option '--dns', 'Return VM DNS A records'
|
9
|
+
option '--vitals', 'Return VM vitals information'
|
10
10
|
def list(deployment_name = nil)
|
11
11
|
auth_required
|
12
12
|
no_track_unsupported
|
13
|
-
show_full_stats = options[:full]
|
14
13
|
|
15
14
|
if deployment_name.nil?
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
deps = director.list_deployments
|
16
|
+
err('No deployments') if deps.empty?
|
17
|
+
deps.each { |dep| show_deployment(dep['name'], options) }
|
18
|
+
else
|
19
|
+
show_deployment deployment_name, options
|
19
20
|
end
|
21
|
+
end
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
23
|
+
def show_deployment(name, options={})
|
24
|
+
say("Deployment `#{name.make_green}'")
|
25
|
+
|
26
|
+
vms = director.fetch_vm_state(name)
|
27
|
+
|
28
|
+
if vms.empty?
|
29
|
+
nl
|
30
|
+
say('No VMs')
|
31
|
+
nl
|
32
|
+
return
|
33
|
+
end
|
24
34
|
|
25
35
|
sorted = vms.sort do |a, b|
|
26
|
-
s = a[
|
27
|
-
s = a[
|
28
|
-
s = a[
|
36
|
+
s = a['job_name'].to_s <=> b['job_name'].to_s
|
37
|
+
s = a['index'].to_i <=> b['index'].to_i if s == 0
|
38
|
+
s = a['resource_pool'].to_s <=> b['resource_pool'].to_s if s == 0
|
29
39
|
s
|
30
40
|
end
|
31
41
|
|
32
42
|
vms_table = table do |t|
|
33
|
-
headings = [
|
34
|
-
|
35
|
-
|
43
|
+
headings = ['Job/index', 'State', 'Resource Pool', 'IPs']
|
44
|
+
if options[:details]
|
45
|
+
headings += ['CID', 'Agent ID', 'Resurrection']
|
46
|
+
end
|
47
|
+
if options[:dns]
|
48
|
+
headings += ['DNS A records']
|
49
|
+
end
|
50
|
+
if options[:vitals]
|
51
|
+
headings += [{:value => "Load\n(avg01, avg05, avg15)", :alignment => :center}]
|
52
|
+
headings += ["CPU\nUser", "CPU\nSys", "CPU\nWait"]
|
53
|
+
headings += ['Memory Usage', 'Swap Usage']
|
54
|
+
headings += ["System\nDisk Usage", "Ephemeral\nDisk Usage", "Persistent\nDisk Usage"]
|
55
|
+
end
|
36
56
|
t.headings = headings
|
37
57
|
|
38
58
|
sorted.each do |vm|
|
39
|
-
job = "#{vm[
|
40
|
-
ips = Array(vm[
|
59
|
+
job = "#{vm['job_name'] || 'unknown'}/#{vm['index'] || 'unknown'}"
|
60
|
+
ips = Array(vm['ips']).join(', ')
|
61
|
+
dns_records = Array(vm['dns']).join("\n")
|
62
|
+
vitals = vm['vitals']
|
63
|
+
|
64
|
+
row = [job, vm['job_state'], vm['resource_pool'], ips]
|
65
|
+
|
66
|
+
if options[:details]
|
67
|
+
row += [vm['vm_cid'], vm['agent_id'], vm['resurrection_paused'] ? 'paused' : 'active']
|
68
|
+
end
|
69
|
+
|
70
|
+
if options[:dns]
|
71
|
+
row += [dns_records.empty? ? 'n/a' : dns_records]
|
72
|
+
end
|
73
|
+
|
74
|
+
if options[:vitals]
|
75
|
+
if vitals
|
76
|
+
cpu = vitals['cpu']
|
77
|
+
mem = vitals['mem']
|
78
|
+
swap = vitals['swap']
|
79
|
+
disk = vitals['disk']
|
41
80
|
|
42
|
-
|
43
|
-
|
81
|
+
row << vitals['load'].map { |l| "#{l}%" }.join(', ')
|
82
|
+
row << "#{cpu['user']}%"
|
83
|
+
row << "#{cpu['sys']}%"
|
84
|
+
row << "#{cpu['wait']}%"
|
85
|
+
row << "#{mem['percent']}% (#{pretty_size(mem['kb'].to_i * 1024)})"
|
86
|
+
row << "#{swap['percent']}% (#{pretty_size(swap['kb'].to_i * 1024)})"
|
87
|
+
row << "#{disk['system']['percent']}%"
|
88
|
+
if disk['ephemeral'].nil?
|
89
|
+
row << 'n/a'
|
90
|
+
else
|
91
|
+
row << "#{disk['ephemeral']['percent']}%"
|
92
|
+
end
|
93
|
+
if disk['persistent'].nil?
|
94
|
+
row << 'n/a'
|
95
|
+
else
|
96
|
+
row << "#{disk['persistent']['percent']}%"
|
97
|
+
end
|
98
|
+
else
|
99
|
+
9.times { row << 'n/a' }
|
100
|
+
end
|
101
|
+
end
|
44
102
|
|
45
103
|
t << row
|
46
104
|
end
|
@@ -49,7 +107,7 @@ module Bosh::Cli::Command
|
|
49
107
|
nl
|
50
108
|
say(vms_table)
|
51
109
|
nl
|
52
|
-
say(
|
110
|
+
say('VMs total: %d' % vms.size)
|
53
111
|
end
|
54
112
|
|
55
113
|
end
|
data/lib/cli/config.rb
CHANGED
@@ -19,6 +19,9 @@ module Bosh::Cli
|
|
19
19
|
|
20
20
|
# @return [Bosh::Cli::Cache] CLI cache (to save task logs etc.)
|
21
21
|
attr_accessor :cache
|
22
|
+
|
23
|
+
# @return [Integer] CLI polling interval
|
24
|
+
attr_accessor :poll_interval
|
22
25
|
end
|
23
26
|
|
24
27
|
@commands = {}
|
@@ -42,7 +45,7 @@ module Bosh::Cli
|
|
42
45
|
@work_dir = work_dir
|
43
46
|
|
44
47
|
unless File.exists?(@filename)
|
45
|
-
File.open(@filename, "w") { |f|
|
48
|
+
File.open(@filename, "w") { |f| Psych.dump({}, f) }
|
46
49
|
File.chmod(0600, @filename)
|
47
50
|
end
|
48
51
|
|
@@ -188,12 +191,13 @@ module Bosh::Cli
|
|
188
191
|
|
189
192
|
def save
|
190
193
|
File.open(@filename, "w") do |f|
|
191
|
-
|
194
|
+
Psych.dump(@config_file, f)
|
192
195
|
end
|
193
196
|
|
194
197
|
rescue SystemCallError => e
|
195
198
|
raise ConfigError, e.message
|
196
199
|
end
|
197
200
|
|
201
|
+
attr_reader :filename
|
198
202
|
end
|
199
203
|
end
|
data/lib/cli/core_ext.rb
CHANGED
@@ -66,30 +66,42 @@ module BoshExtensions
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def load_yaml_file(path, expected_type = Hash)
|
69
|
-
err("Cannot find file `#{path}'") unless File.
|
70
|
-
yaml = YAML.load_file(path)
|
69
|
+
err("Cannot find file `#{path}'".make_red) unless File.exist?(path)
|
71
70
|
|
72
|
-
|
73
|
-
|
71
|
+
begin
|
72
|
+
yaml_str = ERB.new(File.read(path)).result
|
73
|
+
rescue SystemCallError => e
|
74
|
+
err("Cannot load YAML file at `#{path}': #{e}".make_red)
|
75
|
+
end
|
76
|
+
|
77
|
+
begin
|
78
|
+
Bosh::Cli::YamlHelper.check_duplicate_keys(yaml_str)
|
79
|
+
rescue => e
|
80
|
+
err("Incorrect YAML structure in `#{path}': #{e}".make_red)
|
74
81
|
end
|
75
82
|
|
76
|
-
|
83
|
+
yaml = Psych::load(yaml_str)
|
84
|
+
if expected_type && !yaml.is_a?(expected_type)
|
85
|
+
err("Incorrect YAML structure in `#{path}': expected #{expected_type} at the root".make_red)
|
86
|
+
end
|
77
87
|
|
78
88
|
yaml
|
79
|
-
rescue SystemCallError => e
|
80
|
-
err("Cannot load YAML file at `#{path}': #{e}")
|
81
89
|
end
|
82
90
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
|
91
|
+
def write_yaml(manifest, path)
|
92
|
+
File.open(path, "w+") do |f|
|
93
|
+
f.write(manifest.to_yaml)
|
94
|
+
end
|
87
95
|
end
|
88
96
|
|
89
97
|
# @return [Fixnum]
|
90
98
|
def terminal_width
|
91
99
|
STDIN.tty? ? [HighLine::SystemExtensions.terminal_size[0], 120].min : 80
|
92
100
|
end
|
101
|
+
|
102
|
+
def warning(message)
|
103
|
+
warn("[WARNING] #{message}".make_yellow)
|
104
|
+
end
|
93
105
|
end
|
94
106
|
|
95
107
|
module BoshStringExtensions
|
@@ -100,19 +112,19 @@ module BoshStringExtensions
|
|
100
112
|
:yellow => "\e[0m\e[33m"
|
101
113
|
}
|
102
114
|
|
103
|
-
def
|
104
|
-
|
115
|
+
def make_red
|
116
|
+
make_color(:red)
|
105
117
|
end
|
106
118
|
|
107
|
-
def
|
108
|
-
|
119
|
+
def make_green
|
120
|
+
make_color(:green)
|
109
121
|
end
|
110
122
|
|
111
|
-
def
|
112
|
-
|
123
|
+
def make_yellow
|
124
|
+
make_color(:yellow)
|
113
125
|
end
|
114
126
|
|
115
|
-
def
|
127
|
+
def make_color(color_code)
|
116
128
|
if Bosh::Cli::Config.output &&
|
117
129
|
Bosh::Cli::Config.output.tty? &&
|
118
130
|
Bosh::Cli::Config.colorize &&
|
@@ -144,18 +156,7 @@ module BoshStringExtensions
|
|
144
156
|
end
|
145
157
|
|
146
158
|
def columnize(width = 80, left_margin = 0)
|
147
|
-
|
148
|
-
buf = ""
|
149
|
-
self.split(/\s+/).each do |word|
|
150
|
-
if buf.size + word.size > width
|
151
|
-
result << buf << "\n" << " " * left_margin
|
152
|
-
buf = word + " "
|
153
|
-
else
|
154
|
-
buf << word << " "
|
155
|
-
end
|
156
|
-
|
157
|
-
end
|
158
|
-
result + buf
|
159
|
+
Bosh::Cli::LineWrap.new(width, left_margin).wrap(self)
|
159
160
|
end
|
160
161
|
|
161
162
|
def indent(margin = 2)
|