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.
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
@@ -15,9 +15,6 @@ module Bosh::Cli
15
15
  end
16
16
 
17
17
  def result
18
- # TODO: erb is just a fancy eval, so it's not very trustworthy,
19
- # consider using more constrained template engine.
20
- # Note that we use $SAFE=4 for ERB which is a strawman sandbox.
21
18
  ERB.new(@raw_manifest, 4).result(binding.taint)
22
19
  rescue SyntaxError => e
23
20
  raise MalformedManifest,
@@ -64,7 +64,7 @@ module Bosh::Cli
64
64
  stage_header = event["stage"]
65
65
 
66
66
  if tags.size > 0
67
- stage_header += " " + tags.sort.join(", ").green
67
+ stage_header += " " + tags.sort.join(", ").make_green
68
68
  end
69
69
 
70
70
  unless @seen_stages.include?(stage_header)
@@ -122,8 +122,7 @@ module Bosh::Cli
122
122
  error += " #{code}" if code
123
123
  error += ": #{message}" if message
124
124
 
125
- # TODO: add KB article link and maybe cck reference?
126
- @buffer.puts("\n" + error.red)
125
+ @buffer.puts("\n" + error.make_red)
127
126
  end
128
127
 
129
128
  def refresh
@@ -178,12 +177,12 @@ module Bosh::Cli
178
177
 
179
178
  case state.to_s
180
179
  when "done"
181
- progress_bar.title = "Done".green
180
+ progress_bar.title = "Done".make_green
182
181
  progress_bar.finished_steps = progress_bar.total
183
182
  when "error"
184
- progress_bar.title = "Error".red
183
+ progress_bar.title = "Error".make_red
185
184
  else
186
- progress_bar.title = "Not done".yellow
185
+ progress_bar.title = "Not done".make_yellow
187
186
  end
188
187
 
189
188
  progress_bar.bar_visible = false
@@ -272,11 +271,10 @@ module Bosh::Cli
272
271
  end
273
272
 
274
273
  if event["state"] == "failed"
275
- # TODO: truncate?
276
- status = [task_name.red, event_data["error"]].compact.join(": ")
274
+ status = [task_name.make_red, event_data["error"]].compact.join(": ")
277
275
  @stage_has_error = true
278
276
  else
279
- status = task_name.yellow
277
+ status = task_name.make_yellow
280
278
  end
281
279
  @buffer.puts(" #{status} (#{format_time(task_time)})")
282
280
  when "in_progress"
@@ -376,7 +374,9 @@ module Bosh::Cli
376
374
  end
377
375
 
378
376
  def calculate_terminal_width
379
- if !ENV["TERM"].blank?
377
+ if ENV["COLUMNS"].to_s =~ /^\d+$/
378
+ ENV["COLUMNS"].to_i
379
+ elsif !ENV["TERM"].blank?
380
380
  width = `tput cols`
381
381
  $?.exitstatus == 0 ? [width.to_i, 100].min : 80
382
382
  else
@@ -0,0 +1,52 @@
1
+ module Bosh
2
+ module Cli
3
+ class FileWithProgressBar < ::File
4
+
5
+ def progress_bar
6
+ return @progress_bar if @progress_bar
7
+ out = Bosh::Cli::Config.output || StringIO.new
8
+ @progress_bar = ProgressBar.new(file_name, size, out)
9
+ @progress_bar.file_transfer_mode
10
+ @progress_bar
11
+ end
12
+
13
+ def file_name
14
+ File.basename(self.path)
15
+ end
16
+
17
+ def stop_progress_bar
18
+ progress_bar.halt unless progress_bar.finished?
19
+ end
20
+
21
+ def size
22
+ @size || File.size(self.path)
23
+ end
24
+
25
+ def size=(size)
26
+ @size=size
27
+ end
28
+
29
+ def read(*args)
30
+ result = super(*args)
31
+
32
+ if result && result.size > 0
33
+ progress_bar.inc(result.size)
34
+ else
35
+ progress_bar.finish
36
+ end
37
+
38
+ result
39
+ end
40
+
41
+ def write(*args)
42
+ count = super(*args)
43
+ if count
44
+ progress_bar.inc(count)
45
+ else
46
+ progress_bar.finish
47
+ end
48
+ count
49
+ end
50
+ end
51
+ end
52
+ end
@@ -37,7 +37,7 @@ module Bosh::Cli
37
37
  end
38
38
 
39
39
  unless $?.exitstatus == 0
40
- raise InvalidJob, "`#{script_path}' script failed"
40
+ raise InvalidJob, "`#{script_path}' script failed: #{output}"
41
41
  end
42
42
 
43
43
  output
