bosh_cli_plugin_micro 1.1868.0 → 1.1975.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|