bosh-cloudfoundry 0.7.0.alpha.3 → 0.7.0.alpha.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. data/ChangeLog.md +1 -0
  2. data/bosh-cloudfoundry.gemspec +2 -1
  3. data/lib/bosh/cli/commands/cf.rb +35 -130
  4. data/lib/bosh/cloudfoundry.rb +5 -2
  5. data/lib/bosh/cloudfoundry/deployment_attributes.rb +35 -30
  6. data/lib/bosh/cloudfoundry/deployment_file.rb +192 -0
  7. data/lib/bosh/cloudfoundry/release_version.rb +67 -0
  8. data/lib/bosh/cloudfoundry/release_version_cpi.rb +55 -0
  9. data/lib/bosh/cloudfoundry/release_version_cpi_size.rb +49 -0
  10. data/spec/assets/v132/aws/large.yml +393 -0
  11. data/spec/assets/v132/aws/medium.yml +350 -0
  12. data/spec/deployment_file_spec.rb +92 -0
  13. data/spec/plugin_spec.rb +32 -47
  14. data/spec/release_version_cpi_size_spec.rb +13 -0
  15. data/spec/release_version_cpi_spec.rb +17 -0
  16. data/spec/release_version_spec.rb +38 -0
  17. data/spec/spec_helper.rb +2 -0
  18. data/templates/v132/aws/large/deployment_file.yml.erb +431 -0
  19. data/templates/v132/aws/{dev → large}/spec +0 -0
  20. data/templates/v132/{openstack/dev → aws/medium}/deployment_file.yml.erb +35 -23
  21. data/templates/v132/{openstack/dev → aws/medium}/spec +0 -0
  22. data/templates/v132/aws/small/README.md +5 -0
  23. data/templates/v132/aws/spec +6 -0
  24. data/templates/v132/openstack/large/deployment_file.yml.erb +431 -0
  25. data/templates/v132/openstack/large/spec +6 -0
  26. data/templates/v132/{aws/dev → openstack/medium}/deployment_file.yml.erb +35 -23
  27. data/templates/v132/openstack/medium/spec +6 -0
  28. data/templates/v132/openstack/spec +6 -0
  29. metadata +46 -10
  30. data/lib/bosh/cloudfoundry/release_versioned_template.rb +0 -48
  31. data/spec/release_versioned_template_spec.rb +0 -12
data/ChangeLog.md CHANGED
@@ -17,5 +17,6 @@ The rewrite introduces some new implementation/feature concepts:
17
17
  * using `bosh diff` (aka biff) to generate the deployment file
18
18
  * bundles all final releases into the project & distributed rubygem/plugin (no runtime dependency on cf-release git repository; only the public blobstore)
19
19
  * templates are versioned for the final releases
20
+ * different sizes of deployments (orders of magnitude), such as small, medium & large
20
21
 
21
22
  The latter means that new versions of this rubygem can be published that are backwards compatible with aging deployments of Cloud Foundry. There should not be any forced coupling of old `bosh-cloudfoundry` to old `cf-release` final releases.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "bosh-cloudfoundry"
5
- spec.version = "0.7.0.alpha.3"
5
+ spec.version = "0.7.0.alpha.4"
6
6
  spec.authors = ["Dr Nic Williams"]
7
7
  spec.email = ["drnicwilliams@gmail.com"]
8
8
  spec.description = %q{Create & manage Cloud Foundry deployments}
@@ -20,4 +20,5 @@ Gem::Specification.new do |spec|
20
20
  spec.add_development_dependency "rake"
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rspec", "~> 2.13.0"
23
+ spec.add_development_dependency "fakeweb"
23
24
  end
@@ -1,11 +1,11 @@
1
1
  require "yaml"
2
-
3
2
  require "bosh/cloudfoundry"
4
3
 
5
4
  module Bosh::Cli::Command
6
5
  class CloudFoundry < Base
7
6
  include FileUtils
8
7
  include Bosh::Cli::Validation
8
+ include Bosh::Cloudfoundry
9
9
 
10
10
  usage "cf"
11
11
  desc "show micro cf sub-commands"
@@ -23,6 +23,7 @@ module Bosh::Cli::Command
23
23
  def prepare_cf
24
24
  auth_required
25
25
 
26
+ release_yml = Dir[File.join(bosh_release_dir, "releases", "*-#{latest_release_version}.yml")].first
26
27
  release_cmd(non_interactive: true).upload(release_yml)