@@ -0,0 +1,23 @@
1
+ module Bosh::Cli
2
+ class JobCommandArgs < Struct.new(:job, :index, :args)
3
+ def initialize(args)
4
+ job = args.shift
5
+ err('Please provide job name') if job.nil?
6
+ job, index = job.split('/', 2)
7
+
8
+ if index
9
+ if index =~ /^\d+$/
10
+ index = index.to_i
11
+ else
12
+ err('Invalid job index, integer number expected')
13
+ end
14
+ elsif args[0] =~ /^\d+$/
15
+ index = args.shift.to_i
16
+ end
17
+
18
+ self.job = job
19
+ self.index = index
20
+ self.args = args
21
+ end
22
+ end
23
+ end
@@ -1,5 +1,7 @@
1
1
  # Copyright (c) 2009-2012 VMware, Inc.
2
2
 
3
+ require 'common/deep_copy'
4
+
3
5
  module Bosh::Cli
4
6
  class JobPropertyCollection
5
7
  include Enumerable
@@ -12,8 +14,8 @@ module Bosh::Cli
12
14
  def initialize(job_builder, global_properties, job_properties, mappings)
13
15
  @job_builder = job_builder
14
16
 
15
- @job_properties = deep_copy(job_properties || {})
16
- merge(@job_properties, deep_copy(global_properties))
17
+ @job_properties = Bosh::Common::DeepCopy.copy(job_properties || {})
18
+ merge(@job_properties, Bosh::Common::DeepCopy.copy(global_properties))
17
19
 
18
20
  @mappings = mappings || {}
19
21
  @properties = []
@@ -64,11 +66,6 @@ module Bosh::Cli
64
66
  end
65
67
  end
66
68
 
67
- # @param [Object] object Serializable object
68
- # @return [Object] Deep copy of the object
69
- def deep_copy(object)
70
- Marshal.load(Marshal.dump(object))
71
- end
72
69
 
73
70
  # @param [Hash] base
74
71
  # @param [Hash] extras
@@ -2,7 +2,6 @@
2
2
 
3
3
  module Bosh::Cli
4
4
  class JobPropertyValidator
5
- # TODO: tests
6
5
 
7
6
  attr_reader :template_errors
8
7
  attr_reader :jobs_without_properties
@@ -49,12 +48,16 @@ module Bosh::Cli
49
48
  end
50
49
 
51
50
  @template_errors = []
52
- # TODO: track missing props and show the list to user (super helpful!)
53
51
  end
54
52
 
55
53
  def validate
56
54
  @manifest["jobs"].each do |job_spec|
57
- validate_templates(job_spec)
55
+ job_templates = Array(job_spec['template'])
56
+ job_templates.each do |job_template|
57
+ job_spec_for_template = job_spec.dup
58
+ job_spec_for_template['template'] = job_template
59
+ validate_templates(job_spec_for_template)
60
+ end
58
61
  end
59
62
  end
60
63
 
@@ -73,24 +76,31 @@ module Bosh::Cli
73
76
 
74
77
  # Spec is usually more than that but jobs rarely use anything but
75
78
  # networks and properties.
