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.
Files changed (144) hide show
  1. data/bin/bosh +0 -9
  2. data/lib/cli.rb +69 -64
  3. data/lib/cli/backup_destination_path.rb +33 -0
  4. data/lib/cli/base_command.rb +57 -56
  5. data/lib/cli/blob_manager.rb +12 -12
  6. data/lib/cli/changeset_helper.rb +6 -7
  7. data/lib/cli/client/director.rb +724 -0
  8. data/lib/cli/command_handler.rb +6 -7
  9. data/lib/cli/commands/backup.rb +39 -0
  10. data/lib/cli/commands/biff.rb +42 -21
  11. data/lib/cli/commands/blob_management.rb +1 -1
  12. data/lib/cli/commands/cloudcheck.rb +11 -13
  13. data/lib/cli/commands/deployment.rb +53 -37
  14. data/lib/cli/commands/help.rb +3 -2
  15. data/lib/cli/commands/job_management.rb +67 -103
  16. data/lib/cli/commands/job_rename.rb +6 -8
  17. data/lib/cli/commands/log_management.rb +78 -55
  18. data/lib/cli/commands/maintenance.rb +36 -30
  19. data/lib/cli/commands/misc.rb +72 -51
  20. data/lib/cli/commands/package.rb +2 -2
  21. data/lib/cli/commands/property_management.rb +10 -12
  22. data/lib/cli/commands/release.rb +236 -133
  23. data/lib/cli/commands/snapshot.rb +93 -0
  24. data/lib/cli/commands/ssh.rb +216 -213
  25. data/lib/cli/commands/stemcell.rb +46 -34
  26. data/lib/cli/commands/task.rb +2 -2
  27. data/lib/cli/commands/user.rb +27 -3
  28. data/lib/cli/commands/vm.rb +28 -0
  29. data/lib/cli/commands/vms.rb +81 -23
  30. data/lib/cli/config.rb +6 -2
  31. data/lib/cli/core_ext.rb +31 -30
  32. data/lib/cli/deployment_helper.rb +134 -159
  33. data/lib/cli/deployment_manifest.rb +66 -0
  34. data/lib/cli/deployment_manifest_compiler.rb +0 -3
  35. data/lib/cli/event_log_renderer.rb +10 -10
  36. data/lib/cli/file_with_progress_bar.rb +52 -0
  37. data/lib/cli/job_builder.rb +1 -1
  38. data/lib/cli/job_command_args.rb +23 -0
  39. data/lib/cli/job_property_collection.rb +4 -7
  40. data/lib/cli/job_property_validator.rb +22 -12
  41. data/lib/cli/job_state.rb +54 -0
  42. data/lib/cli/line_wrap.rb +54 -0
  43. data/lib/cli/packaging_helper.rb +10 -10
  44. data/lib/cli/release.rb +18 -15
  45. data/lib/cli/release_builder.rb +9 -4
  46. data/lib/cli/release_compiler.rb +9 -9
  47. data/lib/cli/release_tarball.rb +3 -6
  48. data/lib/cli/resurrection.rb +31 -0
  49. data/lib/cli/runner.rb +56 -30
  50. data/lib/cli/stemcell.rb +25 -10
  51. data/lib/cli/task_log_renderer.rb +1 -1
  52. data/lib/cli/task_tracker.rb +10 -9
  53. data/lib/cli/validation.rb +3 -1
  54. data/lib/cli/version.rb +1 -1
  55. data/lib/cli/version_calc.rb +5 -18
  56. data/lib/cli/versions_index.rb +1 -1
  57. data/lib/cli/vm_state.rb +43 -0
  58. data/lib/cli/yaml_helper.rb +26 -35
  59. metadata +75 -208
  60. data/Rakefile +0 -56
  61. data/lib/cli/director.rb +0 -628
  62. data/spec/assets/biff/bad_gateway_config.yml +0 -28
  63. data/spec/assets/biff/good_simple_config.yml +0 -63
  64. data/spec/assets/biff/good_simple_golden_config.yml +0 -63
  65. data/spec/assets/biff/good_simple_template.erb +0 -69
  66. data/spec/assets/biff/ip_out_of_range.yml +0 -63
  67. data/spec/assets/biff/multiple_subnets_config.yml +0 -40
  68. data/spec/assets/biff/network_only_template.erb +0 -34
  69. data/spec/assets/biff/no_cc_config.yml +0 -27
  70. data/spec/assets/biff/no_range_config.yml +0 -27
  71. data/spec/assets/biff/no_subnet_config.yml +0 -16
  72. data/spec/assets/biff/ok_network_config.yml +0 -30
  73. data/spec/assets/biff/properties_template.erb +0 -6
  74. data/spec/assets/config/atmos/config/final.yml +0 -6
  75. data/spec/assets/config/atmos/config/private.yml +0 -4
  76. data/spec/assets/config/bad-providers/config/final.yml +0 -5
  77. data/spec/assets/config/bad-providers/config/private.yml +0 -4
  78. data/spec/assets/config/deprecation/config/final.yml +0 -5
  79. data/spec/assets/config/deprecation/config/private.yml +0 -2
  80. data/spec/assets/config/local/config/final.yml +0 -5
  81. data/spec/assets/config/local/config/private.yml +0 -1
  82. data/spec/assets/config/s3/config/final.yml +0 -5
  83. data/spec/assets/config/s3/config/private.yml +0 -5
  84. data/spec/assets/config/swift-hp/config/final.yml +0 -6
  85. data/spec/assets/config/swift-hp/config/private.yml +0 -7
  86. data/spec/assets/config/swift-rackspace/config/final.yml +0 -6
  87. data/spec/assets/config/swift-rackspace/config/private.yml +0 -6
  88. data/spec/assets/deployment.MF +0 -0
  89. data/spec/assets/plugins/bosh/cli/commands/echo.rb +0 -43
  90. data/spec/assets/plugins/bosh/cli/commands/ruby.rb +0 -24
  91. data/spec/assets/release/jobs/cacher.tgz +0 -0
  92. data/spec/assets/release/jobs/cacher/config/file1.conf +0 -0
  93. data/spec/assets/release/jobs/cacher/config/file2.conf +0 -0
  94. data/spec/assets/release/jobs/cacher/job.MF +0 -6
  95. data/spec/assets/release/jobs/cacher/monit +0 -1
  96. data/spec/assets/release/jobs/cleaner.tgz +0 -0
  97. data/spec/assets/release/jobs/cleaner/job.MF +0 -4
  98. data/spec/assets/release/jobs/cleaner/monit +0 -1
  99. data/spec/assets/release/jobs/sweeper.tgz +0 -0
  100. data/spec/assets/release/jobs/sweeper/config/test.conf +0 -1
  101. data/spec/assets/release/jobs/sweeper/job.MF +0 -5
  102. data/spec/assets/release/jobs/sweeper/monit +0 -1
  103. data/spec/assets/release/packages/mutator.tar.gz +0 -0
  104. data/spec/assets/release/packages/stuff.tgz +0 -0
  105. data/spec/assets/release/release.MF +0 -17
  106. data/spec/assets/release_invalid_checksum.tgz +0 -0
  107. data/spec/assets/release_invalid_jobs.tgz +0 -0
  108. data/spec/assets/release_no_name.tgz +0 -0
  109. data/spec/assets/release_no_version.tgz +0 -0
  110. data/spec/assets/stemcell/image +0 -1
  111. data/spec/assets/stemcell/stemcell.MF +0 -6
  112. data/spec/assets/stemcell_invalid_mf.tgz +0 -0
  113. data/spec/assets/stemcell_no_image.tgz +0 -0
  114. data/spec/assets/valid_release.tgz +0 -0
  115. data/spec/assets/valid_stemcell.tgz +0 -0
  116. data/spec/spec_helper.rb +0 -28
  117. data/spec/unit/base_command_spec.rb +0 -87
  118. data/spec/unit/biff_spec.rb +0 -172
  119. data/spec/unit/blob_manager_spec.rb +0 -288
  120. data/spec/unit/cache_spec.rb +0 -36
  121. data/spec/unit/cli_commands_spec.rb +0 -356
  122. data/spec/unit/config_spec.rb +0 -125
  123. data/spec/unit/core_ext_spec.rb +0 -81
  124. data/spec/unit/dependency_helper_spec.rb +0 -52
  125. data/spec/unit/deployment_manifest_compiler_spec.rb +0 -63
  126. data/spec/unit/deployment_manifest_spec.rb +0 -153
  127. data/spec/unit/director_spec.rb +0 -471
  128. data/spec/unit/director_task_spec.rb +0 -48
  129. data/spec/unit/event_log_renderer_spec.rb +0 -171
  130. data/spec/unit/hash_changeset_spec.rb +0 -73
  131. data/spec/unit/job_builder_spec.rb +0 -455
  132. data/spec/unit/job_property_collection_spec.rb +0 -111
  133. data/spec/unit/job_property_validator_spec.rb +0 -7
  134. data/spec/unit/job_rename_spec.rb +0 -200
  135. data/spec/unit/package_builder_spec.rb +0 -593
  136. data/spec/unit/release_builder_spec.rb +0 -120
  137. data/spec/unit/release_spec.rb +0 -173
  138. data/spec/unit/release_tarball_spec.rb +0 -29
  139. data/spec/unit/runner_spec.rb +0 -7
  140. data/spec/unit/ssh_spec.rb +0 -84
  141. data/spec/unit/stemcell_spec.rb +0 -17
  142. data/spec/unit/task_tracker_spec.rb +0 -131
  143. data/spec/unit/version_calc_spec.rb +0 -27
  144. 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/rest/objects/4e4e78bca2" +
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".green)
28
+ say("`#{tarball_path}' is a valid stemcell".make_green)
31
29
  else