27
28
  end
28
29
 
@@ -33,7 +34,13 @@ module Bosh::Cli::Command
33
34
  option "--name cf-<timestamp>", "Unique bosh deployment name"
34
35
  option "--disk 4096", Integer, "Size of persistent disk (Mb)"
35
36
  option "--security-group default", String, "Security group to assign to provisioned VMs"
37
+ option "--deployment-size medium", String, "Size of deployment - medium or large"
36
38
  def create_cf
39
+ auth_required
40
+ bosh_status # preload
41
+
42
+ setup_deployment_attributes
43
+
37
44
  ip_addresses = options[:ip]
38
45
  err("USAGE: bosh create cf --ip 1.2.3.4 -- please provide one IP address that will be bound to router.") if ip_addresses.blank?
39
46
  err("Only one IP address is supported currently. Please create an issue to mention you need more.") if ip_addresses.size > 1
@@ -43,25 +50,27 @@ module Bosh::Cli::Command
43
50
  err("USAGE: bosh create cf --dns mycloud.com -- please provide a base DNS that has a '*' A record referencing IPs") unless dns
44
51
  attrs.set(:dns, dns)
45
52
 
46
- auth_required
47
- bosh_status # preload
48
-
49
53
  attrs.set_unless_nil(:name, options[:name])
50
- attrs.set_unless_nil(:core_size, options[:core_size] || options[:size])
51
54
  attrs.set_unless_nil(:persistent_disk, options[:disk])
52
55
  attrs.set_unless_nil(:security_group, options[:security_group])
56
+ attrs.set_unless_nil(:common_password, options[:common_password])
57
+ attrs.set_unless_nil(:deployment_size, options[:deployment_size])
58
+
59
+ release_version = ReleaseVersion.latest_version_number
60
+ @release_version_cpi_size =
61
+ ReleaseVersionCpiSize.new(@release_version_cpi, attrs.deployment_size)
53
62
 
54
63
  nl
55
64
  say "CPI: #{bosh_cpi.make_green}"
56
65
  say "DNS mapping: #{attrs.validated_color(:dns)} --> #{attrs.validated_color(:ip_addresses)}"
57
66
  say "Deployment name: #{attrs.validated_color(:name)}"
58
- say "Resource size: #{attrs.validated_color(:core_size)}"
67
+ say "Deployment size: #{attrs.validated_color(:deployment_size)}"
59
68
  say "Persistent disk: #{attrs.validated_color(:persistent_disk)}"
60
69
  say "Security group: #{attrs.validated_color(:security_group)}"
61
70
  nl
62
71
 
63
- step("Validating resource size", "Resource size must be in #{attrs.available_resource_sizes.join(', ')}", :non_fatal) do
64
- attrs.validate(:core_size)
72
+ step("Validating deployment size", "Available deployment sizes are #{attrs.available_deployment_sizes.join(', ')}", :fatal) do
73
+ attrs.validate(:deployment_size)
65
74
  end
66
75
 
67
76
  unless confirmed?("Security group #{attrs.validated_color(:security_group)} exists with ports #{attrs.required_ports.join(", ")}")
@@ -73,53 +82,11 @@ module Bosh::Cli::Command
73
82
 
74
83
  raise Bosh::Cli::ValidationHalted unless errors.empty?
75
84
 
76
- # Create an initial deployment file; upon which the CPI-specific template will be applied below
77
- # Initial file will look like:
78
- # ---
79
- # name: NAME
80
- # director_uuid: 4ae3a0f0-70a5-4c0d-95f2-7fafaefe8b9e
81
- # releases:
82
- # - name: cf-release
83
- # version: 132
84
- # networks: {}
85
- # properties:
86
- # cf:
87
- # dns: mycloud.com
88
- # ip_addresses: ['1.2.3.4']
89
- # core_size: medium
90
- # security_group: cf
91
- # persistent_disk: 4096
92
- step("Checking/creating #{deployment_file_dir} for deployment files",
93
- "Failed to create #{deployment_file_dir} for deployment files", :fatal) do
94
- mkdir_p(deployment_file_dir)
95
- end
96
-
97
- step("Creating deployment file #{deployment_file}",
98
- "Failed to create deployment file #{deployment_file}", :fatal) do
99
- File.open(deployment_file, "w") do |file|
100
- file << {
101
- "name" => attrs.name,
102
- "director_uuid" => bosh_uuid,
103
- "releases" => {
104
- "name" => release_name,
105
- "version" => release_version
106
- },
107
- "networks" => {},
108
- "properties" => {
109
- attrs.properties_key => attrs.attributes_with_string_keys
110
- }
111
- }.to_yaml
112
- end
85
+ deployment_file = DeploymentFile.new(@release_version_cpi_size, attrs, bosh_status)
86
+ deployment_file.prepare_environment
87
+ deployment_file.create_deployment_file
88
+ deployment_file.deploy(options)
113
89
 