76
- # TODO: provide all keys in the spec?
77
79
  spec = {
78
- "job" => {
79
- "name" => job_spec["name"]
80
- },
81
- "networks" => {
82
- "default" => {"ip" => "10.0.0.1"}
80
+ 'job' => {
81
+ 'name' => job_spec['name']
83
82
  },
84
- "properties" => collection.to_hash,
85
- "index" => 0
83
+ 'index' => 0,
84
+ 'networks' => job_network_spec(job_spec),
85
+ 'properties' => collection.to_hash
86
86
  }
87
87
 
88
88
  built_job.all_templates.each do |template_path|
89
- # TODO: add progress bar?
90
89
  evaluate_template(built_job, template_path, spec)
91
90
  end
92
91
  end
93
92
 
93
+ def job_network_spec(job_spec)
94
+ job_spec['networks'].reduce({}) do |networks, network|
95
+ networks[network['name']] = {
96
+ 'ip' => '127.0.0.1', # faking the IP since it shouldn't affect logic
97
+ 'netmask' => '255.255.255.0',
98
+ 'gateway' => '127.0.0.2'
99
+ }
100
+ networks
101
+ end
102
+ end
103
+
94
104
  private
95
105
 
96
106
  # @param [JobBuilder] job Job builder
@@ -0,0 +1,54 @@
1
+ module Bosh::Cli
2
+ class JobState
3
+ OPERATION_DESCRIPTIONS = {
4
+ start: 'start %s',
5
+ stop: 'stop %s',
6
+ detach: 'stop %s and power off its VM(s)',
7
+ restart: 'restart %s',
8
+ recreate: 'recreate %s'
9
+ }
10
+
11
+ NEW_STATES = {
12
+ start: 'started',
13
+ stop: 'stopped',
14
+ detach: 'detached',
15
+ restart: 'restart',
16
+ recreate: 'recreate'
17
+ }
18
+
19
+ COMPLETION_DESCRIPTIONS = {
20
+ start: '%s has been started',
21
+ stop: '%s has been stopped, VM(s) still running',
22
+ detach: '%s has been detached, VM(s) powered off',
23
+ restart: '%s has been restarted',
24
+ recreate: '%s has been recreated'
25
+ }
26
+
27
+ def initialize(command, vm_state)
28
+ @command = command
29
+ @vm_state = vm_state
30
+ end
31
+
32
+ def change(state, job, index)
33
+ job_desc = job_description(job, index)
34
+ op_desc = OPERATION_DESCRIPTIONS.fetch(state) % job_desc
35
+ new_state = NEW_STATES.fetch(state)
36
+ completion_desc = COMPLETION_DESCRIPTIONS.fetch(state) % job_desc.make_green
37
+
38
+ status, task_id = perform_vm_state_change(job, index, new_state, op_desc)
39
+
40
+ [status, task_id, completion_desc]
41
+ end
42
+
43
+ private
44
+ attr_reader :command, :vm_state
45
+
46
+ def job_description(job, index)
47
+ index ? "#{job}/#{index}" : "#{job}"
48
+ end
49
+
50
+ def perform_vm_state_change(job, index, new_state, operation_desc)
51
+ vm_state.change(job, index, new_state, operation_desc)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,54 @@
1
+ module Bosh::Cli
2
+ class LineWrap
3
+ def initialize(width, left_margin = 0)
4
+ @width = width
5
+ @left_margin = left_margin
6
+ end
7
+
8
+ def wrap(string)
9
+ paragraphs = string.split("\n")
10
+
11
+ wrapped_paragraphs = paragraphs.map do |paragraph|
12
+ lines = wrapped_lines(paragraph)
13
+ lines = indent_lines(lines)
14
+
15
+ paragraph_indentation(paragraph) + lines.join("\n")
16
+ end
17
+
18
+ wrapped_paragraphs.join("\n")
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :width
24
+ attr_reader :left_margin
25
+
26
+ def paragraph_indentation(paragraph)
27
+ paragraph.start_with?(' ') ? ' ' : ''
28
+ end
29
+
30
+ def wrapped_lines(string)
31
+ result = []
32
+ buffer = ''
33
+
34
+ string.split(' ').each do |word|
35
+ if new_line_needed?(buffer, word)
36
+ result << buffer
37
+ buffer = word
38
+ else
39
+ buffer << ' ' unless buffer.empty?
40
+ buffer << word
41
+ end
42
+ end
43
+ result << buffer
44
+ end
45
+
46
+ def new_line_needed?(buffer, word)
47
+ buffer.size + word.size > width
48
+ end
49
+
50
+ def indent_lines(lines)
51
+ lines.map { |line| (' ' * left_margin) + line }
52
+ end
53
+ end
54
+ end
@@ -65,7 +65,7 @@ module Bosh::Cli
65
65
  item = @final_index[fingerprint]
66
66
 
67
67
  if item.nil?
68
- say("NOT FOUND".red)
68
+ say("NOT FOUND".make_red)
69
69
  return nil
70
70
  end
71
71
 
@@ -73,7 +73,7 @@ module Bosh::Cli
73
73
  version = item["version"]
74
74
 
75
75
  if blobstore_id.nil?
76
- say("No blobstore id".red)
76
+ say("No blobstore id".make_red)
77
77
  return nil
78
78
  end
79
79
 
@@ -81,18 +81,18 @@ module Bosh::Cli
81
81
  need_fetch = true
82
82
 
83
83
  if File.exists?(filename)
84
- say("FOUND LOCAL".green)
84
+ say("FOUND LOCAL".make_green)
85
85
  if file_checksum(filename) == item["sha1"]
86
86
  @tarball_path = filename
87
87
  need_fetch = false
88
88
  else
89
- say("LOCAL CHECKSUM MISMATCH".red)
89
+ say("LOCAL CHECKSUM MISMATCH".make_red)
90
90
  need_fetch = true
91
91
  end
92
92
  end
93
93
 
94
94
  if need_fetch
95
- say("Downloading `#{name} (#{version})'...".green)
95
+ say("Downloading `#{name} (#{version})'...".make_green)
96
96
  tmp_file = File.open(File.join(Dir.mktmpdir, name), "w")
97
97
  @blobstore.get(blobstore_id, tmp_file)
98
98
  tmp_file.close
@@ -121,7 +121,7 @@ module Bosh::Cli
121
121
  item = @dev_index[fingerprint]
122
122
 
123
123
  if item.nil?
124
- say("NOT FOUND".red)
124
+ say("NOT FOUND".make_red)
125
125
  return nil
126
126
  end
127
127
 
@@ -129,9 +129,9 @@ module Bosh::Cli
129
129
  filename = @dev_index.filename(version)
130
130
 
131
131
  if File.exists?(filename)
132
- say("FOUND LOCAL".green)
132
+ say("FOUND LOCAL".make_green)
133
133
  else
134
- say("TARBALL MISSING".red)
134
+ say("TARBALL MISSING".make_red)
135
135
  return nil
136
136
  end
137
137
 
@@ -140,7 +140,7 @@ module Bosh::Cli
140
140
  @version = version
141
141
  @used_dev_version = true
142
142
  else
143
- say("`#{name} (#{version})' tarball corrupted".red)
143
+ say("`#{name} (#{version})' tarball corrupted".make_red)
144
144
  return nil
145
145
  end
146
146
  end
@@ -182,7 +182,7 @@ module Bosh::Cli
182
182
 
183
183
  @version = version
184
184
  @tarball_generated = true
185
- say("Generated version #{version}".green)
185
+ say("Generated version #{version}".make_green)
186
186
  true
187
187
  end
188
188
 
@@ -66,6 +66,7 @@ module Bosh::Cli
66
66
  has_blobstore_secrets?(bs, "simple", "user", "password") ||
67
67
  has_blobstore_secrets?(bs, "swift", "rackspace") ||
68
68
  has_blobstore_secrets?(bs, "swift", "hp") ||
69
+ has_blobstore_secrets?(bs, "swift", "openstack") ||
69
70
  has_blobstore_secrets?(bs, "s3", "access_key_id", "secret_access_key")
70
71
  end
71
72
 
@@ -111,14 +112,8 @@ module Bosh::Cli
111
112
  end
112
113
 
113
114
  def save_config
114
- # TODO: introduce write_yaml helper
115
- File.open(@dev_config_file, "w") do |f|
116
- YAML.dump(@dev_config, f)
117
- end
118
-
119
- File.open(@final_config_file, "w") do |f|
120
- YAML.dump(@final_config, f)
121
- end
115
+ write_yaml(@dev_config_file, @dev_config)
116
+ write_yaml(@final_config_file, @final_config)
122
117
  end
123
118
 
124
119
  private
@@ -146,7 +141,7 @@ module Bosh::Cli
146
141
 
147
142
  # stores blobstore_secret as blobstore.atmos.secret
148
143
  def deprecate_blobstore_secret
149
- say("WARNING:".red + " use of blobstore_secret is deprecated")
144
+ say("WARNING:".make_red + " use of blobstore_secret is deprecated")
150
145
 
151
146
  @private_config["blobstore"] ||= {}
152
147
  bs = @private_config["blobstore"]
@@ -168,7 +163,7 @@ module Bosh::Cli
168
163
  # to migrate while the old one tells you to upgrade.
169
164
  if @dev_config.has_key?("blobstore_options") &&
170
165
  @dev_config["blobstore_options"] != "deprecated"
171
- say("Found legacy dev config file `#{@dev_config_file}'".yellow)
166
+ say("Found legacy dev config file `#{@dev_config_file}'".make_yellow)
172
167
 
173
168
  new_dev_config = {
174
169
  "dev_name" => @dev_config["name"],
@@ -184,14 +179,14 @@ module Bosh::Cli
184
179
  @dev_config = new_dev_config
185
180
 
186
181
  File.open(@dev_config_file, "w") do |f|
187
- YAML.dump(@dev_config, f)
182
+ Psych.dump(@dev_config, f)
188
183
  end
189
- say("Migrated dev config file format".green)
184
+ say("Migrated dev config file format".make_green)
190
185
  end
191
186
 
192
187
  if @final_config.has_key?("blobstore_options") &&
193
188
  @final_config["blobstore_options"] != "deprecated"
194
- say("Found legacy config file `#{@final_config_file}'".yellow)
189
+ say("Found legacy config file `#{@final_config_file}'".make_yellow)
195
190
 
196
191
  unless @final_config["blobstore_options"]["provider"] == "atmos" &&
197
192
  @final_config["blobstore_options"].has_key?("atmos_options")
@@ -211,8 +206,8 @@ module Bosh::Cli
211
206
 
212
207
  @final_config = new_final_config
213
208
 
214
- File.open(@final_config_file, "w") { |f| YAML.dump(@final_config, f) }
215
- say("Migrated final config file format".green)
209
+ File.open(@final_config_file, "w") { |f| Psych.dump(@final_config, f) }
210
+ say("Migrated final config file format".make_green)
216
211
  end
217
212
  end
218
213
 
@@ -224,6 +219,14 @@ module Bosh::Cli
224
219
  end
225
220
  end
226
221
 
222
+ def write_yaml(file, hash)
223
+ unless hash == load_config(file)
224
+ File.open(file, "w+") do |f|
225
+ Psych.dump(hash, f)
226
+ end
227
+ end
228
+ end
229
+
227
230
  end
228
231
 
229
232
  end