Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Refactor services support #139

Merged
merged 12 commits into from

2 participants

@drnic
Owner

After writing up the "add new services" docs #138 I am reminded of all the places I think the initial draft implementation can be improved.

Most of the functionality of service configuration and rendering is now in ServiceConfig class.

@drnic
Owner

@tpradeep here is the proposed refactoring of services mentioned in #138

@drnic drnic merged commit c303d6d into cloudfoundry-community:master
@tpradeep

By the time the sun rises here in India, you create a PR and merge it before I get a chance to read it :+1:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
80 docs/developer/add-new-services.md
@@ -66,13 +66,69 @@ In your manifest spec, you might want to include an extension to `@system_config
]
```
-Initially, the [SystemConfig](https://github.com/StarkAndWayne/bosh-cloudfoundry/blob/master/lib/bosh-cloudfoundry/config/system_config.rb) class (`@system_config`) does not have a `#mysql=` method. Find where postgresql/redis are defined and add your service name in that list.
+Initially, the [SystemConfig](https://github.com/StarkAndWayne/bosh-cloudfoundry/blob/master/lib/bosh-cloudfoundry/config/system_config.rb) class (`@system_config`) does not have a `#mysql=` method. Let's now implement support for the new service.
### Creating a service config class
For each of postgresql and redis there is a class that knows about its service's configuration, [PostgresqlServiceConfig](https://github.com/StarkAndWayne/bosh-cloudfoundry/blob/master/lib/bosh-cloudfoundry/config/postgresql_service_config.rb) & [RedisServiceConfig](https://github.com/StarkAndWayne/bosh-cloudfoundry/blob/master/lib/bosh-cloudfoundry/config/redis_service_config.rb), respectively.
-Create another one for your service, say `MysqlServiceConfig`.
+Create another one for your service, say `MysqlServiceConfig` as a subclass of [ServiceConfig](https://github.com/drnic/bosh-cloudfoundry/blob/master/lib/bosh-cloudfoundry/config/service_config.rb). Make it look something like:
+
+``` ruby
+# Copyright (c) 2012-2013 Stark & Wayne, LLC
+
+module Bosh; module CloudFoundry; module Config; end; end; end
+
+module Bosh::CloudFoundry::Config
+ class MysqlServiceConfig < ServiceConfig
+
+ # name that maps into the cf-release's jobs folder
+ # for postgresql_gateway and postgresql_node jobs
+ # also used as the key into SystemConfig manifest
+ def service_name
+ "mysql"
+ end
+
+ # Add extra configuration properties into the manifest
+ # for the gateway, node, and service plans
+ def merge_manifest_properties(manifest)
+ if any_service_nodes?
+ # TODO
+ end
+ end
+ end
+
+ SystemConfig.register_service_config(MysqlServiceConfig)
+end
+```
+
+Look at the other `ServiceConfig` subclasses for examples of what to put into the `merge_manifest_properties` method.
+
+### Hooking it up
+
+There is one step to hooking up your new class to make it fully integrated. Add the following line to the bottom of the [config.rb](https://github.com/drnic/bosh-cloudfoundry/blob/master/lib/bosh-cloudfoundry/config.rb) file:
+
+``` ruby
+require "bosh-cloudfoundry/config/mysql_service_config"
+```
+
+This will automatically register the new class with SystemConfig because of the call to `SystemConfig.register_service_config` at the end of the `mysql_service_config.rb` file above.
+
+### Tests should pass
+
+At this point, your tests should pass.
+
+If they don't then adjust your `merge_manifest_properties` method or perhaps you'll need to override more of the methods provided by `ServiceConfig`.
+
+### Using the service
+
+Now, when your new service should be available via the CLI:
+
+```
+$ bosh cf add service mysql
+```
+
+## Further explanations
The purpose of the `SystemConfig` class is two-fold:
@@ -94,22 +150,4 @@ During the building process, we delegate to each ServiceConfig object to modify
* additional jobs (method `add_jobs_to_manifest`); we want the additional resource pool servers to become mysql service nodes ([mysql_node](https://github.com/cloudfoundry/cf-release/tree/master/jobs/mysql_node))
* additional shared properties (method `merge_manifest_properties`); for example, to configure the service plans that the service nodes will support, such as "free", and what versions of the actual service (e.g. mysql 5.5) are running.
-You trigger these 4 methods by calling them from the [SystemDeploymentManifestRenderer#perform](https://github.com/StarkAndWayne/bosh-cloudfoundry/blob/master/lib/bosh-cloudfoundry/system_deployment_manifest_renderer.rb#L20) method.
-
-## Tests should pass
-
-At this point, your tests should pass.
-
-## Enable the service
-
-At this point, the CLI still will not allow the new service. Let's fix that.
-
-In the main CLI file, [cf.rb](https://github.com/StarkAndWayne/bosh-cloudfoundry/blob/master/lib/bosh/cli/commands/cf.rb), find the `#supported_services` method and add your new service name (e.g. `mysql`).
-
-Finally, map your service name to your `ServiceConfig` class in the `#service_config` method.
-
-Now, when your new service should be available via the CLI:
-
-```
-$ bosh cf add service mysql
-```
+The first three all have common implementations for all `ServiceConfig` subclasses. It is possible that your service may require already implementations. If so, then reimplement them in your subclass.
View
1  lib/bosh-cloudfoundry/config.rb
@@ -2,5 +2,6 @@
require "bosh-cloudfoundry/config/system_config"
require "bosh-cloudfoundry/config/microbosh_config"
require "bosh-cloudfoundry/config/dea_config"
+require "bosh-cloudfoundry/config/service_config"
require "bosh-cloudfoundry/config/postgresql_service_config"
require "bosh-cloudfoundry/config/redis_service_config"
View
7 lib/bosh-cloudfoundry/config/dea_config.rb
@@ -46,6 +46,13 @@ def save
@system_config.save
end
+ def build_into_manifest(manifest)
+ add_core_jobs_to_manifest(manifest)
+ add_resource_pools_to_manifest(manifest)
+ add_jobs_to_manifest(manifest)
+ merge_manifest_properties(manifest)
+ end
+
# Adds additional cf-release jobs into the core server (the core job in the manifest)
def add_core_jobs_to_manifest(manifest)
if dea_server_count == 0
View
210 lib/bosh-cloudfoundry/config/postgresql_service_config.rb
@@ -2,184 +2,50 @@
module Bosh; module CloudFoundry; module Config; end; end; end
-class Bosh::CloudFoundry::Config::PostgresqlServiceConfig
-
- def initialize(system_config)
- @system_config = system_config
- end
-
- def self.build_from_system_config(system_config)
- system_config.postgresql ||= []
- new(system_config)
- end
-
- def config
- @system_config.postgresql
- end
-
- # @return [Boolean] true if there are any postgresql nodes to be provisioned
- def any_service_nodes?
- total_service_nodes_count > 0
- end
-
- def total_service_nodes_count
- config.inject(0) { |total, cluster| total + (cluster["count"].to_i) }
- end
-
- def bosh_provider_name
- @system_config.bosh_provider
- end
-
- def update_cluster_count_for_flavor(server_count, server_flavor, server_plan="free")
- if cluster = find_cluster_for_flavor(server_flavor.to_s)
- cluster["count"] = server_count
- else
- config << {"count" => server_count, "flavor" => server_flavor.to_s, "plan" => server_plan}
- end
- self.save
- end
-
- # @return [Hash] the Hash from @system_config for the requested flavor
- # nil if its not currently a requested flavor
- def find_cluster_for_flavor(server_flavor)
- @system_config.postgresql.find { |cl| cl["flavor"] == server_flavor }
- end
-
- def save
- @system_config.save
- end
-
- # resource_pool name for a cluster
- # cluster_name like 'postgresql_m1_xlarge_free'
- def cluster_name(cluster)
- server_flavor = cluster["flavor"]
- server_plan = cluster["plan"] || "free"
- cluster_name = "postgresql_#{server_flavor}_#{server_plan}"
- cluster_name.gsub!(/\W+/, '_')
- cluster_name
- end
-
- # Adds "postgresql_gateway" to colocated "core" job
- def add_core_jobs_to_manifest(manifest)
- if any_service_nodes?
- @core_job ||= manifest["jobs"].find { |job| job["name"] == "core" }
- @core_job["template"] << "postgresql_gateway"
+module Bosh::CloudFoundry::Config
+ class PostgresqlServiceConfig < ServiceConfig
+
+ # name that maps into the cf-release's jobs folder
+ # for postgresql_gateway and postgresql_node jobs
+ # also used as the key into SystemConfig manifest
+ def service_name
+ "postgresql"
end
- end
- # Adds resource pools to the target manifest, if server_count > 0
- #
- # - name: postgresql
- # network: default
- # size: 2
- # stemcell:
- # name: bosh-stemcell
- # version: 0.7.0
- # cloud_properties:
- # instance_type: m1.xlarge
- def add_resource_pools_to_manifest(manifest)
- if any_service_nodes?
- config.each do |cluster|
- server_count = cluster["count"]
- server_flavor = cluster["flavor"]
- resource_pool = {
- "name" => cluster_name(cluster),
- "network" => "default",
- "size" => server_count,
- "stemcell" => {
- "name" => @system_config.stemcell_name,
- "version" => @system_config.stemcell_version
- },
- # TODO how to create "cloud_properties" per-provider?
- "cloud_properties" => {
- "instance_type" => server_flavor
- },
- "persistent_disk" => 16192
+ # Add extra configuration properties into the manifest
+ # for the gateway, node, and service plans
+ def merge_manifest_properties(manifest)
+ if any_service_nodes?
+ manifest["properties"]["postgresql_gateway"] = {
+ "admin_user"=>"psql_admin",
+ "admin_passwd_hash"=>nil,
+ "token"=>"TOKEN",
+ "supported_versions"=>["9.0"],
+ "version_aliases"=>{"current"=>"9.0"}
}
- manifest["resource_pools"] << resource_pool
- end
- end
- end
-
- # Jobs to add to the target manifest
- #
- # - name: postgresql
- # template:
- # - postgresql
- # instances: 2
- # resource_pool: postgresql
- # networks:
- # - name: default
- # default:
- # - dns
- # - gateway
- def add_jobs_to_manifest(manifest)
- if any_service_nodes?
- config.each do |cluster|
- server_count = cluster["count"]
- server_flavor = cluster["flavor"]
- job = {
- "name" => cluster_name(cluster),
- "template" => ["postgresql_node"],
- "instances" => server_count,
- "resource_pool" => cluster_name(cluster),
- # TODO are these AWS-specific networks?
- "networks" => [{
- "name" => "default",
- "default" => ["dns", "gateway"]
- }],
- "persistent_disk" => 16192
+ manifest["properties"]["postgresql_node"] = {
+ "admin_user"=>"psql_admin",
+ "admin_passwd_hash"=>nil,
+ "available_storage"=>2048,
+ "max_db_size"=>256,
+ "max_long_tx"=>30,
+ "supported_versions"=>["9.0"],
+ "default_version"=>"9.0"
+ }
+ manifest["properties"]["service_plans"]["postgresql"] = {
+ "free"=>
+ {"job_management"=>{"high_water"=>1400, "low_water"=>100},
+ "configuration"=>
+ {"capacity"=>200,
+ "max_db_size"=>128,
+ "max_long_query"=>3,
+ "max_long_tx"=>30,
+ "max_clients"=>20,
+ "backup"=>{"enable"=>true}}}
}
- manifest["jobs"] << job
end
end
end
- # Add extra configuration properties into the manifest
- # for the gateway, node, and service plans
- def merge_manifest_properties(manifest)
- if any_service_nodes?
- manifest["properties"]["postgresql_gateway"] = {
- "admin_user"=>"psql_admin",
- "admin_passwd_hash"=>nil,
- "token"=>"TOKEN",
- "supported_versions"=>["9.0"],
- "version_aliases"=>{"current"=>"9.0"}
- }
- manifest["properties"]["postgresql_node"] = {
- "admin_user"=>"psql_admin",
- "admin_passwd_hash"=>nil,
- "available_storage"=>2048,
- "max_db_size"=>256,
- "max_long_tx"=>30,
- "supported_versions"=>["9.0"],
- "default_version"=>"9.0"
- }
- manifest["properties"]["service_plans"]["postgresql"] = {
- "free"=>
- {"job_management"=>{"high_water"=>1400, "low_water"=>100},
- "configuration"=>
- {"capacity"=>200,
- "max_db_size"=>128,
- "max_long_query"=>3,
- "max_long_tx"=>30,
- "max_clients"=>20,
- "backup"=>{"enable"=>true}}}
- }
- end
- end
-
- # @return [Integer] the ballpark ram for postgresql, BOSH agent, etc
- def preallocated_ram
- 300
- end
-
- def ram_for_server_flavor
- provider.ram_for_server_flavor(server_flavor)
- end
-
- # a helper object for the target BOSH provider
- def provider
- @provider ||= Bosh::CloudFoundry::Providers.for_bosh_provider_name(system_config)
- end
+ SystemConfig.register_service_config(PostgresqlServiceConfig)
end
View
197 lib/bosh-cloudfoundry/config/redis_service_config.rb
@@ -2,178 +2,43 @@
module Bosh; module CloudFoundry; module Config; end; end; end
-class Bosh::CloudFoundry::Config::RedisServiceConfig
-
- def initialize(system_config)
- @system_config = system_config
- end
-
- def self.build_from_system_config(system_config)
- system_config.redis ||= []
- new(system_config)
- end
-
- def config
- @system_config.redis
- end
-
- # @return [Boolean] true if there are any redis nodes to be provisioned
- def any_service_nodes?
- total_service_nodes_count > 0
- end
-
- def total_service_nodes_count
- config.inject(0) { |total, cluster| total + (cluster["count"].to_i) }
- end
-
- def bosh_provider_name
- @system_config.bosh_provider
- end
-
- # Used by the CLI cf.rb to update +system_config+
- def update_cluster_count_for_flavor(server_count, server_flavor, server_plan="free")
- if cluster = find_cluster_for_flavor(server_flavor.to_s)
- cluster["count"] = server_count
- else
- config << {"count" => server_count, "flavor" => server_flavor.to_s, "plan" => server_plan}
- end
- self.save
- end
-
- # @return [Hash] the Hash from @system_config for the requested flavor
- # nil if its not currently a requested flavor
- def find_cluster_for_flavor(server_flavor)
- @system_config.redis.find { |cl| cl["flavor"] == server_flavor }
- end
-
- def save
- @system_config.save
- end
-
- # resource_pool name for a cluster
- # cluster_name like 'redis_m1_xlarge_free'
- def cluster_name(cluster)
- server_flavor = cluster["flavor"]
- server_plan = cluster["plan"] || "free"
- cluster_name = "redis_#{server_flavor}_#{server_plan}"
- cluster_name.gsub!(/\W+/, '_')
- cluster_name
- end
-
- # Adds "redis_gateway" to colocated "core" job
- def add_core_jobs_to_manifest(manifest)
- if any_service_nodes?
- @core_job ||= manifest["jobs"].find { |job| job["name"] == "core" }
- @core_job["template"] << "redis_gateway"
+module Bosh::CloudFoundry::Config
+ class RedisServiceConfig < ServiceConfig
+
+ # name that maps into the cf-release's jobs folder
+ # for redis_gateway and redis_node jobs
+ # also used as the key into SystemConfig manifest
+ def service_name
+ "redis"
end
- end
- # Adds resource pools to the target manifest, if server_count > 0
- #
- # - name: redis
- # network: default
- # size: 2
- # stemcell:
- # name: bosh-stemcell
- # version: 0.7.0
- # cloud_properties:
- # instance_type: m1.xlarge
- def add_resource_pools_to_manifest(manifest)
- if any_service_nodes?
- config.each do |cluster|
- server_count = cluster["count"]
- server_flavor = cluster["flavor"]
- resource_pool = {
- "name" => cluster_name(cluster),
- "network" => "default",
- "size" => server_count,
- "stemcell" => {
- "name" => @system_config.stemcell_name,
- "version" => @system_config.stemcell_version
- },
- # TODO how to create "cloud_properties" per-provider?
- "cloud_properties" => {
- "instance_type" => server_flavor
- },
- "persistent_disk" => @system_config.common_persistent_disk
+ # Add extra configuration properties into the manifest
+ # for the gateway, node, and service plans
+ def merge_manifest_properties(manifest)
+ if any_service_nodes?
+ manifest["properties"]["redis_gateway"] = {
+ "token"=>"TOKEN",
+ "supported_versions"=>["2.2"],
+ "version_aliases"=>{"current"=>"2.2"}
}
- manifest["resource_pools"] << resource_pool
- end
- end
- end
-
- # Jobs to add to the target manifest
- #
- # - name: redis
- # template:
- # - redis
- # instances: 2
- # resource_pool: redis
- # networks:
- # - name: default
- # default:
- # - dns
- # - gateway
- def add_jobs_to_manifest(manifest)
- if any_service_nodes?
- config.each do |cluster|
- server_count = cluster["count"]
- server_flavor = cluster["flavor"]
- job = {
- "name" => cluster_name(cluster),
- "template" => ["redis_node"],
- "instances" => server_count,
- "resource_pool" => cluster_name(cluster),
- # TODO are these AWS-specific networks?
- "networks" => [{
- "name" => "default",
- "default" => ["dns", "gateway"]
- }],
- "persistent_disk" => @system_config.common_persistent_disk
+ manifest["properties"]["redis_node"] = {
+ "available_memory"=>256,
+ "supported_versions"=>["2.2"],
+ "default_version"=>"2.2"
+ }
+ manifest["properties"]["service_plans"]["redis"] = {
+ "free"=>
+ {"job_management"=>{"high_water"=>1400, "low_water"=>100},
+ "configuration"=>
+ {"capacity"=>200,
+ "max_memory"=>16,
+ "max_swap"=>32,
+ "max_clients"=>500,
+ "backup"=>{"enable"=>true}}}
}
- manifest["jobs"] << job
end
end
end
- # Add extra configuration properties into the manifest
- # for the gateway, node, and service plans
- def merge_manifest_properties(manifest)
- if any_service_nodes?
- manifest["properties"]["redis_gateway"] = {
- "token"=>"TOKEN",
- "supported_versions"=>["2.2"],
- "version_aliases"=>{"current"=>"2.2"}
- }
- manifest["properties"]["redis_node"] = {
- "available_memory"=>256,
- "supported_versions"=>["2.2"],
- "default_version"=>"2.2"
- }
- manifest["properties"]["service_plans"]["redis"] = {
- "free"=>
- {"job_management"=>{"high_water"=>1400, "low_water"=>100},
- "configuration"=>
- {"capacity"=>200,
- "max_memory"=>16,
- "max_swap"=>32,
- "max_clients"=>500,
- "backup"=>{"enable"=>true}}}
- }
- end
- end
-
- # @return [Integer] the ballpark ram for redis, BOSH agent, etc
- def preallocated_ram
- 300
- end
-
- def ram_for_server_flavor
- provider.ram_for_server_flavor(server_flavor)
- end
-
- # a helper object for the target BOSH provider
- def provider
- @provider ||= Bosh::CloudFoundry::Providers.for_bosh_provider_name(system_config)
- end
+ SystemConfig.register_service_config(RedisServiceConfig)
end
View
175 lib/bosh-cloudfoundry/config/service_config.rb
@@ -0,0 +1,175 @@
+# Copyright (c) 2012-2013 Stark & Wayne, LLC
+
+module Bosh; module CloudFoundry; module Config; end; end; end
+
+class Bosh::CloudFoundry::Config::ServiceConfig
+ attr_reader :system_config
+
+ def initialize(system_config)
+ @system_config = system_config
+ end
+
+ def self.build_from_system_config(system_config)
+ new(system_config)
+ end
+
+ # name that maps into the cf-release's jobs folder
+ # for xyz_gateway and xyz_node jobs
+ def service_name
+ raise "please implement #service_name in your subclass #{self.class}"
+ end
+
+ # the subset of SystemConfig that describes this ServiceConfig;
+ # by default, assume its in a key of the +service_name+
+ def config
+ system_config.send(service_name.to_sym) || []
+ end
+
+ def bosh_provider_name
+ system_config.bosh_provider
+ end
+
+ def job_gateway_name
+ "#{service_name}_gateway"
+ end
+
+ def job_node_name
+ "#{service_name}_node"
+ end
+
+ # resource_pool name for a cluster
+ # cluster_name like 'redis_m1_xlarge_free'
+ def cluster_name(cluster)
+ server_flavor = cluster["flavor"]
+ server_plan = cluster["plan"] || "free"
+ cluster_name = "#{service_name}_#{server_flavor}_#{server_plan}"
+ cluster_name.gsub!(/\W+/, '_')
+ cluster_name
+ end
+
+ # @return [Boolean] true if there are any postgresql nodes to be provisioned
+ def any_service_nodes?
+ total_service_nodes_count > 0
+ end
+
+ def total_service_nodes_count
+ config.inject(0) { |total, cluster| total + (cluster["count"].to_i) }
+ end
+
+ def update_cluster_count_for_flavor(server_count, server_flavor, server_plan="free")
+ if cluster = find_cluster_for_flavor(server_flavor.to_s)
+ cluster["count"] = server_count
+ else
+ config << {"count" => server_count, "flavor" => server_flavor.to_s, "plan" => server_plan}
+ end
+ self.save
+ end
+
+ # @return [Hash] the Hash from system_config for the requested flavor
+ # nil if its not currently a requested flavor
+ def find_cluster_for_flavor(server_flavor)
+ config.find { |cl| cl["flavor"] == server_flavor }
+ end
+
+ def save
+ system_config.save
+ end
+
+ # @return [Integer] the ballpark ram for redis, BOSH agent, etc
+ def preallocated_ram
+ 300
+ end
+
+ def ram_for_server_flavor
+ provider.ram_for_server_flavor(server_flavor)
+ end
+
+ # a helper object for the target BOSH provider
+ def provider
+ @provider ||= Bosh::CloudFoundry::Providers.for_bosh_provider_name(system_config)
+ end
+
+ def build_into_manifest(manifest)
+ add_core_jobs_to_manifest(manifest)
+ add_resource_pools_to_manifest(manifest)
+ add_jobs_to_manifest(manifest)
+ merge_manifest_properties(manifest)
+ end
+
+ # Adds "redis_gateway" to colocated "core" job
+ def add_core_jobs_to_manifest(manifest)
+ if any_service_nodes?
+ @core_job ||= manifest["jobs"].find { |job| job["name"] == "core" }
+ @core_job["template"] << job_gateway_name
+ end
+ end
+
+ # Adds resource pools to the target manifest, if server_count > 0
+ #
+ # - name: redis
+ # network: default
+ # size: 2
+ # stemcell:
+ # name: bosh-stemcell
+ # version: 0.7.0
+ # cloud_properties:
+ # instance_type: m1.xlarge
+ def add_resource_pools_to_manifest(manifest)
+ if any_service_nodes?
+ config.each do |cluster|
+ server_count = cluster["count"]
+ server_flavor = cluster["flavor"]
+ resource_pool = {
+ "name" => cluster_name(cluster),
+ "network" => "default",
+ "size" => server_count,
+ "stemcell" => {
+ "name" => system_config.stemcell_name,
+ "version" => system_config.stemcell_version
+ },
+ # TODO how to create "cloud_properties" per-provider?
+ "cloud_properties" => {
+ "instance_type" => server_flavor
+ },
+ "persistent_disk" => system_config.common_persistent_disk
+ }
+ manifest["resource_pools"] << resource_pool
+ end
+ end
+ end
+
+ # Jobs to add to the target manifest
+ #
+ # - name: redis
+ # template:
+ # - redis
+ # instances: 2
+ # resource_pool: redis
+ # networks:
+ # - name: default
+ # default:
+ # - dns
+ # - gateway
+ def add_jobs_to_manifest(manifest)
+ if any_service_nodes?
+ config.each do |cluster|
+ server_count = cluster["count"]
+ server_flavor = cluster["flavor"]
+ job = {
+ "name" => cluster_name(cluster),
+ "template" => [job_node_name],
+ "instances" => server_count,
+ "resource_pool" => cluster_name(cluster),
+ # TODO are these AWS-specific networks?
+ "networks" => [{
+ "name" => "default",
+ "default" => ["dns", "gateway"]
+ }],
+ "persistent_disk" => system_config.common_persistent_disk
+ }
+ manifest["jobs"] << job
+ end
+ end
+ end
+
+end
View
70 lib/bosh-cloudfoundry/config/system_config.rb
@@ -17,8 +17,21 @@ def initialize(system_dir)
super(config_file, system_dir)
self.system_dir = system_dir
self.system_name = File.basename(system_dir)
+ setup_services
end
+ def self.create_config_accessor(attr)
+ define_method attr do
+ read(attr, false)
+ end
+
+ define_method "#{attr}=" do |value|
+ write_global(attr, value)
+ end
+ end
+
+ # Accessors for access to config manifest
+ # Additional accessors are created for each service, such as redis/redis= & postgresql/postgresql=
[
:bosh_target, # e.g. http://1.2.3.4:25555
:bosh_target_uuid,
@@ -43,19 +56,10 @@ def initialize(system_dir)
:common_persistent_disk, # e.g. 16192 (integer in Mb)
:admin_emails, # e.g. ['drnic@starkandwayne.com']
:dea, # e.g. { "count" => 2, "flavor" => "m1.large" }
- :postgresql, # e.g. [{ "count" => 2, "flavor" => "m1.large", "plan" => "free" }]
- :redis, # e.g. [{ "count" => 2, "flavor" => "m1.large", "plan" => "free" }]
:security_group, # e.g. "cloudfoundry-production"
+ :available_services, # e.g. ['redis']; restricts supported_services; default - all supported service
:system_initialized, # e.g. true / false
- ].each do |attr|
- define_method attr do
- read(attr, false)
- end
-
- define_method "#{attr}=" do |value|
- write_global(attr, value)
- end
- end
+ ].each { |attr| create_config_accessor(attr) }
def microbosh
unless bosh_target
@@ -63,4 +67,48 @@ def microbosh
end
@microbosh ||= Bosh::CloudFoundry::Config::MicroboshConfig.new(bosh_target)
end
+
+ def self.register_service_config(service_config_class)
+ @service_classes ||= []
+ @service_classes << service_config_class
+ end
+
+ def self.service_classes
+ @service_classes
+ end
+
+ def service_classes
+ self.class.service_classes
+ end
+
+ def setup_services
+ @services_by_name = {}
+ service_classes.each do |service_class|
+ service = service_class.build_from_system_config(self)
+ service_name = service.service_name
+ self.class.create_config_accessor(service_name)
+ self.send("#{service_name}=", [])
+ @services_by_name[service_name] = service
+ end
+ end
+
+ def supported_services
+ if available_services.is_a?(Array) && available_services.first.is_a?(String)
+ available_services
+ end
+ if available_services
+ puts "IGNORING 'available_services' configuration: must be an array of service names"
+ end
+ @services_by_name.keys
+ end
+
+ def services
+ @services_by_name.values
+ end
+
+ def service(service_name)
+ @services_by_name[service_name] ||
+ raise("please add #{service_name} support to SystemConfig#service method")
+ end
+
end
View
18 lib/bosh-cloudfoundry/system_deployment_manifest_renderer.rb
@@ -40,20 +40,10 @@ def perform
system_config.security_group
)
- dea_config.add_core_jobs_to_manifest(manifest)
- dea_config.add_resource_pools_to_manifest(manifest)
- dea_config.add_jobs_to_manifest(manifest)
- dea_config.merge_manifest_properties(manifest)
-
- postgresql_service_config.add_core_jobs_to_manifest(manifest)
- postgresql_service_config.add_resource_pools_to_manifest(manifest)
- postgresql_service_config.add_jobs_to_manifest(manifest)
- postgresql_service_config.merge_manifest_properties(manifest)
-
- redis_service_config.add_core_jobs_to_manifest(manifest)
- redis_service_config.add_resource_pools_to_manifest(manifest)
- redis_service_config.add_jobs_to_manifest(manifest)
- redis_service_config.merge_manifest_properties(manifest)
+ dea_config.build_into_manifest(manifest)
+ system_config.services.each do |service_config|
+ service_config.build_into_manifest(manifest)
+ end
chdir system_config.system_dir do
mkdir_p("deployments")
View
11 lib/bosh/cli/commands/cf.rb
@@ -571,18 +571,11 @@ def validate_service_name(service_name)
end
def supported_services
- %w[postgresql redis]
+ system_config.supported_services
end
def service_config(service_name)
- case service_name.to_sym
- when :postgresql
- Bosh::CloudFoundry::Config::PostgresqlServiceConfig.build_from_system_config(system_config)
- when :redis
- Bosh::CloudFoundry::Config::RedisServiceConfig.build_from_system_config(system_config)
- else
- raise "please add #{service_name} support to #service_config method"
- end
+ system_config.service(service_name)
end
def default_core_server_flavor
View
14 spec/unit/cf_command_spec.rb
@@ -239,6 +239,7 @@ def generate_new_system(cmd = nil)
@cmd.add_option(:flavor, 'm1.large')
@cmd.add_service_node("postgresql", 4)
+ @cmd.system_config.postgresql.should_not be_nil
@cmd.system_config.postgresql.size.should == 1
postgresql_config = @cmd.system_config.postgresql.first
postgresql_config["flavor"].should == "m1.large"
@@ -255,6 +256,7 @@ def generate_new_system(cmd = nil)
@cmd.add_option(:flavor, 'm1.large')
@cmd.add_service_node("redis", 2)
+ @cmd.system_config.redis.should_not be_nil
@cmd.system_config.redis.size.should == 1
redis_config = @cmd.system_config.redis.first
redis_config["flavor"].should == "m1.large"
@@ -303,5 +305,17 @@ def generate_new_system(cmd = nil)
@cmd.bosh_release_versions("appcloud-dev").should == ["124.1-dev", "126.1-dev"]
@cmd.bosh_release_versions("XXX").should == []
end
+
+ it "supports specific services" do
+ generate_new_system
+ @cmd.supported_services.should == %w[postgresql redis]
+ end
+
+ it "can access the ServiceConfig for a supported service" do
+ generate_new_system
+ service_config = @cmd.service_config("redis")
+ service_config.should_not be_nil
+ service_config.class.should == Bosh::CloudFoundry::Config::RedisServiceConfig
+ end
end
end
Something went wrong with that request. Please try again.