114
- stdout = Bosh::Cli::Config.output
115
- Bosh::Cli::Config.output = nil
116
- deployment_cmd(non_interactive: true).set_current(deployment_file)
117
- biff_cmd(non_interactive: true).biff(template_file)
118
- Bosh::Cli::Config.output = stdout
119
- end
120
- # re-set current deployment to show output
121
- deployment_cmd.set_current(deployment_file)
122
- deployment_cmd(non_interactive: options[:non_interactive]).perform
123
90
  rescue Bosh::Cli::ValidationHalted
124
91
  errors.each do |error|
125
92
  say error.make_red
@@ -129,23 +96,28 @@ module Bosh::Cli::Command
129
96
  usage "show cf passwords"
130
97
  desc "display the internal passwords for deployment"
131
98
  def show_cf_passwords
132
- load_deployment_into_attributes
99
+
100
+ setup_deployment_attributes
101
+ reconstruct_deployment_file
133
102
  say "Common password: #{attrs.validated_color(:common_password)}"
134
103
  end
135
104
 
136
105
  protected
137
- def load_deployment_into_attributes
138
- attrs.load_deployment_file(deployment)
106
+ def setup_deployment_attributes
107
+ @release_version_cpi = ReleaseVersionCpi.latest_for_cpi(bosh_cpi)
108
+ @deployment_attributes = DeploymentAttributes.new(director_client, bosh_status, @release_version_cpi)
139
109
  end
140
110
 
141
- def release_versioned_template
142
- @release_versioned_template ||= begin
143
- Bosh::Cloudfoundry::ReleaseVersionedTemplate.new(release_version, bosh_cpi, deployment_size)
144
- end
111
+ def attrs
112
+ @deployment_attributes
145
113
  end
146
114
 
147
- def template_file
148
- release_versioned_template.template_file_path
115
+ # After a deployment is created, the input properties/attributes are stored within the generated
116
+ # deployment file. Therefore, to update a deployment, first we must load in the attributes.
117
+ def reconstruct_deployment_file
118
+ @deployment_file = DeploymentFile.reconstruct_from_deployment_file(deployment, director_client, bosh_status)
119
+ @deployment_attributes = @deployment_file.deployment_attributes
120
+ @release_version_cpi_size = @deployment_file.release_version_cpi_size
149
121
  end
150
122
 
151
123
  def bosh_release_dir
@@ -173,73 +145,10 @@ module Bosh::Cli::Command
173
145
  latest_version
174
146
  end
175
147
 
176
- def release_yml
177
- @release_yml ||= begin
178
- Dir[File.join(bosh_release_dir, "releases", "*-#{latest_release_version}.yml")].first
179
- end
180
- end
181
-
182
- def attrs
183
- @deployment_attributes ||= begin
184
- klass = release_versioned_template.deployment_attributes_class
185
- klass.new(director_client, bosh_status, release_versioned_template)
186
- end
187
- end
188
-
189
- # TODO - determined by the release version (appcloud-131, cf-release-132, ...)
190
- def release_name
191
- "cf-release"
192
- end
193
-
194
- # TODO - support other release versions
195
- def release_version
196
- 132
197
- end
198
-
199
- # TODO - support other deployment sizes
200
- def deployment_size
201
- "dev"
202
- end
203
-
204
148
  def director_client
205
149
  director
206
150
  end
207
151
 
208
- def deployment_file
209
- File.join(deployment_file_dir, "#{attrs.name}.yml")
210
- end
211
-
212
- def deployment_file_dir
213
- File.expand_path("deployments/cf")
214
- end
215
-
216
- def deployment_cmd(options = {})
217
- cmd ||= Bosh::Cli::Command::Deployment.new
218
- options.each do |key, value|
219
- cmd.add_option key.to_sym, value
220
- end
221
- cmd
222
- end
223
-
224
- def release_cmd(options = {})
225
- cmd ||= Bosh::Cli::Command::Release.new
226
- options.each do |key, value|
227
- cmd.add_option key.to_sym, value
228
- end
229
- cmd
230
- end
231
-
232
- def biff
233
- @biff_cmd ||= Bosh::Cli::Command::Biff.new
234
- end
235
-
236
- def biff_cmd(options = {})
237
- options.each do |key, value|
238
- biff.add_option key.to_sym, value
239
- end
240
- biff
241
- end
242
-
243
152
  def bosh_status
