bosh_deployer 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/config/aws_defaults.yml +3 -0
- data/config/openstack_defaults.yml +50 -0
- data/lib/bosh/cli/commands/micro.rb +12 -1
- data/lib/deployer/config.rb +15 -3
- data/lib/deployer/instance_manager/aws.rb +12 -4
- data/lib/deployer/instance_manager/openstack.rb +256 -0
- data/lib/deployer/instance_manager/vsphere.rb +1 -1
- data/lib/deployer/instance_manager.rb +32 -6
- data/lib/deployer/version.rb +1 -1
- metadata +58 -8
data/config/aws_defaults.yml
CHANGED
@@ -0,0 +1,50 @@
|
|
1
|
+
---
|
2
|
+
name:
|
3
|
+
|
4
|
+
logging:
|
5
|
+
level: INFO
|
6
|
+
|
7
|
+
dir:
|
8
|
+
|
9
|
+
network:
|
10
|
+
type: dynamic
|
11
|
+
cloud_properties: {}
|
12
|
+
|
13
|
+
env:
|
14
|
+
bosh:
|
15
|
+
password:
|
16
|
+
|
17
|
+
resources:
|
18
|
+
persistent_disk: 4096
|
19
|
+
cloud_properties:
|
20
|
+
instance_type: m1.small
|
21
|
+
availability_zone:
|
22
|
+
|
23
|
+
cloud:
|
24
|
+
plugin: openstack
|
25
|
+
properties:
|
26
|
+
openstack:
|
27
|
+
auth_url:
|
28
|
+
username:
|
29
|
+
api_key:
|
30
|
+
tenant:
|
31
|
+
default_key_name:
|
32
|
+
default_security_groups: []
|
33
|
+
ssh_user: vcap
|
34
|
+
registry:
|
35
|
+
endpoint: http://admin:admin@localhost:25889
|
36
|
+
user: admin
|
37
|
+
password: admin
|
38
|
+
stemcell:
|
39
|
+
kernel_id:
|
40
|
+
disk: 4096
|
41
|
+
agent:
|
42
|
+
ntp: []
|
43
|
+
blobstore:
|
44
|
+
plugin: local
|
45
|
+
properties:
|
46
|
+
blobstore_path: /var/vcap/micro_bosh/data/cache
|
47
|
+
mbus:
|
48
|
+
|
49
|
+
apply_spec:
|
50
|
+
properties: {}
|
@@ -80,12 +80,14 @@ module Bosh::Cli::Command
|
|
80
80
|
|
81
81
|
def perform(*options)
|
82
82
|
update = options.delete("--update")
|
83
|
+
force = options.delete("--force")
|
83
84
|
stemcell = options.shift
|
84
85
|
|
85
86
|
err "No deployment set" unless deployment
|
86
87
|
|
88
|
+
manifest = load_yaml_file(deployment)
|
89
|
+
|
87
90
|
if stemcell.nil?
|
88
|
-
manifest = load_yaml_file(deployment)
|
89
91
|
unless manifest.is_a?(Hash)
|
90
92
|
err("Invalid manifest format")
|
91
93
|
end
|
@@ -114,6 +116,15 @@ module Bosh::Cli::Command
|
|
114
116
|
err "Instance exists. Did you mean to --update?"
|
115
117
|
end
|
116
118
|
|
119
|
+
# make sure the user knows a persistent disk is a really good idea
|
120
|
+
unless dig_hash(manifest, "resources", "persistent_disk")
|
121
|
+
unless force
|
122
|
+
msg = "No persistent disk configured, use --force to deploy anyway"
|
123
|
+
quit(msg.red)
|
124
|
+
end
|
125
|
+
say("WARNING! The micro bosh data won't be persisted".red)
|
126
|
+
end
|
127
|
+
|
117
128
|
confirmation = "Deploying new"
|
118
129
|
|
119
130
|
method = :create_deployment
|
data/lib/deployer/config.rb
CHANGED
@@ -10,7 +10,7 @@ module Bosh::Deployer
|
|
10
10
|
include Helpers
|
11
11
|
|
12
12
|
attr_accessor :logger, :db, :uuid, :resources, :cloud_options,
|
13
|
-
:spec_properties, :bosh_ip, :env, :name
|
13
|
+
:spec_properties, :agent_properties, :bosh_ip, :env, :name
|
14
14
|
|
15
15
|
def configure(config)
|
16
16
|
plugin = cloud_plugin(config)
|
@@ -31,7 +31,9 @@ module Bosh::Deployer
|
|
31
31
|
@logger.level = Logger.const_get(config["logging"]["level"].upcase)
|
32
32
|
@logger.formatter = ThreadFormatter.new
|
33
33
|
|
34
|
-
|
34
|
+
apply_spec = config["apply_spec"]
|
35
|
+
@spec_properties = apply_spec["properties"]
|
36
|
+
@agent_properties = apply_spec["agent"]
|
35
37
|
|
36
38
|
@db = Sequel.sqlite
|
37
39
|
|
@@ -87,7 +89,9 @@ module Bosh::Deployer
|
|
87
89
|
end
|
88
90
|
|
89
91
|
def networks
|
90
|
-
@networks
|
92
|
+
return @networks if @networks
|
93
|
+
|
94
|
+
@networks = {
|
91
95
|
"bosh" => {
|
92
96
|
"cloud_properties" => @net_conf["cloud_properties"],
|
93
97
|
"netmask" => @net_conf["netmask"],
|
@@ -98,6 +102,14 @@ module Bosh::Deployer
|
|
98
102
|
"default" => ["dns", "gateway"]
|
99
103
|
}
|
100
104
|
}
|
105
|
+
if @net_conf["vip"]
|
106
|
+
@networks["vip"] = {
|
107
|
+
"ip" => @net_conf["vip"],
|
108
|
+
"type" => "vip"
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
@networks
|
101
113
|
end
|
102
114
|
|
103
115
|
private
|
@@ -128,7 +128,15 @@ module Bosh::Deployer
|
|
128
128
|
|
129
129
|
def discover_bosh_ip
|
130
130
|
if exists?
|
131
|
-
|
131
|
+
# choose elastic IP over public, as any agent connecting to the
|
132
|
+
# deployed micro bosh will be cut off from the public IP when
|
133
|
+
# we re-deploy micro bosh
|
134
|
+
if cloud.ec2.instances[state.vm_cid].has_elastic_ip?
|
135
|
+
ip = cloud.ec2.instances[state.vm_cid].elastic_ip.public_ip
|
136
|
+
else
|
137
|
+
ip = cloud.ec2.instances[state.vm_cid].public_ip_address
|
138
|
+
end
|
139
|
+
|
132
140
|
if ip != Config.bosh_ip
|
133
141
|
Config.bosh_ip = ip
|
134
142
|
logger.info("discovered bosh ip=#{Config.bosh_ip}")
|
@@ -142,14 +150,14 @@ module Bosh::Deployer
|
|
142
150
|
cloud.ec2.instances[state.vm_cid].private_ip_address
|
143
151
|
end
|
144
152
|
|
145
|
-
# @return [Integer] size in
|
153
|
+
# @return [Integer] size in MiB
|
146
154
|
def disk_size(cid)
|
147
|
-
# AWS stores disk size in
|
155
|
+
# AWS stores disk size in GiB but the CPI uses MiB
|
148
156
|
cloud.ec2.volumes[cid].size * 1024
|
149
157
|
end
|
150
158
|
|
151
159
|
def persistent_disk_changed?
|
152
|
-
# since AWS stores disk size in
|
160
|
+
# since AWS stores disk size in GiB and the CPI uses MiB there
|
153
161
|
# is a risk of conversion errors which lead to an unnecessary
|
154
162
|
# disk migration, so we need to do a double conversion
|
155
163
|
# here to avoid that
|
@@ -0,0 +1,256 @@
|
|
1
|
+
# Copyright (c) 2009-2012 VMware, Inc.
|
2
|
+
|
3
|
+
require 'net/ssh'
|
4
|
+
|
5
|
+
module Bosh::Deployer
|
6
|
+
class InstanceManager
|
7
|
+
|
8
|
+
class Openstack < InstanceManager
|
9
|
+
|
10
|
+
def update_spec(spec)
|
11
|
+
spec = super(spec)
|
12
|
+
properties = spec["properties"]
|
13
|
+
|
14
|
+
properties["openstack"] =
|
15
|
+
Config.spec_properties["openstack"] ||
|
16
|
+
Config.cloud_options["properties"]["openstack"].dup
|
17
|
+
|
18
|
+
properties["openstack"]["registry"] = Config.cloud_options["properties"]["registry"]
|
19
|
+
properties["openstack"]["stemcell"] = Config.cloud_options["properties"]["stemcell"]
|
20
|
+
|
21
|
+
spec.delete("networks")
|
22
|
+
|
23
|
+
spec
|
24
|
+
end
|
25
|
+
|
26
|
+
def configure
|
27
|
+
properties = Config.cloud_options["properties"]
|
28
|
+
@ssh_user = properties["openstack"]["ssh_user"]
|
29
|
+
@ssh_port = properties["openstack"]["ssh_port"] || 22
|
30
|
+
@ssh_wait = properties["openstack"]["ssh_wait"] || 60
|
31
|
+
|
32
|
+
key = properties["openstack"]["private_key"]
|
33
|
+
unless key
|
34
|
+
raise ConfigError, "Missing properties.openstack.private_key"
|
35
|
+
end
|
36
|
+
@ssh_key = File.expand_path(key)
|
37
|
+
unless File.exists?(@ssh_key)
|
38
|
+
raise ConfigError, "properties.openstack.private_key '#{key}' does not exist"
|
39
|
+
end
|
40
|
+
|
41
|
+
uri = URI.parse(properties["registry"]["endpoint"])
|
42
|
+
user, password = uri.userinfo.split(":", 2)
|
43
|
+
@registry_port = uri.port
|
44
|
+
|
45
|
+
@registry_db = Tempfile.new("openstack_registry_db")
|
46
|
+
@registry_db_url = "sqlite://#{@registry_db.path}"
|
47
|
+
|
48
|
+
registry_config = {
|
49
|
+
"logfile" => "./openstack_registry.log",
|
50
|
+
"http" => {
|
51
|
+
"port" => uri.port,
|
52
|
+
"user" => user,
|
53
|
+
"password" => password
|
54
|
+
},
|
55
|
+
"db" => {
|
56
|
+
"database" => @registry_db_url
|
57
|
+
},
|
58
|
+
"openstack" => properties["openstack"]
|
59
|
+
}
|
60
|
+
|
61
|
+
@registry_config = Tempfile.new("openstack_registry_yml")
|
62
|
+
@registry_config.write(YAML.dump(registry_config))
|
63
|
+
@registry_config.close
|
64
|
+
end
|
65
|
+
|
66
|
+
def start
|
67
|
+
configure()
|
68
|
+
|
69
|
+
Sequel.connect(@registry_db_url) do |db|
|
70
|
+
migrate(db)
|
71
|
+
servers = @deployments["openstack_servers"]
|
72
|
+
db[:openstack_servers].insert_multiple(servers) if servers
|
73
|
+
end
|
74
|
+
|
75
|
+
unless has_openstack_registry?
|
76
|
+
raise "openstack_registry command not found - " +
|
77
|
+
"run 'gem install bosh_openstack_registry'"
|
78
|
+
end
|
79
|
+
|
80
|
+
cmd = "openstack_registry -c #{@registry_config.path}"
|
81
|
+
|
82
|
+
@registry_pid = spawn(cmd)
|
83
|
+
|
84
|
+
5.times do
|
85
|
+
sleep 0.5
|
86
|
+
if Process.waitpid(@registry_pid, Process::WNOHANG)
|
87
|
+
raise Error, "`#{cmd}` failed, exit status=#{$?.exitstatus}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
timeout_time = Time.now.to_f + (60 * 5)
|
92
|
+
http_client = HTTPClient.new()
|
93
|
+
begin
|
94
|
+
http_client.head("http://127.0.0.1:#{@registry_port}")
|
95
|
+
sleep 0.5
|
96
|
+
rescue URI::Error, SocketError, Errno::ECONNREFUSED => e
|
97
|
+
if timeout_time - Time.now.to_f > 0
|
98
|
+
retry
|
99
|
+
else
|
100
|
+
raise "Cannot access openstack_registry: #{e.message}"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
logger.info("openstack_registry is ready on port #{@registry_port}")
|
104
|
+
ensure
|
105
|
+
@registry_config.unlink if @registry_config
|
106
|
+
end
|
107
|
+
|
108
|
+
def stop
|
109
|
+
if @registry_pid && process_exists?(@registry_pid)
|
110
|
+
Process.kill("INT", @registry_pid)
|
111
|
+
Process.waitpid(@registry_pid)
|
112
|
+
end
|
113
|
+
|
114
|
+
return unless @registry_db_url
|
115
|
+
|
116
|
+
Sequel.connect(@registry_db_url) do |db|
|
117
|
+
@deployments["openstack_servers"] = db[:openstack_servers].map {|row| row}
|
118
|
+
end
|
119
|
+
|
120
|
+
save_state
|
121
|
+
@registry_db.unlink if @registry_db
|
122
|
+
end
|
123
|
+
|
124
|
+
def wait_until_agent_ready
|
125
|
+
tunnel(@registry_port)
|
126
|
+
super
|
127
|
+
end
|
128
|
+
|
129
|
+
def discover_bosh_ip
|
130
|
+
if exists?
|
131
|
+
server = cloud.openstack.servers.get(state.vm_cid)
|
132
|
+
ip = server.public_ip_address
|
133
|
+
ip = server.private_ip_address if ip.nil? || ip.empty?
|
134
|
+
if ip.nil? || ip.empty?
|
135
|
+
raise "Unable to discover bosh ip"
|
136
|
+
else
|
137
|
+
if ip["addr"] != Config.bosh_ip
|
138
|
+
Config.bosh_ip = ip["addr"]
|
139
|
+
logger.info("discovered bosh ip=#{Config.bosh_ip}")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
super
|
145
|
+
end
|
146
|
+
|
147
|
+
def service_ip
|
148
|
+
ip = cloud.openstack.servers.get(state.vm_cid).private_ip_address
|
149
|
+
ip["addr"] unless ip.nil? || ip.empty?
|
150
|
+
end
|
151
|
+
|
152
|
+
# @return [Integer] size in MiB
|
153
|
+
def disk_size(cid)
|
154
|
+
# OpenStack stores disk size in GiB but we work with MiB
|
155
|
+
cloud.openstack.volumes.get(cid).size * 1024
|
156
|
+
end
|
157
|
+
|
158
|
+
def persistent_disk_changed?
|
159
|
+
# since OpenStack stores disk size in GiB and we use MiB there
|
160
|
+
# is a risk of conversion errors which lead to an unnecessary
|
161
|
+
# disk migration, so we need to do a double conversion
|
162
|
+
# here to avoid that
|
163
|
+
requested = (Config.resources['persistent_disk'] / 1024.0).ceil * 1024
|
164
|
+
requested != disk_size(state.disk_cid)
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
# TODO this code is similar to has_stemcell_copy?
|
170
|
+
# move the two into bosh_common later
|
171
|
+
def has_openstack_registry?(path=ENV['PATH'])
|
172
|
+
path.split(":").each do |dir|
|
173
|
+
return true if File.exist?(File.join(dir, "openstack_registry"))
|
174
|
+
end
|
175
|
+
false
|
176
|
+
end
|
177
|
+
|
178
|
+
def migrate(db)
|
179
|
+
db.create_table :openstack_servers do
|
180
|
+
primary_key :id
|
181
|
+
column :server_id, :text, :unique => true, :null => false
|
182
|
+
column :settings, :text, :null => false
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def process_exists?(pid)
|
187
|
+
begin
|
188
|
+
Process.kill(0, pid)
|
189
|
+
rescue Errno::ESRCH
|
190
|
+
false
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def socket_readable?(ip, port)
|
195
|
+
socket = TCPSocket.new(ip, port)
|
196
|
+
if IO.select([socket], nil, nil, 5)
|
197
|
+
logger.debug("tcp socket #{ip}:#{port} is readable")
|
198
|
+
yield
|
199
|
+
true
|
200
|
+
else
|
201
|
+
false
|
202
|
+
end
|
203
|
+
rescue SocketError => e
|
204
|
+
logger.debug("tcp socket #{ip}:#{port} SocketError: #{e.inspect}")
|
205
|
+
sleep 1
|
206
|
+
false
|
207
|
+
rescue SystemCallError => e
|
208
|
+
logger.debug("tcp socket #{ip}:#{port} SystemCallError: #{e.inspect}")
|
209
|
+
sleep 1
|
210
|
+
false
|
211
|
+
ensure
|
212
|
+
socket.close if socket
|
213
|
+
end
|
214
|
+
|
215
|
+
def tunnel(port)
|
216
|
+
return if @session
|
217
|
+
|
218
|
+
ip = discover_bosh_ip
|
219
|
+
|
220
|
+
loop until socket_readable?(ip, @ssh_port) do
|
221
|
+
#sshd is up, sleep while host keys are generated
|
222
|
+
sleep @ssh_wait
|
223
|
+
end
|
224
|
+
|
225
|
+
lo = "127.0.0.1"
|
226
|
+
cmd = "ssh -R #{port}:#{lo}:#{port} #{@ssh_user}@#{ip}"
|
227
|
+
|
228
|
+
logger.info("Preparing for ssh tunnel: #{cmd}")
|
229
|
+
loop do
|
230
|
+
begin
|
231
|
+
@session = Net::SSH.start(ip, @ssh_user, :keys => [@ssh_key],
|
232
|
+
:paranoid => false)
|
233
|
+
logger.debug("ssh #{@ssh_user}@#{ip}: ESTABLISHED")
|
234
|
+
break
|
235
|
+
rescue => e
|
236
|
+
logger.debug("ssh start #{@ssh_user}@#{ip} failed: #{e.inspect}")
|
237
|
+
sleep 1
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
@session.forward.remote(port, lo, port)
|
242
|
+
logger.info("`#{cmd}` started: OK")
|
243
|
+
|
244
|
+
Thread.new do
|
245
|
+
begin
|
246
|
+
@session.loop { true }
|
247
|
+
rescue IOError => e
|
248
|
+
logger.debug("`#{cmd}` terminated: #{e.inspect}")
|
249
|
+
@session = nil
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
@@ -350,13 +350,17 @@ module Bosh::Deployer
|
|
350
350
|
properties["director"]["name"] = Config.name
|
351
351
|
end
|
352
352
|
|
353
|
-
|
354
|
-
|
355
|
-
|
353
|
+
# blobstore and nats need to use an elastic IP (if available),
|
354
|
+
# as when the micro bosh instance is re-created during a
|
355
|
+
# deployment, it might get a new private IP
|
356
|
+
%w{blobstore nats}.each do |service|
|
357
|
+
update_agent_service_address(properties, service, bosh_ip)
|
358
|
+
end
|
356
359
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
+
services = %w{postgres director redis blobstore nats aws_registry
|
361
|
+
openstack_registry}
|
362
|
+
services.each do |service|
|
363
|
+
update_service_address(properties, service, service_ip)
|
360
364
|
end
|
361
365
|
|
362
366
|
spec
|
@@ -382,6 +386,28 @@ module Bosh::Deployer
|
|
382
386
|
|
383
387
|
private
|
384
388
|
|
389
|
+
# update the agent service section from the contents of the apply_spec
|
390
|
+
def update_agent_service_address(properties, service, address)
|
391
|
+
if Config.agent_properties
|
392
|
+
agent = properties["agent"] ||= {}
|
393
|
+
svc = agent[service] ||= {}
|
394
|
+
svc["address"] = address
|
395
|
+
|
396
|
+
if override = Config.agent_properties[service]
|
397
|
+
svc.merge!(override)
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
def update_service_address(properties, service, address)
|
403
|
+
return unless properties[service]
|
404
|
+
properties[service]["address"] = address
|
405
|
+
|
406
|
+
if override = Config.spec_properties[service]
|
407
|
+
properties[service].merge!(override)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
385
411
|
def bosh_ip
|
386
412
|
Config.bosh_ip
|
387
413
|
end
|
data/lib/deployer/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bosh_deployer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bosh_common
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.
|
21
|
+
version: 0.5.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.
|
29
|
+
version: 0.5.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: bosh_cpi
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 0.6.
|
69
|
+
version: 0.6.2
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -74,7 +74,55 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: 0.6.
|
77
|
+
version: 0.6.2
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: bosh_aws_registry
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 0.2.2
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.2.2
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: bosh_openstack_cpi
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 0.0.2
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 0.0.2
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: bosh_openstack_registry
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.0.1
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 0.0.1
|
78
126
|
- !ruby/object:Gem::Dependency
|
79
127
|
name: agent_client
|
80
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,6 +162,7 @@ extensions: []
|
|
114
162
|
extra_rdoc_files: []
|
115
163
|
files:
|
116
164
|
- config/aws_defaults.yml
|
165
|
+
- config/openstack_defaults.yml
|
117
166
|
- config/vsphere_defaults.yml
|
118
167
|
- lib/bosh/cli/commands/micro.rb
|
119
168
|
- lib/deployer.rb
|
@@ -122,6 +171,7 @@ files:
|
|
122
171
|
- lib/deployer/helpers.rb
|
123
172
|
- lib/deployer/instance_manager.rb
|
124
173
|
- lib/deployer/instance_manager/aws.rb
|
174
|
+
- lib/deployer/instance_manager/openstack.rb
|
125
175
|
- lib/deployer/instance_manager/vsphere.rb
|
126
176
|
- lib/deployer/models/instance.rb
|
127
177
|
- lib/deployer/version.rb
|
@@ -142,7 +192,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
142
192
|
version: '0'
|
143
193
|
segments:
|
144
194
|
- 0
|
145
|
-
hash: -
|
195
|
+
hash: -2032018102027977195
|
146
196
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
197
|
none: false
|
148
198
|
requirements:
|
@@ -151,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
151
201
|
version: '0'
|
152
202
|
segments:
|
153
203
|
- 0
|
154
|
-
hash: -
|
204
|
+
hash: -2032018102027977195
|
155
205
|
requirements: []
|
156
206
|
rubyforge_project:
|
157
207
|
rubygems_version: 1.8.24
|