bosh_cli_plugin_micro 1.1868.0 → 1.1975.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/bosh/cli/commands/micro.rb +1 -1
- data/lib/bosh/deployer/deployments_state.rb +65 -0
- data/lib/bosh/deployer/instance_manager/aws.rb +40 -32
- data/lib/bosh/deployer/instance_manager/openstack.rb +39 -30
- data/lib/bosh/deployer/instance_manager/vcloud.rb +12 -6
- data/lib/bosh/deployer/instance_manager/vsphere.rb +12 -5
- data/lib/bosh/deployer/instance_manager.rb +50 -74
- data/lib/bosh/deployer/job_template.rb +39 -0
- data/lib/bosh/deployer/microbosh_job_instance.rb +53 -0
- data/lib/bosh/deployer/registry.rb +5 -5
- data/lib/bosh/deployer/version.rb +1 -1
- metadata +55 -20
@@ -226,7 +226,7 @@ module Bosh::Cli::Command
|
|
226
226
|
usage 'micro deployments'
|
227
227
|
desc 'Show the list of deployments'
|
228
228
|
def list
|
229
|
-
file = File.join(work_dir, Bosh::Deployer::
|
229
|
+
file = File.join(work_dir, Bosh::Deployer::DeploymentsState::DEPLOYMENTS_FILE)
|
230
230
|
if File.exists?(file)
|
231
231
|
deployments = load_yaml_file(file)['instances']
|
232
232
|
else
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
module Bosh::Deployer
|
4
|
+
class DeploymentsState
|
5
|
+
|
6
|
+
DEPLOYMENTS_FILE = 'bosh-deployments.yml'
|
7
|
+
|
8
|
+
attr_reader :file, :deployments, :state
|
9
|
+
|
10
|
+
def self.load_from_dir(dir, logger)
|
11
|
+
file = File.join(dir, DEPLOYMENTS_FILE)
|
12
|
+
if File.exists?(file)
|
13
|
+
logger.info("Loading existing deployment data from: #{file}")
|
14
|
+
deployments = Psych.load_file(file)
|
15
|
+
else
|
16
|
+
logger.info("No existing deployments found (will save to #{file})")
|
17
|
+
deployments = { 'instances' => [], 'disks' => [] }
|
18
|
+
end
|
19
|
+
new(deployments, file)
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(deployments, file)
|
23
|
+
@deployments = deployments
|
24
|
+
@file = file
|
25
|
+
end
|
26
|
+
|
27
|
+
def load_deployment(name, infrastructure)
|
28
|
+
infrastructure.disk_model.insert_multiple(deployments['disks']) if infrastructure.disk_model
|
29
|
+
models_instance.insert_multiple(deployments['instances'])
|
30
|
+
|
31
|
+
@state = models_instance.find(name: name)
|
32
|
+
if state.nil?
|
33
|
+
@state = models_instance.new
|
34
|
+
state.uuid = "bm-#{SecureRandom.uuid}"
|
35
|
+
state.name = name
|
36
|
+
state.stemcell_sha1 = nil
|
37
|
+
state.save
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def save(infrastructure)
|
42
|
+
state.save
|
43
|
+
deployments['instances'] = models_instance.map { |instance| instance.values }
|
44
|
+
if infrastructure.disk_model
|
45
|
+
deployments['disks'] = infrastructure.disk_model.map { |disk| disk.values }
|
46
|
+
end
|
47
|
+
|
48
|
+
File.open(file, 'w') do |file|
|
49
|
+
file.write(Psych.dump(deployments))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def exists?
|
54
|
+
return false unless state
|
55
|
+
[state.vm_cid, state.stemcell_cid, state.disk_cid].any?
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def models_instance
|
61
|
+
Models::Instance
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
@@ -4,36 +4,28 @@ require 'bosh/deployer/ssh_server'
|
|
4
4
|
|
5
5
|
module Bosh::Deployer
|
6
6
|
class InstanceManager
|
7
|
-
class Aws
|
8
|
-
def initialize(
|
9
|
-
|
7
|
+
class Aws
|
8
|
+
def initialize(instance_manager, logger)
|
9
|
+
@instance_manager = instance_manager
|
10
|
+
@logger = logger
|
11
|
+
properties = Config.cloud_options['properties']
|
10
12
|
|
11
13
|
@registry = Registry.new(
|
12
|
-
|
14
|
+
properties['registry']['endpoint'],
|
13
15
|
'aws',
|
14
|
-
|
15
|
-
|
16
|
+
properties['aws'],
|
17
|
+
instance_manager,
|
16
18
|
logger,
|
17
19
|
)
|
18
20
|
|
19
|
-
|
20
|
-
ssh_user = properties['aws']['ssh_user']
|
21
|
-
ssh_port = properties['aws']['ssh_port'] || 22
|
22
|
-
ssh_wait = properties['aws']['ssh_wait'] || 60
|
23
|
-
|
24
|
-
key = properties['aws']['ec2_private_key']
|
25
|
-
err 'Missing properties.aws.ec2_private_key' unless key
|
26
|
-
ssh_key = File.expand_path(key)
|
27
|
-
unless File.exists?(ssh_key)
|
28
|
-
err "properties.aws.ec2_private_key '#{key}' does not exist"
|
29
|
-
end
|
21
|
+
ssh_key, ssh_port, ssh_user, ssh_wait = ssh_properties(properties)
|
30
22
|
|
31
23
|
ssh_server = SshServer.new(ssh_user, ssh_key, ssh_port, logger)
|
32
24
|
@remote_tunnel = RemoteTunnel.new(ssh_server, ssh_wait, logger)
|
33
25
|
end
|
34
26
|
|
35
|
-
def remote_tunnel
|
36
|
-
@remote_tunnel.create(
|
27
|
+
def remote_tunnel
|
28
|
+
@remote_tunnel.create(instance_manager.bosh_ip, registry.port)
|
37
29
|
end
|
38
30
|
|
39
31
|
def disk_model
|
@@ -67,37 +59,38 @@ module Bosh::Deployer
|
|
67
59
|
|
68
60
|
def stop
|
69
61
|
registry.stop
|
70
|
-
save_state
|
62
|
+
instance_manager.save_state
|
71
63
|
end
|
72
64
|
|
73
65
|
def discover_bosh_ip
|
74
|
-
if state.vm_cid
|
66
|
+
if instance_manager.state.vm_cid
|
75
67
|
# choose elastic IP over public, as any agent connecting to the
|
76
68
|
# deployed micro bosh will be cut off from the public IP when
|
77
69
|
# we re-deploy micro bosh
|
78
|
-
|
79
|
-
|
70
|
+
instance = instance_manager.cloud.ec2.instances[instance_manager.state.vm_cid]
|
71
|
+
if instance.has_elastic_ip?
|
72
|
+
ip = instance.elastic_ip.public_ip
|
80
73
|
else
|
81
|
-
ip =
|
74
|
+
ip = instance.public_ip_address
|
82
75
|
end
|
83
76
|
|
84
|
-
if ip && ip !=
|
85
|
-
|
86
|
-
logger.info("discovered bosh ip=#{
|
77
|
+
if ip && ip != instance_manager.bosh_ip
|
78
|
+
instance_manager.bosh_ip = ip
|
79
|
+
logger.info("discovered bosh ip=#{instance_manager.bosh_ip}")
|
87
80
|
end
|
88
81
|
end
|
89
82
|
|
90
|
-
|
83
|
+
instance_manager.bosh_ip
|
91
84
|
end
|
92
85
|
|
93
86
|
def service_ip
|
94
|
-
cloud.ec2.instances[state.vm_cid].private_ip_address
|
87
|
+
instance_manager.cloud.ec2.instances[instance_manager.state.vm_cid].private_ip_address
|
95
88
|
end
|
96
89
|
|
97
90
|
# @return [Integer] size in MiB
|
98
91
|
def disk_size(cid)
|
99
92
|
# AWS stores disk size in GiB but the CPI uses MiB
|
100
|
-
cloud.ec2.volumes[cid].size * 1024
|
93
|
+
instance_manager.cloud.ec2.volumes[cid].size * 1024
|
101
94
|
end
|
102
95
|
|
103
96
|
def persistent_disk_changed?
|
@@ -106,12 +99,27 @@ module Bosh::Deployer
|
|
106
99
|
# disk migration, so we need to do a double conversion
|
107
100
|
# here to avoid that
|
108
101
|
requested = (Config.resources['persistent_disk'] / 1024.0).ceil * 1024
|
109
|
-
requested != disk_size(state.disk_cid)
|
102
|
+
requested != disk_size(instance_manager.state.disk_cid)
|
110
103
|
end
|
111
104
|
|
112
105
|
private
|
113
106
|
|
114
|
-
attr_reader :registry
|
107
|
+
attr_reader :registry, :instance_manager, :logger
|
108
|
+
|
109
|
+
def ssh_properties(properties)
|
110
|
+
ssh_user = properties['aws']['ssh_user']
|
111
|
+
ssh_port = properties['aws']['ssh_port'] || 22
|
112
|
+
ssh_wait = properties['aws']['ssh_wait'] || 60
|
113
|
+
|
114
|
+
key = properties['aws']['ec2_private_key']
|
115
|
+
err 'Missing properties.aws.ec2_private_key' unless key
|
116
|
+
ssh_key = File.expand_path(key)
|
117
|
+
unless File.exists?(ssh_key)
|
118
|
+
err "properties.aws.ec2_private_key '#{key}' does not exist"
|
119
|
+
end
|
120
|
+
|
121
|
+
[ssh_key, ssh_port, ssh_user, ssh_wait]
|
122
|
+
end
|
115
123
|
end
|
116
124
|
end
|
117
125
|
end
|
@@ -4,35 +4,27 @@ require 'bosh/deployer/ssh_server'
|
|
4
4
|
|
5
5
|
module Bosh::Deployer
|
6
6
|
class InstanceManager
|
7
|
-
class Openstack
|
8
|
-
def initialize(
|
9
|
-
|
7
|
+
class Openstack
|
8
|
+
def initialize(instance_manager, logger)
|
9
|
+
@instance_manager = instance_manager
|
10
|
+
@logger = logger
|
11
|
+
properties = Config.cloud_options['properties']
|
10
12
|
|
11
13
|
@registry = Registry.new(
|
12
|
-
|
14
|
+
properties['registry']['endpoint'],
|
13
15
|
'openstack',
|
14
|
-
|
15
|
-
|
16
|
+
properties['openstack'],
|
17
|
+
instance_manager,
|
16
18
|
logger,
|
17
19
|
)
|
18
20
|
|
19
|
-
|
20
|
-
ssh_user = properties['openstack']['ssh_user']
|
21
|
-
ssh_port = properties['openstack']['ssh_port'] || 22
|
22
|
-
ssh_wait = properties['openstack']['ssh_wait'] || 60
|
23
|
-
|
24
|
-
key = properties['openstack']['private_key']
|
25
|
-
err 'Missing properties.openstack.private_key' unless key
|
26
|
-
ssh_key = File.expand_path(key)
|
27
|
-
unless File.exists?(ssh_key)
|
28
|
-
err "properties.openstack.private_key '#{key}' does not exist"
|
29
|
-
end
|
21
|
+
ssh_key, ssh_port, ssh_user, ssh_wait = ssh_properties(properties)
|
30
22
|
ssh_server = SshServer.new(ssh_user, ssh_key, ssh_port, logger)
|
31
23
|
@remote_tunnel = RemoteTunnel.new(ssh_server, ssh_wait, logger)
|
32
24
|
end
|
33
25
|
|
34
|
-
def remote_tunnel
|
35
|
-
@remote_tunnel.create(
|
26
|
+
def remote_tunnel
|
27
|
+
@remote_tunnel.create(instance_manager.bosh_ip, registry.port)
|
36
28
|
end
|
37
29
|
|
38
30
|
def disk_model
|
@@ -62,31 +54,33 @@ module Bosh::Deployer
|
|
62
54
|
|
63
55
|
def stop
|
64
56
|
registry.stop
|
65
|
-
save_state
|
57
|
+
instance_manager.save_state
|
66
58
|
end
|
67
59
|
|
68
60
|
def discover_bosh_ip
|
69
|
-
if state.vm_cid
|
70
|
-
floating_ip = cloud.openstack.servers.
|
61
|
+
if instance_manager.state.vm_cid
|
62
|
+
floating_ip = instance_manager.cloud.openstack.servers.
|
63
|
+
get(instance_manager.state.vm_cid).floating_ip_address
|
71
64
|
ip = floating_ip || service_ip
|
72
65
|
|
73
|
-
if ip !=
|
74
|
-
|
75
|
-
logger.info("discovered bosh ip=#{
|
66
|
+
if ip != instance_manager.bosh_ip
|
67
|
+
instance_manager.bosh_ip = ip
|
68
|
+
logger.info("discovered bosh ip=#{instance_manager.bosh_ip}")
|
76
69
|
end
|
77
70
|
end
|
78
71
|
|
79
|
-
|
72
|
+
instance_manager.bosh_ip
|
80
73
|
end
|
81
74
|
|
82
75
|
def service_ip
|
83
|
-
cloud.openstack.servers.
|
76
|
+
instance_manager.cloud.openstack.servers.
|
77
|
+
get(instance_manager.state.vm_cid).private_ip_address
|
84
78
|
end
|
85
79
|
|
86
80
|
# @return [Integer] size in MiB
|
87
81
|
def disk_size(cid)
|
88
82
|
# OpenStack stores disk size in GiB but we work with MiB
|
89
|
-
cloud.openstack.volumes.get(cid).size * 1024
|
83
|
+
instance_manager.cloud.openstack.volumes.get(cid).size * 1024
|
90
84
|
end
|
91
85
|
|
92
86
|
def persistent_disk_changed?
|
@@ -95,12 +89,27 @@ module Bosh::Deployer
|
|
95
89
|
# disk migration, so we need to do a double conversion
|
96
90
|
# here to avoid that
|
97
91
|
requested = (Config.resources['persistent_disk'] / 1024.0).ceil * 1024
|
98
|
-
requested != disk_size(state.disk_cid)
|
92
|
+
requested != disk_size(instance_manager.state.disk_cid)
|
99
93
|
end
|
100
94
|
|
101
95
|
private
|
102
96
|
|
103
|
-
attr_reader :registry
|
97
|
+
attr_reader :registry, :instance_manager, :logger
|
98
|
+
|
99
|
+
def ssh_properties(properties)
|
100
|
+
ssh_user = properties['openstack']['ssh_user']
|
101
|
+
ssh_port = properties['openstack']['ssh_port'] || 22
|
102
|
+
ssh_wait = properties['openstack']['ssh_wait'] || 60
|
103
|
+
|
104
|
+
key = properties['openstack']['private_key']
|
105
|
+
err 'Missing properties.openstack.private_key' unless key
|
106
|
+
ssh_key = File.expand_path(key)
|
107
|
+
unless File.exists?(ssh_key)
|
108
|
+
err "properties.openstack.private_key '#{key}' does not exist"
|
109
|
+
end
|
110
|
+
|
111
|
+
[ssh_key, ssh_port, ssh_user, ssh_wait]
|
112
|
+
end
|
104
113
|
end
|
105
114
|
end
|
106
115
|
end
|
@@ -2,9 +2,13 @@
|
|
2
2
|
|
3
3
|
module Bosh::Deployer
|
4
4
|
class InstanceManager
|
5
|
-
class Vcloud
|
5
|
+
class Vcloud
|
6
|
+
def initialize(instance_manager, logger)
|
7
|
+
@instance_manager = instance_manager
|
8
|
+
@logger = logger
|
9
|
+
end
|
6
10
|
|
7
|
-
def remote_tunnel
|
11
|
+
def remote_tunnel
|
8
12
|
# VCloud / vsphere does not use bosh-registry so no remote_tunnel
|
9
13
|
# to bosh-registry is required
|
10
14
|
end
|
@@ -36,24 +40,26 @@ module Bosh::Deployer
|
|
36
40
|
end
|
37
41
|
|
38
42
|
def discover_bosh_ip
|
39
|
-
bosh_ip
|
43
|
+
instance_manager.bosh_ip
|
40
44
|
end
|
41
45
|
|
42
46
|
def service_ip
|
43
|
-
bosh_ip
|
47
|
+
instance_manager.bosh_ip
|
44
48
|
end
|
45
49
|
|
46
50
|
# @return [Integer] size in MiB
|
47
51
|
def disk_size(cid)
|
48
|
-
cloud.get_disk_size_mb(cid)
|
52
|
+
instance_manager.cloud.get_disk_size_mb(cid)
|
49
53
|
end
|
50
54
|
|
51
55
|
def persistent_disk_changed?
|
52
|
-
Config.resources['persistent_disk'] != disk_size(state.disk_cid)
|
56
|
+
Config.resources['persistent_disk'] != disk_size(instance_manager.state.disk_cid)
|
53
57
|
end
|
54
58
|
|
55
59
|
private
|
56
60
|
|
61
|
+
attr_reader :instance_manager, :logger
|
62
|
+
|
57
63
|
FakeRegistry = Struct.new(:port)
|
58
64
|
def registry
|
59
65
|
@registry ||= FakeRegistry.new(nil)
|
@@ -2,8 +2,13 @@
|
|
2
2
|
|
3
3
|
module Bosh::Deployer
|
4
4
|
class InstanceManager
|
5
|
-
class Vsphere
|
6
|
-
def
|
5
|
+
class Vsphere
|
6
|
+
def initialize(instance_manager, logger)
|
7
|
+
@instance_manager = instance_manager
|
8
|
+
@logger = logger
|
9
|
+
end
|
10
|
+
|
11
|
+
def remote_tunnel
|
7
12
|
end
|
8
13
|
|
9
14
|
def disk_model
|
@@ -37,11 +42,11 @@ module Bosh::Deployer
|
|
37
42
|
end
|
38
43
|
|
39
44
|
def discover_bosh_ip
|
40
|
-
bosh_ip
|
45
|
+
instance_manager.bosh_ip
|
41
46
|
end
|
42
47
|
|
43
48
|
def service_ip
|
44
|
-
bosh_ip
|
49
|
+
instance_manager.bosh_ip
|
45
50
|
end
|
46
51
|
|
47
52
|
# @return [Integer] size in MiB
|
@@ -50,11 +55,13 @@ module Bosh::Deployer
|
|
50
55
|
end
|
51
56
|
|
52
57
|
def persistent_disk_changed?
|
53
|
-
Config.resources['persistent_disk'] != disk_size(state.disk_cid)
|
58
|
+
Config.resources['persistent_disk'] != disk_size(instance_manager.state.disk_cid)
|
54
59
|
end
|
55
60
|
|
56
61
|
private
|
57
62
|
|
63
|
+
attr_reader :instance_manager, :logger
|
64
|
+
|
58
65
|
FakeRegistry = Struct.new(:port)
|
59
66
|
def registry
|
60
67
|
@registry ||= FakeRegistry.new(nil)
|
@@ -3,9 +3,15 @@ require 'bosh/deployer/logger_renderer'
|
|
3
3
|
require 'bosh/deployer/hash_fingerprinter'
|
4
4
|
require 'bosh/deployer/director_gateway_error'
|
5
5
|
require 'bosh/deployer/ui_messager'
|
6
|
+
require 'bosh/deployer/deployments_state'
|
7
|
+
require 'bosh/deployer/microbosh_job_instance'
|
8
|
+
|
9
|
+
require 'forwardable'
|
6
10
|
|
7
11
|
module Bosh::Deployer
|
8
12
|
class InstanceManager
|
13
|
+
extend Forwardable
|
14
|
+
|
9
15
|
CONNECTION_EXCEPTIONS = [
|
10
16
|
Bosh::Agent::Error,
|
11
17
|
Errno::ECONNREFUSED,
|
@@ -16,8 +22,8 @@ module Bosh::Deployer
|
|
16
22
|
|
17
23
|
DEPLOYMENTS_FILE = 'bosh-deployments.yml'
|
18
24
|
|
19
|
-
attr_reader :state
|
20
25
|
attr_accessor :renderer
|
26
|
+
attr_reader :infrastructure, :deployments_state
|
21
27
|
|
22
28
|
def self.create(config)
|
23
29
|
err 'No cloud properties defined' if config['cloud'].nil?
|
@@ -34,14 +40,17 @@ module Bosh::Deployer
|
|
34
40
|
config_sha1 = Bosh::Deployer::HashFingerprinter.new.sha1(config)
|
35
41
|
ui_messager = Bosh::Deployer::UiMessager.for_deployer
|
36
42
|
|
37
|
-
|
38
|
-
plugin_class.new(config, config_sha1, ui_messager)
|
43
|
+
new(config, config_sha1, ui_messager, plugin_name)
|
39
44
|
end
|
40
45
|
|
41
|
-
def initialize(config, config_sha1, ui_messager)
|
46
|
+
def initialize(config, config_sha1, ui_messager, plugin_name)
|
42
47
|
Config.configure(config)
|
48
|
+
@config = Config
|
49
|
+
|
50
|
+
plugin_class = InstanceManager.const_get(plugin_name.capitalize)
|
51
|
+
@infrastructure = plugin_class.new(self, logger)
|
43
52
|
|
44
|
-
@
|
53
|
+
@deployments_state = DeploymentsState.load_from_dir(config['dir'], logger)
|
45
54
|
load_state(config['name'])
|
46
55
|
|
47
56
|
Config.uuid = state.uuid
|
@@ -51,28 +60,28 @@ module Bosh::Deployer
|
|
51
60
|
@renderer = LoggerRenderer.new
|
52
61
|
end
|
53
62
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
def logger
|
63
|
-
Config.logger
|
64
|
-
end
|
63
|
+
def_delegators(
|
64
|
+
:@deployments_state,
|
65
|
+
:deployments,
|
66
|
+
:state,
|
67
|
+
:exists?,
|
68
|
+
)
|
65
69
|
|
66
|
-
|
67
|
-
|
68
|
-
|
70
|
+
def_delegators(
|
71
|
+
:@config,
|
72
|
+
:cloud,
|
73
|
+
:agent,
|
74
|
+
:logger,
|
75
|
+
:bosh_ip,
|
76
|
+
:bosh_ip=,
|
77
|
+
)
|
69
78
|
|
70
|
-
def
|
71
|
-
|
79
|
+
def check_dependencies
|
80
|
+
infrastructure.check_dependencies
|
72
81
|
end
|
73
82
|
|
74
|
-
def
|
75
|
-
|
83
|
+
def discover_bosh_ip
|
84
|
+
infrastructure.discover_bosh_ip
|
76
85
|
end
|
77
86
|
|
78
87
|
def step(task)
|
@@ -83,10 +92,10 @@ module Bosh::Deployer
|
|
83
92
|
end
|
84
93
|
|
85
94
|
def with_lifecycle
|
86
|
-
start
|
95
|
+
infrastructure.start
|
87
96
|
yield
|
88
97
|
ensure
|
89
|
-
stop
|
98
|
+
infrastructure.stop
|
90
99
|
end
|
91
100
|
|
92
101
|
def create_deployment(stemcell_tgz, stemcell_archive)
|
@@ -117,7 +126,7 @@ module Bosh::Deployer
|
|
117
126
|
step "Creating VM from #{state.stemcell_cid}" do
|
118
127
|
state.vm_cid = create_vm(state.stemcell_cid)
|
119
128
|
update_vm_metadata(state.vm_cid, { 'Name' => state.name })
|
120
|
-
discover_bosh_ip
|
129
|
+
infrastructure.discover_bosh_ip
|
121
130
|
end
|
122
131
|
save_state
|
123
132
|
|
@@ -343,7 +352,7 @@ module Bosh::Deployer
|
|
343
352
|
if state.disk_cid.nil?
|
344
353
|
create_disk
|
345
354
|
attach_disk(state.disk_cid, true)
|
346
|
-
elsif persistent_disk_changed?
|
355
|
+
elsif infrastructure.persistent_disk_changed?
|
347
356
|
size = Config.resources['persistent_disk']
|
348
357
|
|
349
358
|
# save a reference to the old disk
|
@@ -373,20 +382,25 @@ module Bosh::Deployer
|
|
373
382
|
|
374
383
|
step 'Applying micro BOSH spec' do
|
375
384
|
# first update spec with infrastructure specific stuff
|
376
|
-
update_spec(spec)
|
385
|
+
infrastructure.update_spec(spec)
|
377
386
|
# then update spec with generic changes
|
378
|
-
|
387
|
+
spec = spec.update(bosh_ip, infrastructure.service_ip)
|
388
|
+
|
389
|
+
microbosh_job_instance = MicroboshJobInstance.new(bosh_ip, Config.agent_url, logger)
|
390
|
+
spec = microbosh_job_instance.render_templates(spec)
|
391
|
+
|
392
|
+
agent.run_task(:apply, spec)
|
379
393
|
end
|
380
394
|
|
381
395
|
agent_start
|
382
396
|
end
|
383
397
|
|
384
|
-
|
385
|
-
|
386
|
-
def bosh_ip
|
387
|
-
Config.bosh_ip
|
398
|
+
def save_state
|
399
|
+
deployments_state.save(infrastructure)
|
388
400
|
end
|
389
401
|
|
402
|
+
private
|
403
|
+
|
390
404
|
def agent_stop
|
391
405
|
step 'Stopping agent services' do
|
392
406
|
begin
|
@@ -421,7 +435,7 @@ module Bosh::Deployer
|
|
421
435
|
end
|
422
436
|
|
423
437
|
def wait_until_agent_ready
|
424
|
-
remote_tunnel
|
438
|
+
infrastructure.remote_tunnel
|
425
439
|
wait_until_ready('agent') { agent.ping }
|
426
440
|
end
|
427
441
|
|
@@ -467,16 +481,6 @@ module Bosh::Deployer
|
|
467
481
|
save_state
|
468
482
|
end
|
469
483
|
|
470
|
-
def load_deployments
|
471
|
-
if File.exists?(@state_yml)
|
472
|
-
logger.info("Loading existing deployment data from: #{@state_yml}")
|
473
|
-
Psych.load_file(@state_yml)
|
474
|
-
else
|
475
|
-
logger.info("No existing deployments found (will save to #{@state_yml})")
|
476
|
-
{ 'instances' => [], 'disks' => [] }
|
477
|
-
end
|
478
|
-
end
|
479
|
-
|
480
484
|
def load_apply_spec(dir)
|
481
485
|
load_spec("#{dir}/apply_spec.yml") do
|
482
486
|
err "this isn't a micro bosh stemcell - apply_spec.yml missing"
|
@@ -495,36 +499,9 @@ module Bosh::Deployer
|
|
495
499
|
Psych.load_file(file)
|
496
500
|
end
|
497
501
|
|
498
|
-
def generate_unique_name
|
499
|
-
SecureRandom.uuid
|
500
|
-
end
|
501
|
-
|
502
502
|
def load_state(name)
|
503
|
-
|
504
|
-
|
505
|
-
disk_model.insert_multiple(@deployments['disks']) if disk_model
|
506
|
-
instance_model.insert_multiple(@deployments['instances'])
|
507
|
-
|
508
|
-
@state = instance_model.find(name: name)
|
509
|
-
if @state.nil?
|
510
|
-
@state = instance_model.new
|
511
|
-
@state.uuid = "bm-#{generate_unique_name}"
|
512
|
-
@state.name = name
|
513
|
-
@state.stemcell_sha1 = nil
|
514
|
-
@state.save
|
515
|
-
else
|
516
|
-
discover_bosh_ip
|
517
|
-
end
|
518
|
-
end
|
519
|
-
|
520
|
-
def save_state
|
521
|
-
state.save
|
522
|
-
@deployments['instances'] = instance_model.map { |instance| instance.values }
|
523
|
-
@deployments['disks'] = disk_model.map { |disk| disk.values } if disk_model
|
524
|
-
|
525
|
-
File.open(@state_yml, 'w') do |file|
|
526
|
-
file.write(Psych.dump(@deployments))
|
527
|
-
end
|
503
|
+
deployments_state.load_deployment(name, infrastructure)
|
504
|
+
infrastructure.discover_bosh_ip
|
528
505
|
end
|
529
506
|
|
530
507
|
def run_command(command)
|
@@ -571,4 +548,3 @@ module Bosh::Deployer
|
|
571
548
|
end
|
572
549
|
end
|
573
550
|
end
|
574
|
-
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module Bosh::Deployer
|
5
|
+
class JobTemplate
|
6
|
+
|
7
|
+
class FetchError < Exception
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :name, :version, :sha1, :blobstore_id
|
11
|
+
|
12
|
+
def initialize(template_spec, blobstore)
|
13
|
+
@name = template_spec.fetch('name')
|
14
|
+
@version = template_spec.fetch('version')
|
15
|
+
@sha1 = template_spec.fetch('sha1')
|
16
|
+
@blobstore_id = template_spec.fetch('blobstore_id')
|
17
|
+
@blobstore = blobstore
|
18
|
+
end
|
19
|
+
|
20
|
+
def download_blob
|
21
|
+
uuid = SecureRandom.uuid
|
22
|
+
path = File.join(Dir.tmpdir, "template-#{uuid}")
|
23
|
+
File.open(path, 'w') do |f|
|
24
|
+
blobstore.get(blobstore_id, f)
|
25
|
+
end
|
26
|
+
path
|
27
|
+
rescue Bosh::Blobstore::BlobstoreError => e
|
28
|
+
if e.message.include?('Could not fetch object')
|
29
|
+
raise FetchError.new
|
30
|
+
else
|
31
|
+
raise e
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :blobstore
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'bosh/director/core/templates/job_template_loader'
|
2
|
+
require 'bosh/director/core/templates/job_instance_renderer'
|
3
|
+
require 'bosh/deployer/job_template'
|
4
|
+
require 'blobstore_client'
|
5
|
+
|
6
|
+
module Bosh::Deployer
|
7
|
+
class MicroboshJobInstance
|
8
|
+
|
9
|
+
def initialize(bosh_ip, mbus, logger)
|
10
|
+
@logger = logger
|
11
|
+
|
12
|
+
uri = URI.parse(mbus)
|
13
|
+
user, password = uri.userinfo.split(':', 2)
|
14
|
+
uri.userinfo = ''
|
15
|
+
uri.host = bosh_ip
|
16
|
+
uri.path = '/blobs'
|
17
|
+
@blobstore_options = {
|
18
|
+
'endpoint' => uri.to_s,
|
19
|
+
'user' => user,
|
20
|
+
'password' => password,
|
21
|
+
'ssl_no_verify' => true,
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def render_templates(spec)
|
26
|
+
blobstore = Bosh::Blobstore::DavBlobstoreClient.new(blobstore_options)
|
27
|
+
|
28
|
+
templates = spec['job']['templates'].map do |template|
|
29
|
+
JobTemplate.new(template, blobstore)
|
30
|
+
end
|
31
|
+
|
32
|
+
job_template_loader =
|
33
|
+
Bosh::Director::Core::Templates::JobTemplateLoader.new(logger)
|
34
|
+
job_instance_renderer =
|
35
|
+
Bosh::Director::Core::Templates::JobInstanceRenderer.new(templates, job_template_loader)
|
36
|
+
|
37
|
+
rendered_job_instance = job_instance_renderer.render(spec)
|
38
|
+
rendered_templates_archive = rendered_job_instance.persist(blobstore)
|
39
|
+
|
40
|
+
spec.merge(
|
41
|
+
'rendered_templates_archive' => rendered_templates_archive.spec,
|
42
|
+
'configuration_hash' => rendered_job_instance.configuration_hash,
|
43
|
+
)
|
44
|
+
rescue JobTemplate::FetchError
|
45
|
+
logger.debug('skipping rendering since the agent appears to be ruby')
|
46
|
+
spec
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
attr_reader :spec, :blobstore_options, :logger
|
52
|
+
end
|
53
|
+
end
|
@@ -5,9 +5,9 @@ module Bosh::Deployer
|
|
5
5
|
class Registry
|
6
6
|
attr_reader :port
|
7
7
|
|
8
|
-
def initialize(endpoint, cloud_plugin, cloud_properties,
|
8
|
+
def initialize(endpoint, cloud_plugin, cloud_properties, state, logger)
|
9
9
|
@cloud_properties = cloud_properties
|
10
|
-
@
|
10
|
+
@state = state
|
11
11
|
@logger = logger
|
12
12
|
|
13
13
|
uri = URI.parse(endpoint)
|
@@ -20,7 +20,7 @@ module Bosh::Deployer
|
|
20
20
|
write_configure
|
21
21
|
Sequel.connect(connection_settings) do |db|
|
22
22
|
migrate(db)
|
23
|
-
instances = deployments['registry_instances']
|
23
|
+
instances = state.deployments['registry_instances']
|
24
24
|
db[:registry_instances].insert_multiple(instances) if instances
|
25
25
|
end
|
26
26
|
|
@@ -46,7 +46,7 @@ module Bosh::Deployer
|
|
46
46
|
return unless db_file
|
47
47
|
|
48
48
|
Sequel.connect(connection_settings) do |db|
|
49
|
-
deployments['registry_instances'] = db[:registry_instances].map { |row| row }
|
49
|
+
state.deployments['registry_instances'] = db[:registry_instances].map { |row| row }
|
50
50
|
end
|
51
51
|
ensure
|
52
52
|
db_file.unlink if db_file
|
@@ -62,7 +62,7 @@ module Bosh::Deployer
|
|
62
62
|
private
|
63
63
|
|
64
64
|
attr_reader(
|
65
|
-
:
|
65
|
+
:state,
|
66
66
|
:cloud_properties,
|
67
67
|
:logger,
|
68
68
|
:user,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bosh_cli_plugin_micro
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1975.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: 2014-
|
12
|
+
date: 2014-02-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sqlite3
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 1.
|
37
|
+
version: 1.1975.0
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 1.
|
45
|
+
version: 1.1975.0
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: bosh-stemcell
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - ~>
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 1.
|
53
|
+
version: 1.1975.0
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.
|
61
|
+
version: 1.1975.0
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: bosh-registry
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - ~>
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 1.
|
69
|
+
version: 1.1975.0
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -74,7 +74,7 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - ~>
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: 1.
|
77
|
+
version: 1.1975.0
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
name: agent_client
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,7 +82,7 @@ dependencies:
|
|
82
82
|
requirements:
|
83
83
|
- - ~>
|
84
84
|
- !ruby/object:Gem::Version
|
85
|
-
version: 1.
|
85
|
+
version: 1.1975.0
|
86
86
|
type: :runtime
|
87
87
|
prerelease: false
|
88
88
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -90,7 +90,7 @@ dependencies:
|
|
90
90
|
requirements:
|
91
91
|
- - ~>
|
92
92
|
- !ruby/object:Gem::Version
|
93
|
-
version: 1.
|
93
|
+
version: 1.1975.0
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
95
|
name: bosh_cpi
|
96
96
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,7 +98,7 @@ dependencies:
|
|
98
98
|
requirements:
|
99
99
|
- - ~>
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version: 1.
|
101
|
+
version: 1.1975.0
|
102
102
|
type: :runtime
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -106,7 +106,7 @@ dependencies:
|
|
106
106
|
requirements:
|
107
107
|
- - ~>
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: 1.
|
109
|
+
version: 1.1975.0
|
110
110
|
- !ruby/object:Gem::Dependency
|
111
111
|
name: bosh_aws_cpi
|
112
112
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,7 +114,7 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - ~>
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 1.
|
117
|
+
version: 1.1975.0
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -122,7 +122,7 @@ dependencies:
|
|
122
122
|
requirements:
|
123
123
|
- - ~>
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version: 1.
|
125
|
+
version: 1.1975.0
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: bosh_openstack_cpi
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -130,7 +130,7 @@ dependencies:
|
|
130
130
|
requirements:
|
131
131
|
- - ~>
|
132
132
|
- !ruby/object:Gem::Version
|
133
|
-
version: 1.
|
133
|
+
version: 1.1975.0
|
134
134
|
type: :runtime
|
135
135
|
prerelease: false
|
136
136
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -138,7 +138,7 @@ dependencies:
|
|
138
138
|
requirements:
|
139
139
|
- - ~>
|
140
140
|
- !ruby/object:Gem::Version
|
141
|
-
version: 1.
|
141
|
+
version: 1.1975.0
|
142
142
|
- !ruby/object:Gem::Dependency
|
143
143
|
name: bosh_vcloud_cpi
|
144
144
|
requirement: !ruby/object:Gem::Requirement
|
@@ -162,7 +162,7 @@ dependencies:
|
|
162
162
|
requirements:
|
163
163
|
- - ~>
|
164
164
|
- !ruby/object:Gem::Version
|
165
|
-
version: 1.
|
165
|
+
version: 1.1975.0
|
166
166
|
type: :runtime
|
167
167
|
prerelease: false
|
168
168
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -170,7 +170,39 @@ dependencies:
|
|
170
170
|
requirements:
|
171
171
|
- - ~>
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: 1.
|
173
|
+
version: 1.1975.0
|
174
|
+
- !ruby/object:Gem::Dependency
|
175
|
+
name: bosh-director-core
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
179
|
+
- - ~>
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: 1.1975.0
|
182
|
+
type: :runtime
|
183
|
+
prerelease: false
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
185
|
+
none: false
|
186
|
+
requirements:
|
187
|
+
- - ~>
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: 1.1975.0
|
190
|
+
- !ruby/object:Gem::Dependency
|
191
|
+
name: blobstore_client
|
192
|
+
requirement: !ruby/object:Gem::Requirement
|
193
|
+
none: false
|
194
|
+
requirements:
|
195
|
+
- - ~>
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: 1.1975.0
|
198
|
+
type: :runtime
|
199
|
+
prerelease: false
|
200
|
+
version_requirements: !ruby/object:Gem::Requirement
|
201
|
+
none: false
|
202
|
+
requirements:
|
203
|
+
- - ~>
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: 1.1975.0
|
174
206
|
- !ruby/object:Gem::Dependency
|
175
207
|
name: rspec
|
176
208
|
requirement: !ruby/object:Gem::Requirement
|
@@ -205,7 +237,7 @@ dependencies:
|
|
205
237
|
version: '0'
|
206
238
|
description: ! 'BOSH CLI plugin for Micro BOSH deployment
|
207
239
|
|
208
|
-
|
240
|
+
9c66c4'
|
209
241
|
email: support@cloudfoundry.com
|
210
242
|
executables: []
|
211
243
|
extensions: []
|
@@ -220,6 +252,7 @@ files:
|
|
220
252
|
- lib/bosh/deployer/config.rb
|
221
253
|
- lib/bosh/deployer/configuration.rb
|
222
254
|
- lib/bosh/deployer/deployer_renderer.rb
|
255
|
+
- lib/bosh/deployer/deployments_state.rb
|
223
256
|
- lib/bosh/deployer/director_gateway_error.rb
|
224
257
|
- lib/bosh/deployer/hash_fingerprinter.rb
|
225
258
|
- lib/bosh/deployer/instance_manager.rb
|
@@ -227,7 +260,9 @@ files:
|
|
227
260
|
- lib/bosh/deployer/instance_manager/openstack.rb
|
228
261
|
- lib/bosh/deployer/instance_manager/vcloud.rb
|
229
262
|
- lib/bosh/deployer/instance_manager/vsphere.rb
|
263
|
+
- lib/bosh/deployer/job_template.rb
|
230
264
|
- lib/bosh/deployer/logger_renderer.rb
|
265
|
+
- lib/bosh/deployer/microbosh_job_instance.rb
|
231
266
|
- lib/bosh/deployer/models/instance.rb
|
232
267
|
- lib/bosh/deployer/registry.rb
|
233
268
|
- lib/bosh/deployer/remote_tunnel.rb
|
@@ -258,7 +293,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
258
293
|
version: '0'
|
259
294
|
segments:
|
260
295
|
- 0
|
261
|
-
hash:
|
296
|
+
hash: -912028750024144705
|
262
297
|
requirements: []
|
263
298
|
rubyforge_project:
|
264
299
|
rubygems_version: 1.8.23
|