244
153
  @bosh_status ||= begin
245
154
  step("Fetching bosh information", "Cannot fetch bosh information", :fatal) do
@@ -249,10 +158,6 @@ module Bosh::Cli::Command
249
158
  end
250
159
  end
251
160
 
252
- def bosh_uuid
253
- bosh_status["uuid"]
254
- end
255
-
256
161
  def bosh_cpi
257
162
  bosh_status["cpi"]
258
163
  end
@@ -1,4 +1,7 @@
1
1
  module Bosh; module Cloudfoundry; end; end
2
2
 
3
- require "bosh/cloudfoundry/release_versioned_template"
4
- require "bosh/cloudfoundry/deployment_attributes"
3
+ require "bosh/cloudfoundry/release_version"
4
+ require "bosh/cloudfoundry/release_version_cpi"
5
+ require "bosh/cloudfoundry/release_version_cpi_size"
6
+ require "bosh/cloudfoundry/deployment_attributes"
7
+ require "bosh/cloudfoundry/deployment_file"
@@ -6,13 +6,15 @@ module Bosh::Cloudfoundry
6
6
  include Bosh::Cli::Validation
7
7
 
8
8
  attr_reader :attributes
9
- def initialize(director_client, bosh_status, released_versioned_template, attributes = {})
9
+ attr_reader :released_version_cpi
10
+
11
+ def initialize(director_client, bosh_status, released_version_cpi, attributes = {})
10
12
  @director_client = director_client
11
13
  @bosh_status = bosh_status
12
- @released_versioned_template = released_versioned_template
14
+ @released_version_cpi = released_version_cpi
13
15
  @attributes = attributes
14
16
  @attributes[:name] ||= default_name
15
- @attributes[:core_size] ||= default_size
17
+ @attributes[:deployment_size] ||= default_deployment_size
16
18
  @attributes[:persistent_disk] ||= default_persistent_disk
17
19
  @attributes[:security_group] ||= default_security_group
18
20
  @attributes[:common_password] ||= random_string(12, :common)
@@ -22,8 +24,8 @@ module Bosh::Cloudfoundry
22
24
  @attributes[:name]
23
25
  end
24
26
 
25
- def core_size
26
- @attributes[:core_size]
27
+ def deployment_size
28
+ @attributes[:deployment_size]
27
29
  end
28
30
 
29
31
  def persistent_disk
@@ -35,11 +37,11 @@ module Bosh::Cloudfoundry
35
37
  end
36
38
 
37
39
  def ip_addresses
38
- @attribute[:ip_addresses]
40
+ @attributes[:ip_addresses]
39
41
  end
40
42
 
41
43
  def dns
42
- @attribute[:dns]
44
+ @attributes[:dns]
43
45
  end
44
46
 
45
47
  def set_unless_nil(attribute, value)
@@ -50,23 +52,12 @@ module Bosh::Cloudfoundry
50
52
  attributes[attribute.to_sym] = value if value
51
53
  end
52
54
 
53
- def load_deployment_file(deployment_file)
54
- deployment_obj = YAML.load_file(deployment_file)
55
- attributes = deployment_obj["properties"][properties_key]
56
- @attributes = attributes.inject({}) do |mem, key_value|
57
- k, v = key_value; mem[k.to_sym] = v; mem
58
- end
59
- end
60
-
61
- # attributes are stored within deployment file at properties.cf
62
- def properties_key
63
- "cf"
64
- end
65
-
66
55
  def validate(attribute)
67
56
  value = attributes[attribute.to_sym]
68
- if attribute.to_s =~ /size$/
69
- available_resource_sizes.include?(value)
57
+ if attribute.to_s == "deployment_size"
58
+ available_deployment_sizes.include?(value)
59
+ elsif attribute.to_s =~ /size$/
60
+ available_resources.include?(value)
70
61
  else
71
62
  true
72
63
  end
@@ -83,12 +74,25 @@ module Bosh::Cloudfoundry
83
74
  end
84
75
 