32
- say("Validation errors:".red)
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(tarball_path)
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
- stemcell = Bosh::Cli::Stemcell.new(tarball_path, cache)
47
-
48
- nl
49
- say("Verifying stemcell...")
50
- stemcell.validate
51
- nl
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
- unless stemcell.valid?
54
- err("Stemcell is invalid, please fix, verify and upload again")
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
- 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")
78
+ if stemcell_type == "local"
79
+ status, task_id = director.upload_stemcell(stemcell_location)
64
80
  else
65
- say("No")
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".green)
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}'".red)
201
+ say("You are going to delete stemcell `#{name}/#{version}'".make_red)
190
202
 
191
203
  unless confirmed?
192
- say("Canceled deleting stemcell".green)
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
- YAML.load(response.body)
247
+ Psych.load(response.body)
236
248
  end
237
249
 
238
250
  end
@@ -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
@@ -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".green)
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
@@ -2,45 +2,103 @@
2
2
 
3
3
  module Bosh::Cli::Command
4
4
  class Vms < Base
5
- include Bosh::Cli::DeploymentHelper
6
-
7
- usage "vms"
8
- desc "List all VMs that in a deployment"
9
- option "--full", "Return detailed VM information"
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
- deployment_required
17
- manifest = prepare_deployment_manifest
18
- deployment_name = manifest["name"]
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
- say("Deployment `#{deployment_name.green}'")
22
- vms = director.fetch_vm_state(deployment_name)
23
- err("No VMs") if vms.empty?
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["job_name"].to_s <=> b["job_name"].to_s
27
- s = a["index"].to_i <=> b["index"].to_i if s == 0
28
- s = a["resource_pool"].to_s <=> b["resource_pool"].to_s if s == 0
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 = ["Job/index", "State", "Resource Pool", "IPs"]
34
- headings += ["CID", "Agent ID"] if show_full_stats
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["job_name"] || "unknown"}/#{vm["index"] || "unknown"}"
40
- ips = Array(vm["ips"]).join(", ")
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
- row = [job, vm["job_state"], vm["resource_pool"], ips]
43
- row += [vm["vm_cid"], vm["agent_id"]] if show_full_stats
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("VMs total: %d" % vms.size)
110
+ say('VMs total: %d' % vms.size)
53
111
  end
54
112
 
55
113
  end
@@ -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| YAML.dump({}, 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
- YAML.dump(@config_file, f)
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
@@ -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.exists?(path)
70
- yaml = YAML.load_file(path)
69
+ err("Cannot find file `#{path}'".make_red) unless File.exist?(path)
71
70
 
72
- if expected_type && !yaml.is_a?(expected_type)
73
- err("Incorrect file format in `#{path}', #{expected_type} expected")
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
- Bosh::Cli::YamlHelper.check_duplicate_keys(path)
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 dump_yaml_to_file(obj, file)
84
- yaml = YAML.dump(obj)
85
- file.write(yaml.gsub(" \n", "\n"))
86
- file.flush
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 red
104
- colorize(:red)
115
+ def make_red
116
+ make_color(:red)
105
117
  end
106
118
 
107
- def green
108
- colorize(:green)
119
+ def make_green
120
+ make_color(:green)
109
121
  end
110
122
 
111
- def yellow
112
- colorize(:yellow)
123
+ def make_yellow
124
+ make_color(:yellow)
113
125
  end
114
126
 
115
- def colorize(color_code)
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
- result = ""
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)