bosh-cloudfoundry 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +6 -0
- data/Guardfile +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +242 -0
- data/Rakefile +33 -0
- data/bosh-cloudfoundry.gemspec +29 -0
- data/config/defaults.yml +6 -0
- data/lib/bosh-cloudfoundry.rb +34 -0
- data/lib/bosh-cloudfoundry/bosh_release_manager.rb +141 -0
- data/lib/bosh-cloudfoundry/config.rb +6 -0
- data/lib/bosh-cloudfoundry/config/common_config.rb +27 -0
- data/lib/bosh-cloudfoundry/config/dea_config.rb +150 -0
- data/lib/bosh-cloudfoundry/config/microbosh_config.rb +106 -0
- data/lib/bosh-cloudfoundry/config/postgresql_service_config.rb +185 -0
- data/lib/bosh-cloudfoundry/config/redis_service_config.rb +179 -0
- data/lib/bosh-cloudfoundry/config/system_config.rb +60 -0
- data/lib/bosh-cloudfoundry/config_options.rb +362 -0
- data/lib/bosh-cloudfoundry/gerrit_patches_helper.rb +47 -0
- data/lib/bosh-cloudfoundry/providers.rb +19 -0
- data/lib/bosh-cloudfoundry/providers/aws.rb +75 -0
- data/lib/bosh-cloudfoundry/system_deployment_manifest_renderer.rb +286 -0
- data/lib/bosh-cloudfoundry/version.rb +5 -0
- data/lib/bosh/cli/commands/cf.rb +668 -0
- data/spec/assets/.gitkeep +0 -0
- data/spec/assets/cf-release/jobs/cloud_controller/templates/runtimes.yml +150 -0
- data/spec/assets/deployments/aws-core-1-m1.small-free-redis.yml +221 -0
- data/spec/assets/deployments/aws-core-1-m1.xlarge-free-postgresql-2-m1.small-free-postgresql.yml +248 -0
- data/spec/assets/deployments/aws-core-2-m1.xlarge-dea.yml +195 -0
- data/spec/assets/deployments/aws-core-only.yml +178 -0
- data/spec/assets/deployments/aws-core-with-nfs.yml +192 -0
- data/spec/functional/.gitkeep +0 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/unit/.gitkeep +0 -0
- data/spec/unit/bosh_release_manager_spec.rb +36 -0
- data/spec/unit/cf_command_spec.rb +280 -0
- data/spec/unit/config/common_config_spec.rb +21 -0
- data/spec/unit/config/dea_config_spec.rb +92 -0
- data/spec/unit/config/microbosh_config_spec.rb +11 -0
- data/spec/unit/config/postgresql_service_config_spec.rb +103 -0
- data/spec/unit/config/redis_service_config_spec.rb +103 -0
- data/spec/unit/config/system_config_spec.rb +29 -0
- data/spec/unit/config_options_spec.rb +64 -0
- data/spec/unit/system_deployment_manifest_renderer_spec.rb +93 -0
- metadata +246 -0
@@ -0,0 +1,179 @@
|
|
1
|
+
# Copyright (c) 2012-2013 Stark & Wayne, LLC
|
2
|
+
|
3
|
+
module Bosh; module CloudFoundry; module Config; end; end; end
|
4
|
+
|
5
|
+
class Bosh::CloudFoundry::Config::RedisServiceConfig
|
6
|
+
|
7
|
+
def initialize(system_config)
|
8
|
+
@system_config = system_config
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.build_from_system_config(system_config)
|
12
|
+
system_config.redis ||= []
|
13
|
+
new(system_config)
|
14
|
+
end
|
15
|
+
|
16
|
+
def config
|
17
|
+
@system_config.redis
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Boolean] true if there are any redis nodes to be provisioned
|
21
|
+
def any_service_nodes?
|
22
|
+
total_service_nodes_count > 0
|
23
|
+
end
|
24
|
+
|
25
|
+
def total_service_nodes_count
|
26
|
+
config.inject(0) { |total, cluster| total + (cluster["count"].to_i) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def bosh_provider_name
|
30
|
+
@system_config.bosh_provider
|
31
|
+
end
|
32
|
+
|
33
|
+
# Used by the CLI cf.rb to update +system_config+
|
34
|
+
def update_cluster_count_for_flavor(server_count, server_flavor, server_plan="free")
|
35
|
+
if cluster = find_cluster_for_flavor(server_flavor.to_s)
|
36
|
+
cluster["count"] = server_count
|
37
|
+
else
|
38
|
+
config << {"count" => server_count, "flavor" => server_flavor.to_s, "plan" => server_plan}
|
39
|
+
end
|
40
|
+
self.save
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [Hash] the Hash from @system_config for the requested flavor
|
44
|
+
# nil if its not currently a requested flavor
|
45
|
+
def find_cluster_for_flavor(server_flavor)
|
46
|
+
@system_config.redis.find { |cl| cl["flavor"] == server_flavor }
|
47
|
+
end
|
48
|
+
|
49
|
+
def save
|
50
|
+
@system_config.save
|
51
|
+
end
|
52
|
+
|
53
|
+
# resource_pool name for a cluster
|
54
|
+
# cluster_name like 'redis_m1_xlarge_free'
|
55
|
+
def cluster_name(cluster)
|
56
|
+
server_flavor = cluster["flavor"]
|
57
|
+
server_plan = cluster["plan"] || "free"
|
58
|
+
cluster_name = "redis_#{server_flavor}_#{server_plan}"
|
59
|
+
cluster_name.gsub!(/\W+/, '_')
|
60
|
+
cluster_name
|
61
|
+
end
|
62
|
+
|
63
|
+
# Adds "redis_gateway" to colocated "core" job
|
64
|
+
def add_core_jobs_to_manifest(manifest)
|
65
|
+
if any_service_nodes?
|
66
|
+
@core_job ||= manifest["jobs"].find { |job| job["name"] == "core" }
|
67
|
+
@core_job["template"] << "redis_gateway"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Adds resource pools to the target manifest, if server_count > 0
|
72
|
+
#
|
73
|
+
# - name: redis
|
74
|
+
# network: default
|
75
|
+
# size: 2
|
76
|
+
# stemcell:
|
77
|
+
# name: bosh-stemcell
|
78
|
+
# version: 0.6.4
|
79
|
+
# cloud_properties:
|
80
|
+
# instance_type: m1.xlarge
|
81
|
+
def add_resource_pools_to_manifest(manifest)
|
82
|
+
if any_service_nodes?
|
83
|
+
config.each do |cluster|
|
84
|
+
server_count = cluster["count"]
|
85
|
+
server_flavor = cluster["flavor"]
|
86
|
+
resource_pool = {
|
87
|
+
"name" => cluster_name(cluster),
|
88
|
+
"network" => "default",
|
89
|
+
"size" => server_count,
|
90
|
+
"stemcell" => {
|
91
|
+
"name" => @system_config.stemcell_name,
|
92
|
+
"version" => @system_config.stemcell_version
|
93
|
+
},
|
94
|
+
# TODO how to create "cloud_properties" per-provider?
|
95
|
+
"cloud_properties" => {
|
96
|
+
"instance_type" => server_flavor
|
97
|
+
},
|
98
|
+
"persistent_disk" => @system_config.common_persistent_disk
|
99
|
+
}
|
100
|
+
manifest["resource_pools"] << resource_pool
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Jobs to add to the target manifest
|
106
|
+
#
|
107
|
+
# - name: redis
|
108
|
+
# template:
|
109
|
+
# - redis
|
110
|
+
# instances: 2
|
111
|
+
# resource_pool: redis
|
112
|
+
# networks:
|
113
|
+
# - name: default
|
114
|
+
# default:
|
115
|
+
# - dns
|
116
|
+
# - gateway
|
117
|
+
def add_jobs_to_manifest(manifest)
|
118
|
+
if any_service_nodes?
|
119
|
+
config.each do |cluster|
|
120
|
+
server_count = cluster["count"]
|
121
|
+
server_flavor = cluster["flavor"]
|
122
|
+
job = {
|
123
|
+
"name" => cluster_name(cluster),
|
124
|
+
"template" => ["redis_node"],
|
125
|
+
"instances" => server_count,
|
126
|
+
"resource_pool" => cluster_name(cluster),
|
127
|
+
# TODO are these AWS-specific networks?
|
128
|
+
"networks" => [{
|
129
|
+
"name" => "default",
|
130
|
+
"default" => ["dns", "gateway"]
|
131
|
+
}],
|
132
|
+
"persistent_disk" => @system_config.common_persistent_disk
|
133
|
+
}
|
134
|
+
manifest["jobs"] << job
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Add extra configuration properties into the manifest
|
140
|
+
# for the gateway, node, and service plans
|
141
|
+
def merge_manifest_properties(manifest)
|
142
|
+
if any_service_nodes?
|
143
|
+
manifest["properties"]["redis_gateway"] = {
|
144
|
+
"token"=>"TOKEN",
|
145
|
+
"supported_versions"=>["2.2"],
|
146
|
+
"version_aliases"=>{"current"=>"2.2"}
|
147
|
+
}
|
148
|
+
manifest["properties"]["redis_node"] = {
|
149
|
+
"available_memory"=>256,
|
150
|
+
"supported_versions"=>["2.2"],
|
151
|
+
"default_version"=>"2.2"
|
152
|
+
}
|
153
|
+
manifest["properties"]["service_plans"]["redis"] = {
|
154
|
+
"free"=>
|
155
|
+
{"job_management"=>{"high_water"=>1400, "low_water"=>100},
|
156
|
+
"configuration"=>
|
157
|
+
{"capacity"=>200,
|
158
|
+
"max_memory"=>16,
|
159
|
+
"max_swap"=>32,
|
160
|
+
"max_clients"=>500,
|
161
|
+
"backup"=>{"enable"=>true}}}
|
162
|
+
}
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# @return [Integer] the ballpark ram for redis, BOSH agent, etc
|
167
|
+
def preallocated_ram
|
168
|
+
300
|
169
|
+
end
|
170
|
+
|
171
|
+
def ram_for_server_flavor
|
172
|
+
provider.ram_for_server_flavor(server_flavor)
|
173
|
+
end
|
174
|
+
|
175
|
+
# a helper object for the target BOSH provider
|
176
|
+
def provider
|
177
|
+
@provider ||= Bosh::CloudFoundry::Providers.for_bosh_provider_name(system_config)
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Copyright (c) 2012-2013 Stark & Wayne, LLC
|
2
|
+
|
3
|
+
module Bosh; module CloudFoundry; module Config; end; end; end
|
4
|
+
|
5
|
+
# Model for the configuration data of a CloudFoundry System
|
6
|
+
# description.
|
7
|
+
# Stores the data as a YAML configuration file within a System's
|
8
|
+
# home folder.
|
9
|
+
class Bosh::CloudFoundry::Config::SystemConfig < Bosh::Cli::Config
|
10
|
+
|
11
|
+
# Defaults the +system_dir+ and +system_name+ based on the path
|
12
|
+
# of the +config_file+.
|
13
|
+
# It is assumed that the +config_file+ is located within a folder
|
14
|
+
# dedicated to the System begin configured.
|
15
|
+
def initialize(system_dir)
|
16
|
+
config_file = File.join(system_dir, "manifest.yml")
|
17
|
+
super(config_file, system_dir)
|
18
|
+
self.system_dir = system_dir
|
19
|
+
self.system_name = File.basename(system_dir)
|
20
|
+
end
|
21
|
+
|
22
|
+
[
|
23
|
+
:bosh_target, # e.g. http://1.2.3.4:25555
|
24
|
+
:bosh_target_uuid,
|
25
|
+
:bosh_provider, # from list 'aws', 'openstack', 'vsphere', 'vcloud'
|
26
|
+
:system_name, # e.g. production
|
27
|
+
:system_dir, # e.g. /var/vcap/store/systems/production
|
28
|
+
:release_name, # e.g. 'appcloud'
|
29
|
+
:release_version, # e.g. 'latest'
|
30
|
+
:gerrit_changes, # e.g. ['84/13084/4', '37/13137/4']
|
31
|
+
:stemcell_name, # e.g. 'bosh-stemcell'
|
32
|
+
:stemcell_version, # e.g. '0.6.7'
|
33
|
+
:core_ip, # Static IP for Core CF server (router, cc) e.g. '1.2.3.4'
|
34
|
+
:root_dns, # Root DNS for cc & user apps, e.g. 'mycompanycloud.com'
|
35
|
+
:core_server_flavor, # Server size for CF Core; e.g. 'm1.xlarge' on AWS
|
36
|
+
:runtimes, # e.g. { "ruby18" => false, "ruby19" => true }
|
37
|
+
:common_password, # e.g. 'c1oudc0wc1oudc0w` - must be 16 chars for CC password
|
38
|
+
:common_persistent_disk, # e.g. 16192 (integer in Mb)
|
39
|
+
:admin_emails, # e.g. ['drnic@starkandwayne.com']
|
40
|
+
:dea, # e.g. { "count" => 2, "flavor" => "m1.large" }
|
41
|
+
:postgresql, # e.g. [{ "count" => 2, "flavor" => "m1.large", "plan" => "free" }]
|
42
|
+
:redis, # e.g. [{ "count" => 2, "flavor" => "m1.large", "plan" => "free" }]
|
43
|
+
:security_group # e.g. "cloudfoundry-production"
|
44
|
+
].each do |attr|
|
45
|
+
define_method attr do
|
46
|
+
read(attr, false)
|
47
|
+
end
|
48
|
+
|
49
|
+
define_method "#{attr}=" do |value|
|
50
|
+
write_global(attr, value)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def microbosh
|
55
|
+
unless bosh_target
|
56
|
+
raise "please set #bosh_target before requesting microbosh configuration"
|
57
|
+
end
|
58
|
+
@microbosh ||= Bosh::CloudFoundry::Config::MicroboshConfig.new(bosh_target)
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,362 @@
|
|
1
|
+
# Copyright (c) 2012-2013 Stark & Wayne, LLC
|
2
|
+
|
3
|
+
module Bosh; module CloudFoundry; end; end
|
4
|
+
|
5
|
+
# A set of helper methods to add to a Command class to
|
6
|
+
# get values from Command +options+ if provided,
|
7
|
+
# else from +Bosh::CloudFoundry::Config+.
|
8
|
+
# Some helpers also prompt for values if
|
9
|
+
# no option/common_config value found.
|
10
|
+
#
|
11
|
+
# Assumes there is a +director+ method for making
|
12
|
+
# API calls to the target BOSH Director API.
|
13
|
+
module Bosh::CloudFoundry::ConfigOptions
|
14
|
+
DEFAULT_CONFIG_PATH = File.expand_path("~/.bosh_common_config")
|
15
|
+
DEFAULT_CF_RELEASE_GIT_REPO = "git://github.com/cloudfoundry/cf-release.git"
|
16
|
+
DEFAULT_BOSH_GIT_REPO = "git://github.com/cloudfoundry/bosh.git"
|
17
|
+
DEFAULT_BASE_SYSTEM_PATH = "/var/vcap/store/systems"
|
18
|
+
DEFAULT_RELEASES_PATH = "/var/vcap/store/releases"
|
19
|
+
DEFAULT_STEMCELLS_PATH = "/var/vcap/store/stemcells"
|
20
|
+
DEFAULT_REPOS_PATH = "/var/vcap/store/repos"
|
21
|
+
DEFAULT_RELEASE_NAME = "appcloud" # name of cf-release final release name
|
22
|
+
DEFAULT_RELEASE_VERSION = "124" # FIXME restore to "latest" when #49 fixed
|
23
|
+
DEFAULT_STEMCELL_NAME = "bosh-stemcell"
|
24
|
+
DEFAULT_COMMONT_PERSISTENT_DISK = 16192
|
25
|
+
COMMON_PASSWORD_SIZE = 16 # characters; the min for the CC password
|
26
|
+
|
27
|
+
# @return [Bosh::CloudFoundry::Config:: CommonConfig] Current common CF configuration
|
28
|
+
def common_config
|
29
|
+
@common_config ||= begin
|
30
|
+
config_file = options[:common_config] || DEFAULT_CONFIG_PATH
|
31
|
+
common_config = Bosh::CloudFoundry::Config:: CommonConfig.new(config_file)
|
32
|
+
common_config.cf_release_git_repo ||= DEFAULT_CF_RELEASE_GIT_REPO
|
33
|
+
common_config.bosh_git_repo ||= DEFAULT_BOSH_GIT_REPO
|
34
|
+
common_config.save
|
35
|
+
common_config
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Bosh::CloudFoundry::Config::SystemConfig] System-specific configuration
|
40
|
+
def system_config
|
41
|
+
unless system
|
42
|
+
puts caller
|
43
|
+
err("Internal bug: cannot access system_config until a system has been selected by user")
|
44
|
+
end
|
45
|
+
@system_config ||= begin
|
46
|
+
system_config = Bosh::CloudFoundry::Config::SystemConfig.new(system)
|
47
|
+
system_config.bosh_target = options[:bosh_target] || config.target
|
48
|
+
system_config.bosh_target_uuid = options[:bosh_target_uuid] || config.target_uuid
|
49
|
+
system_config.bosh_provider = 'aws' # TODO support other BOSH providers
|
50
|
+
system_config.release_name ||= DEFAULT_RELEASE_NAME
|
51
|
+
system_config.release_version ||= DEFAULT_RELEASE_VERSION
|
52
|
+
system_config.stemcell_name ||= DEFAULT_STEMCELL_NAME
|
53
|
+
system_config.common_persistent_disk = DEFAULT_COMMONT_PERSISTENT_DISK
|
54
|
+
system_config.save
|
55
|
+
system_config
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# @return [String] CloudFoundry system path
|
60
|
+
def system
|
61
|
+
options[:system] || common_config.target_system
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [String] CloudFoundry system name
|
65
|
+
def system_name
|
66
|
+
@system_name ||= system_config.system_name
|
67
|
+
end
|
68
|
+
|
69
|
+
# Example usage:
|
70
|
+
# overriddable_config_option :release_name, :system_config, :release_name
|
71
|
+
# overriddable_config_option :core_ip, :system_config
|
72
|
+
# overriddable_config_option :cf_release_git_repo, :common_config
|
73
|
+
#
|
74
|
+
# +target_config+ is a method name resolving to
|
75
|
+
# an instance of either +SystemConfig+ or +CommonConfig+.
|
76
|
+
def self.overriddable_config_option(config_option, target_config_accessor, target_config_name=nil)
|
77
|
+
target_config_name ||= config_option
|
78
|
+
config_option = config_option.to_sym
|
79
|
+
target_config_accessor = target_config_accessor.to_sym
|
80
|
+
target_config_name = target_config_name.to_sym
|
81
|
+
# The call:
|
82
|
+
# overriddable_config_option :release_name, :system_config, :release_name
|
83
|
+
# Creates the following method:
|
84
|
+
# def release_name
|
85
|
+
# if override = options[:release_name]
|
86
|
+
# system_config.release_name = override
|
87
|
+
# system_config.save
|
88
|
+
# end
|
89
|
+
# return system_config.release_name if system_config.release_name
|
90
|
+
# choose_release_name # if it exists; OR
|
91
|
+
# generate_release_name # if it exists; OR
|
92
|
+
# nil
|
93
|
+
# end
|
94
|
+
define_method config_option do
|
95
|
+
# convert :system_config into the instance of SystemConfig
|
96
|
+
target_config = self.send(target_config_accessor)
|
97
|
+
# determine if options has an override for
|
98
|
+
if override = options[config_option]
|
99
|
+
target_config.send(:"#{target_config_name}=", override)
|
100
|
+
target_config.save
|
101
|
+
end
|
102
|
+
config_value = target_config.send(target_config_name)
|
103
|
+
return config_value if config_value
|
104
|
+
if self.respond_to?(:"choose_#{config_option}")
|
105
|
+
self.send(:"choose_#{config_option}")
|
106
|
+
elsif self.respond_to?(:"generate_#{config_option}")
|
107
|
+
override = self.send(:"generate_#{config_option}")
|
108
|
+
target_config.send(:"#{target_config_name}=", override)
|
109
|
+
target_config.save
|
110
|
+
override
|
111
|
+
else
|
112
|
+
nil
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# @return [String] BOSH target to manage CloudFoundry
|
118
|
+
overriddable_config_option :bosh_target, :system_config
|
119
|
+
|
120
|
+
# @return [String] BOSH target director UUID
|
121
|
+
overriddable_config_option :bosh_target_uuid, :system_config
|
122
|
+
|
123
|
+
# @return [String] Name of BOSH release in target BOSH
|
124
|
+
overriddable_config_option :release_name, :system_config
|
125
|
+
|
126
|
+
# @return [String] Version of BOSH release in target BOSH [defaulted above]
|
127
|
+
overriddable_config_option :release_version, :system_config
|
128
|
+
|
129
|
+
# @return [String] Name of BOSH stemcell to use for deployments
|
130
|
+
overriddable_config_option :stemcell_name, :system_config
|
131
|
+
|
132
|
+
# @return [String] Version of BOSH stemcell to use for deployments
|
133
|
+
overriddable_config_option :stemcell_version, :system_config
|
134
|
+
|
135
|
+
# @return [String] public IP address for the Core CF server (to the router)
|
136
|
+
overriddable_config_option :core_ip, :system_config
|
137
|
+
|
138
|
+
# @return [String] public DNS all apps & api access, e.g. mycompany.com
|
139
|
+
overriddable_config_option :root_dns, :system_config
|
140
|
+
|
141
|
+
# @return [String] flavor of server for the Core server in CloudFoundry deployment
|
142
|
+
overriddable_config_option :core_server_flavor, :system_config
|
143
|
+
|
144
|
+
# @return [Array] list of emails for pre-created admin accounts in CloudFoundry deployment
|
145
|
+
overriddable_config_option :admin_emails, :system_config
|
146
|
+
|
147
|
+
# @return [Integer] the persistent disk size (Mb) attached to any server that wants one
|
148
|
+
overriddable_config_option :common_persistent_disk, :system_config
|
149
|
+
|
150
|
+
# @return [String] a strong password used throughout deployment manifests
|
151
|
+
overriddable_config_option :common_password, :system_config
|
152
|
+
|
153
|
+
# @return [String] name of AWS security group being used
|
154
|
+
overriddable_config_option :security_group, :system_config
|
155
|
+
|
156
|
+
# @return [String] CloudFoundry BOSH release git URI
|
157
|
+
def cf_release_git_repo
|
158
|
+
options[:cf_release_git_repo] || common_config.cf_release_git_repo
|
159
|
+
end
|
160
|
+
|
161
|
+
# @return [String] Path to store BOSH release projects
|
162
|
+
def releases_dir
|
163
|
+
options[:releases_dir] || common_config.releases_dir || choose_releases_dir
|
164
|
+
end
|
165
|
+
|
166
|
+
# @return [String] Path to cf-release BOSH release
|
167
|
+
def cf_release_dir
|
168
|
+
options[:cf_release_dir] || common_config.cf_release_dir || begin
|
169
|
+
common_config.cf_release_dir = File.join(releases_dir, "cf-release")
|
170
|
+
common_config.save
|
171
|
+
common_config.cf_release_dir
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# @return [String] Path to store stemcells locally
|
176
|
+
def stemcells_dir
|
177
|
+
options[:stemcells_dir] || common_config.stemcells_dir || choose_stemcells_dir
|
178
|
+
end
|
179
|
+
|
180
|
+
# @return [String] Path to store source repositories locally
|
181
|
+
def repos_dir
|
182
|
+
options[:repos_dir] || common_config.repos_dir || choose_repos_dir
|
183
|
+
end
|
184
|
+
|
185
|
+
# @return [Boolean] true if skipping validations
|
186
|
+
def skip_validations?
|
187
|
+
options[:no_validation] || options[:no_validations] || options[:skip_validations]
|
188
|
+
end
|
189
|
+
|
190
|
+
# @return [Boolean] true if release_version is 'latest'; or no system set yet
|
191
|
+
def use_latest_release?
|
192
|
+
system.nil? || release_version == "latest"
|
193
|
+
end
|
194
|
+
|
195
|
+
def bosh_git_repo
|
196
|
+
options[:bosh_git_repo] || common_config.bosh_git_repo
|
197
|
+
end
|
198
|
+
|
199
|
+
def deployment_manifest(subsystem="core")
|
200
|
+
YAML.load_file(deployment_manifest_path(subsystem))
|
201
|
+
end
|
202
|
+
|
203
|
+
def deployment_manifest_path(subsystem="core")
|
204
|
+
File.join(system, "deployments", "#{system_name}-#{subsystem}.yml")
|
205
|
+
end
|
206
|
+
|
207
|
+
# @return [String] Path to store BOSH systems (collections of deployments)
|
208
|
+
def base_systems_dir
|
209
|
+
@base_systems_dir ||= options[:base_systems_dir] || common_config.base_systems_dir || begin
|
210
|
+
if non_interactive?
|
211
|
+
err "Please set base_systems_dir configuration for non-interactive mode"
|
212
|
+
end
|
213
|
+
|
214
|
+
base_systems_dir = ask("Path for to store all CloudFoundry systems: ") {
|
215
|
+
|q| q.default = DEFAULT_BASE_SYSTEM_PATH }
|
216
|
+
common_config.base_systems_dir = File.expand_path(base_systems_dir)
|
217
|
+
unless File.directory?(common_config.base_systems_dir)
|
218
|
+
say "Creating systems path #{common_config.base_systems_dir}"
|
219
|
+
FileUtils.mkdir_p(common_config.base_systems_dir)
|
220
|
+
end
|
221
|
+
common_config.save
|
222
|
+
common_config.base_systems_dir
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def choose_releases_dir
|
227
|
+
if non_interactive?
|
228
|
+
err "Please set releases_dir configuration for non-interactive mode"
|
229
|
+
end
|
230
|
+
|
231
|
+
releases_dir = ask("Path to store all BOSH releases: ") {
|
232
|
+
|q| q.default = DEFAULT_RELEASES_PATH }
|
233
|
+
|
234
|
+
common_config.releases_dir = File.expand_path(releases_dir)
|
235
|
+
unless File.directory?(common_config.releases_dir)
|
236
|
+
say "Creating releases path #{common_config.releases_dir}"
|
237
|
+
FileUtils.mkdir_p(common_config.releases_dir)
|
238
|
+
end
|
239
|
+
common_config.save
|
240
|
+
common_config.releases_dir
|
241
|
+
end
|
242
|
+
|
243
|
+
def choose_stemcells_dir
|
244
|
+
if non_interactive?
|
245
|
+
err "Please set stemcells_dir configuration for non-interactive mode"
|
246
|
+
end
|
247
|
+
|
248
|
+
stemcells_dir = ask("Path to store downloaded/created stemcells: ") {
|
249
|
+
|q| q.default = DEFAULT_STEMCELLS_PATH }
|
250
|
+
|
251
|
+
common_config.stemcells_dir = File.expand_path(stemcells_dir)
|
252
|
+
unless File.directory?(common_config.stemcells_dir)
|
253
|
+
say "Creating stemcells path #{common_config.stemcells_dir}"
|
254
|
+
FileUtils.mkdir_p(common_config.stemcells_dir)
|
255
|
+
end
|
256
|
+
common_config.save
|
257
|
+
common_config.stemcells_dir
|
258
|
+
end
|
259
|
+
|
260
|
+
def choose_repos_dir
|
261
|
+
if non_interactive?
|
262
|
+
err "Please set repos_dir configuration for non-interactive mode"
|
263
|
+
end
|
264
|
+
|
265
|
+
repos_dir = ask("Path to store source repositories: ") {
|
266
|
+
|q| q.default = DEFAULT_REPOS_PATH }
|
267
|
+
|
268
|
+
common_config.repos_dir = File.expand_path(repos_dir)
|
269
|
+
unless File.directory?(common_config.repos_dir)
|
270
|
+
say "Creating repos path #{common_config.repos_dir}"
|
271
|
+
FileUtils.mkdir_p(common_config.repos_dir)
|
272
|
+
end
|
273
|
+
common_config.save
|
274
|
+
common_config.repos_dir
|
275
|
+
end
|
276
|
+
|
277
|
+
# @return [String] Primary static IP for CloudController & Router
|
278
|
+
def choose_core_ip
|
279
|
+
if non_interactive?
|
280
|
+
err "Please set core_ip configuration for non-interactive mode"
|
281
|
+
end
|
282
|
+
|
283
|
+
if aws?
|
284
|
+
system_config.core_ip = ask("Main public IP address (press Enter to provision new IP): ").to_s
|
285
|
+
else
|
286
|
+
system_config.core_ip = ask("Main public IP address: ").to_s
|
287
|
+
end
|
288
|
+
if system_config.core_ip.blank?
|
289
|
+
say "Provisioning #{bosh_provider} public IP address..."
|
290
|
+
system_config.core_ip = provider.provision_public_ip_address
|
291
|
+
if system_config.core_ip.blank?
|
292
|
+
say "Hmmm, I wasn't able to get a public IP at the moment. Perhaps try again or provision it manually?".red
|
293
|
+
exit 1
|
294
|
+
end
|
295
|
+
end
|
296
|
+
system_config.save
|
297
|
+
system_config.core_ip
|
298
|
+
end
|
299
|
+
|
300
|
+
# @return [String] Root DNS for applications & CloudController API
|
301
|
+
def choose_root_dns
|
302
|
+
if non_interactive?
|
303
|
+
err "Please set root_dns configuration for non-interactive mode"
|
304
|
+
end
|
305
|
+
|
306
|
+
system_config.root_dns = ask("Root DNS (e.g. mycompany.com): ").to_s
|
307
|
+
system_config.save
|
308
|
+
system_config.root_dns
|
309
|
+
end
|
310
|
+
|
311
|
+
def choose_core_server_flavor
|
312
|
+
if non_interactive?
|
313
|
+
err "Please set core_server_flavor configuration for non-interactive mode"
|
314
|
+
end
|
315
|
+
|
316
|
+
server_flavor = ask("Server flavor for core of CloudFoundry? ") do |q|
|
317
|
+
q.default = default_core_server_flavor
|
318
|
+
end
|
319
|
+
system_config.core_server_flavor = server_flavor.to_s
|
320
|
+
system_config.save
|
321
|
+
system_config.core_server_flavor
|
322
|
+
end
|
323
|
+
|
324
|
+
def choose_admin_emails
|
325
|
+
if non_interactive?
|
326
|
+
err "Please set admin_emails configuration for non-interactive mode"
|
327
|
+
end
|
328
|
+
|
329
|
+
admin_email_list = ask("Email address for administrator of CloudFoundry? ") do |q|
|
330
|
+
git_email = `git config user.email`.strip
|
331
|
+
q.default = git_email if git_email.size > 0
|
332
|
+
end
|
333
|
+
admin_emails = admin_email_list.to_s.split(",")
|
334
|
+
system_config.admin_emails = admin_emails
|
335
|
+
system_config.save
|
336
|
+
system_config.admin_emails
|
337
|
+
end
|
338
|
+
|
339
|
+
# generates a password of a specific length; defaults to size +COMMON_PASSWORD_SIZE+
|
340
|
+
def generate_common_password(size=COMMON_PASSWORD_SIZE)
|
341
|
+
OpenSSL::Random.random_bytes(size).unpack("H*")[0][0..size-1]
|
342
|
+
end
|
343
|
+
|
344
|
+
def generate_security_group
|
345
|
+
"cloudfoundry-#{system_name}"
|
346
|
+
end
|
347
|
+
|
348
|
+
# List of versions of stemcell called "bosh-stemcell" that are available
|
349
|
+
# in target BOSH.
|
350
|
+
# Ordered by version number.
|
351
|
+
# @return [Array] BOSH stemcell versions available in target BOSH, e.g. ["0.6.4", "0.6.7"]
|
352
|
+
def bosh_stemcell_versions
|
353
|
+
@bosh_stemcell_versions ||= begin
|
354
|
+
# [{"name"=>"bosh-stemcell", "version"=>"0.6.7", "cid"=>"ami-9730bffe"}]
|
355
|
+
stemcells = director.list_stemcells
|
356
|
+
stemcells.select! {|s| s["name"] == stemcell_name}
|
357
|
+
stemcells.map { |rel| rel["version"] }.sort { |v1, v2|
|
358
|
+
version_cmp(v1, v2)
|
359
|
+
}
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|