85
76
  # TODO move these validations into a "ValidatedSize" class or similar
86
- def available_resource_sizes
87
- resources = @released_versioned_template.spec["resources"]
88
- if resources && resources.is_a?(Array) && resources.first.is_a?(String)
89
- resources
90
- else
91
- err "template spec needs 'resources' key with list of resource pool names available"
77
+ def available_resources
78
+ @available_resources ||= begin
79
+ resources = released_version_cpi.spec["resources"]
80
+ if resources && resources.is_a?(Array) && resources.first.is_a?(String)
81
+ resources
82
+ else
83
+ err "template spec needs 'resources' key with list of resource pool names available; found #{released_version_cpi.spec.inspect}"
84
+ end
85
+ end
86
+ end
87
+
88
+ def available_deployment_sizes
89
+ @available_deployment_sizes ||= begin
90
+ deployment_sizes = released_version_cpi.spec["deployment_sizes"]
91
+ if deployment_sizes && deployment_sizes.is_a?(Array) && deployment_sizes.first.is_a?(String)
92
+ deployment_sizes
93
+ else
94
+ err "template spec needs 'deployment_sizes' key with list of deployment sizes names available; found #{deployment_sizes.spec.inspect}"
95
+ end
92
96
  end
93
97
  end
94
98
 
@@ -114,8 +118,9 @@ module Bosh::Cloudfoundry
114
118
  "cf-#{Time.now.to_i}"
115
119
  end
116
120
 
117
- def default_size
118
- "small"
121
+ # TODO change to small when its implemented
122
+ def default_deployment_size
123
+ "medium"
119
124
  end
120
125
 
121
126
  def default_persistent_disk
@@ -0,0 +1,192 @@
1
+ module Bosh::Cloudfoundry
2
+ # Prior to deploying (creating or updating or deleting) a bosh release we
3
+ # need a deployment file. This is created with this class +DeploymentFile+.
4
+ #
5
+ # The deployment file is a product of:
6
+ # * a release version/CPI/size (+ReleaseVersionCpiSize+) which provides a template; and
7
+ # * attributes (+DeploymentAttributes+) which populate the template
8
+ class DeploymentFile
9
+ include FileUtils
10
+ include Bosh::Cli::Validation
11
+
12
+ attr_reader :release_version_cpi_size
13
+ attr_reader :deployment_attributes
14
+ attr_reader :bosh_status
15
+
16
+ def initialize(release_version_cpi_size, deployment_attributes, bosh_status)
17
+ @release_version_cpi_size = release_version_cpi_size
18
+ @deployment_attributes = deployment_attributes
19
+ @bosh_status = bosh_status
20
+ end
21
+
22
+ def prepare_environment
23
+ step("Checking/creating #{deployment_file_dir} for deployment files",
24
+ "Failed to create #{deployment_file_dir} for deployment files", :fatal) do
25
+ mkdir_p(deployment_file_dir)
26
+ end
27
+ end
28
+
29
+ # Create an initial deployment file; upon which the CPI-specific template will be applied below
30
+ # Initial file will look like:
31
+ # ---
32
+ # name: NAME
33
+ # director_uuid: 4ae3a0f0-70a5-4c0d-95f2-7fafaefe8b9e
34
+ # releases:
35
+ # - name: cf-release
36
+ # version: 132
37
+ # networks: {}
38
+ # properties:
39
+ # cf:
40
+ # dns: mycloud.com
41
+ # ip_addresses: ['1.2.3.4']
42
+ # deployment_size: medium
43
+ # security_group: cf
44
+ # persistent_disk: 4096
45
+ #
46
+ # It is then merged with the corresponding template from +release_version_cpi_size+.
47
+ def create_deployment_file
48
+ step("Creating deployment file #{deployment_file}",
49
+ "Failed to create deployment file #{deployment_file}", :fatal) do
50
+ File.open(deployment_file, "w") do |file|
51
+ file << {
52
+ "name" => deployment_attributes.name,
53
+ "director_uuid" => bosh_uuid,
54
+ "releases" => {
55
+ "name" => release_name,
56
+ "version" => release_version_number
57
+ },
58
+ "networks" => {},
59
+ "properties" => {
60
+ self.class.properties_key => deployment_attributes.attributes_with_string_keys
61
+ }
62
+ }.to_yaml
63
+ end
64
+
65
+ quieten_output do
66
+ deployment_cmd(non_interactive: true).set_current(deployment_file)
67
+ biff_cmd(non_interactive: true).biff(template_file)
68
+ end
69
+ end
70
+ rescue Bosh::Cli::ValidationHalted
71
+ errors.each do |error|
72
+ say error.make_red
73
+ end
74
+ end
75
+
76
+ # Perform the create/update deployment described by this +DeploymentFile+
77
+ def deploy(options={})
78
+ # set current deployment to show the change in the output
79
+ deployment_cmd.set_current(deployment_file)
80
+ deployment_cmd(non_interactive: options[:non_interactive]).perform
81
+ end
82
+
83
+ # The trio of DeploymentFile, DeploymentAttributes & ReleaseVersionCpiSize can be
84
+ # reconstructed from a deployment file that was previously generated by this class.
85
+ #
86
+ # Specifically, it requires the deployment file to look like:
87
+ # ---
88
+ # name: NAME
89
+ # releases:
90
+ # - name: cf-release
91
+ # version: 132
92
+ # properties:
93
+ # cf:
94
+ # dns: mycloud.com
95
+ # ip_addresses: ['1.2.3.4']
96
+ # deployment_size: medium
97
+ # security_group: cf
98
+ # persistent_disk: 4096
99
+ def self.reconstruct_from_deployment_file(deployment_file_path, director_client, bosh_status)
100
+ deployment_file = YAML.load_file(deployment_file_path)
101
+ bosh_cpi = bosh_status["cpi"]
102
+
103
+ release = deployment_file["releases"].find do |release|
104
+ release["name"] == "cf" || release["name"] == "cf-release"
105
+ end
106
+ release_version = release["version"]
107
+ release_version_cpi = ReleaseVersionCpi.new(release_version, bosh_cpi)
108
+ deployment_size = deployment_file["properties"]["deployment_size"]
109
+ release_version_cpi_size = ReleaseVersionCpiSize.new(release_version_cpi, deployment_size)
110
+
111
+ attributes = deployment_file["properties"][properties_key]
112
+ # convert string keys to symbol keys
113
+ attributes = attributes.inject({}) do |mem, key_value|
114
+ k, v = key_value; mem[k.to_sym] = v; mem
115
+ end
116
+ deployment_attributes = DeploymentAttributes.new(director_client, bosh_status, release_version_cpi, attributes)
117
+
118
+ self.new(release_version_cpi_size, deployment_attributes, bosh_status)
119
+ end
120
+
121
+ def release_name
122
+ release_version_cpi_size.release_name
123
+ end
124
+
125
+ def release_version_number
126
+ release_version_cpi_size.release_version_number
127
+ end
128
+
129
+ def deployment_size
130
+ deployment_attributes.deployment_size
131
+ end
132
+
133
+ def deployment_file
134
+ File.join(deployment_file_dir, "#{deployment_attributes.name}.yml")
135
+ end
136
+
137
+ def deployment_file_dir
138
+ File.expand_path("deployments/cf")
139
+ end
140
+
141
+ def template_file
142
+ release_version_cpi_size.template_file_path
143
+ end
144
+
145
+ def deployment_cmd(options = {})
146
+ cmd ||= Bosh::Cli::Command::Deployment.new
147
+ options.each do |key, value|
148
+ cmd.add_option key.to_sym, value
149
+ end
150
+ cmd
151
+ end
152
+
153
+ def release_cmd(options = {})
154
+ cmd ||= Bosh::Cli::Command::Release.new
155
+ options.each do |key, value|
156
+ cmd.add_option key.to_sym, value
157
+ end
158
+ cmd
159
+ end
160
+
161
+ def biff
162
+ @biff_cmd ||= Bosh::Cli::Command::Biff.new
163
+ end
164
+
165
+ def biff_cmd(options = {})
166
+ options.each do |key, value|
167
+ biff.add_option key.to_sym, value
168
+ end
169
+ biff
170
+ end
171
+
172
+ def bosh_uuid
173
+ bosh_status["uuid"]
174
+ end
175
+
176
+ def bosh_cpi
177
+ bosh_status["cpi"]
178
+ end
179
+
180
+ # attributes are stored within deployment file at properties.cf
181
+ def self.properties_key
182
+ "cf"
183
+ end
184
+
185
+ def quieten_output(&block)
186
+ stdout = Bosh::Cli::Config.output
187
+ Bosh::Cli::Config.output = nil
188
+ yield
189
+ Bosh::Cli::Config.output = stdout
190
+ end
191
+ end
192
+ end