bosh-director 1.3202.0 → 1.3213.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/db/migrations/director/20151223172000_rename_requires_json.rb +7 -0
- data/db/migrations/director/20160106162749_runtime_configs.rb +19 -0
- data/db/migrations/director/20160106163433_add_runtime_configs_to_deployments.rb +7 -0
- data/db/migrations/director/20160202162216_add_post_start_completed_to_instance.rb +7 -0
- data/db/migrations/director/20160210201838_denormalize_compiled_package_stemcell_id_to_stemcell_name_and_version.rb +57 -0
- data/db/migrations/director/20160219175840_add_column_teams_to_deployments.rb +8 -0
- data/db/migrations/director/20160224222508_add_deployment_name_to_task.rb +7 -0
- data/db/migrations/director/20160225182206_rename_post_start_completed.rb +8 -0
- data/lib/bosh/director.rb +9 -0
- data/lib/bosh/director/api.rb +1 -1
- data/lib/bosh/director/api/api_helper.rb +27 -0
- data/lib/bosh/director/api/controllers/base_controller.rb +28 -5
- data/lib/bosh/director/api/controllers/cloud_configs_controller.rb +4 -3
- data/lib/bosh/director/api/controllers/deployments_controller.rb +165 -81
- data/lib/bosh/director/api/controllers/locks_controller.rb +1 -1
- data/lib/bosh/director/api/controllers/packages_controller.rb +4 -35
- data/lib/bosh/director/api/controllers/releases_controller.rb +6 -4
- data/lib/bosh/director/api/controllers/runtime_configs_controller.rb +41 -0
- data/lib/bosh/director/api/controllers/stemcells_controller.rb +1 -1
- data/lib/bosh/director/api/controllers/tasks_controller.rb +72 -5
- data/lib/bosh/director/api/deployment_manager.rb +10 -42
- data/lib/bosh/director/api/extensions/scoping.rb +11 -24
- data/lib/bosh/director/api/instance_lookup.rb +10 -22
- data/lib/bosh/director/api/instance_manager.rb +27 -15
- data/lib/bosh/director/api/local_identity_provider.rb +0 -8
- data/lib/bosh/director/api/problem_manager.rb +7 -19
- data/lib/bosh/director/api/property_manager.rb +12 -21
- data/lib/bosh/director/api/resurrector_manager.rb +4 -4
- data/lib/bosh/director/api/route_configuration.rb +1 -0
- data/lib/bosh/director/api/runtime_config_manager.rb +35 -0
- data/lib/bosh/director/api/snapshot_manager.rb +2 -2
- data/lib/bosh/director/api/task_helper.rb +2 -1
- data/lib/bosh/director/api/task_manager.rb +2 -8
- data/lib/bosh/director/api/uaa_identity_provider.rb +0 -16
- data/lib/bosh/director/blob_util.rb +3 -2
- data/lib/bosh/director/cloudcheck_helper.rb +17 -3
- data/lib/bosh/director/compile_task.rb +53 -24
- data/lib/bosh/director/compile_task_generator.rb +6 -6
- data/lib/bosh/director/compiled_package_group.rb +4 -3
- data/lib/bosh/director/compiled_release.rb +6 -0
- data/lib/bosh/director/compiled_release/manifest.rb +30 -0
- data/lib/bosh/director/compiled_release_manifest.rb +3 -3
- data/lib/bosh/director/config.rb +11 -1
- data/lib/bosh/director/deployment_plan.rb +1 -0
- data/lib/bosh/director/deployment_plan/assembler.rb +6 -2
- data/lib/bosh/director/deployment_plan/cloud_manifest_parser.rb +26 -10
- data/lib/bosh/director/deployment_plan/compilation_config.rb +43 -7
- data/lib/bosh/director/deployment_plan/compilation_instance_pool.rb +10 -3
- data/lib/bosh/director/deployment_plan/deployment_repo.rb +4 -10
- data/lib/bosh/director/deployment_plan/dynamic_network.rb +1 -1
- data/lib/bosh/director/deployment_plan/instance.rb +36 -17
- data/lib/bosh/director/deployment_plan/instance_plan.rb +13 -2
- data/lib/bosh/director/deployment_plan/instance_spec.rb +12 -4
- data/lib/bosh/director/deployment_plan/job.rb +73 -39
- data/lib/bosh/director/deployment_plan/job_availability_zone_parser.rb +4 -4
- data/lib/bosh/director/deployment_plan/job_migrator.rb +7 -7
- data/lib/bosh/director/deployment_plan/job_network_parser.rb +6 -6
- data/lib/bosh/director/deployment_plan/job_spec_parser.rb +91 -33
- data/lib/bosh/director/deployment_plan/links/link.rb +9 -4
- data/lib/bosh/director/deployment_plan/links/link_lookup.rb +23 -15
- data/lib/bosh/director/deployment_plan/links/link_path.rb +168 -15
- data/lib/bosh/director/deployment_plan/links/links_resolver.rb +34 -32
- data/lib/bosh/director/deployment_plan/links/template_link.rb +28 -8
- data/lib/bosh/director/deployment_plan/manifest_validator.rb +1 -1
- data/lib/bosh/director/deployment_plan/network_settings.rb +27 -13
- data/lib/bosh/director/deployment_plan/package_validator.rb +9 -5
- data/lib/bosh/director/deployment_plan/placement_planner/networks_to_static_ips.rb +4 -4
- data/lib/bosh/director/deployment_plan/planner.rb +31 -7
- data/lib/bosh/director/deployment_plan/planner_factory.rb +147 -6
- data/lib/bosh/director/deployment_plan/runtime_manifest_parser.rb +142 -0
- data/lib/bosh/director/deployment_plan/stemcell.rb +2 -2
- data/lib/bosh/director/deployment_plan/steps/package_compile_step.rb +3 -2
- data/lib/bosh/director/deployment_plan/template.rb +93 -8
- data/lib/bosh/director/deployment_plan/update_config.rb +10 -0
- data/lib/bosh/director/deployment_plan/vm_extension.rb +27 -0
- data/lib/bosh/director/errand/runner.rb +1 -1
- data/lib/bosh/director/errors.rb +11 -1
- data/lib/bosh/director/instance_updater.rb +46 -57
- data/lib/bosh/director/instance_updater/instance_state.rb +9 -0
- data/lib/bosh/director/instance_updater/state_applier.rb +18 -5
- data/lib/bosh/director/job_queue.rb +2 -2
- data/lib/bosh/director/job_renderer.rb +2 -2
- data/lib/bosh/director/job_updater.rb +7 -1
- data/lib/bosh/director/jobs/attach_disk.rb +2 -2
- data/lib/bosh/director/jobs/cloud_check/apply_resolutions.rb +6 -1
- data/lib/bosh/director/jobs/cloud_check/scan_and_fix.rb +14 -3
- data/lib/bosh/director/jobs/export_release.rb +1 -1
- data/lib/bosh/director/jobs/fetch_logs.rb +1 -4
- data/lib/bosh/director/jobs/helpers/compiled_package_deleter.rb +1 -2
- data/lib/bosh/director/jobs/helpers/stemcell_deleter.rb +0 -16
- data/lib/bosh/director/jobs/release/release_job.rb +7 -7
- data/lib/bosh/director/jobs/run_errand.rb +5 -5
- data/lib/bosh/director/jobs/ssh.rb +3 -3
- data/lib/bosh/director/jobs/update_deployment.rb +41 -5
- data/lib/bosh/director/jobs/update_release.rb +78 -82
- data/lib/bosh/director/jobs/update_stemcell.rb +1 -1
- data/lib/bosh/director/jobs/vm_state.rb +34 -21
- data/lib/bosh/director/key_generator.rb +54 -0
- data/lib/bosh/director/lock.rb +2 -2
- data/lib/bosh/director/log_bundles_cleaner.rb +1 -0
- data/lib/bosh/director/manifest/changeset.rb +39 -22
- data/lib/bosh/director/manifest/diff_lines.rb +1 -27
- data/lib/bosh/director/manifest/manifest.rb +22 -7
- data/lib/bosh/director/manifest/redactor.rb +44 -0
- data/lib/bosh/director/models.rb +1 -0
- data/lib/bosh/director/models/compiled_package.rb +21 -15
- data/lib/bosh/director/models/deployment.rb +10 -0
- data/lib/bosh/director/models/instance.rb +2 -1
- data/lib/bosh/director/models/release_version.rb +0 -16
- data/lib/bosh/director/models/runtime_config.rb +19 -0
- data/lib/bosh/director/models/template.rb +4 -4
- data/lib/bosh/director/package_dependencies_manager.rb +22 -0
- data/lib/bosh/director/password_helper.rb +18 -0
- data/lib/bosh/director/permission_authorizer.rb +50 -30
- data/lib/bosh/director/post_deployment_script_runner.rb +40 -0
- data/lib/bosh/director/problem_handlers/missing_disk.rb +2 -2
- data/lib/bosh/director/problem_resolver.rb +8 -2
- data/lib/bosh/director/problem_scanner/scanner.rb +1 -1
- data/lib/bosh/director/problem_scanner/vm_scan_stage.rb +1 -1
- data/lib/bosh/director/validation_helper.rb +5 -5
- data/lib/bosh/director/version.rb +1 -1
- data/lib/bosh/director/vm_creator.rb +8 -0
- data/lib/cloud/dummy.rb +1 -0
- metadata +51 -19
- data/lib/bosh/director/api/vm_state_manager.rb +0 -9
- data/lib/bosh/director/compiled_package/blob_sha_mismatch_error.rb +0 -5
- data/lib/bosh/director/compiled_package/compiled_package.rb +0 -30
@@ -15,7 +15,7 @@ module Bosh
|
|
15
15
|
manifest['jobs'].each do |job|
|
16
16
|
if job.has_key?('migrated_from')
|
17
17
|
raise Bosh::Director::DeploymentInvalidProperty,
|
18
|
-
"Deployment manifest
|
18
|
+
"Deployment manifest instance groups contain 'migrated_from', but it can only be used with cloud-config."
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
module Bosh::Director::DeploymentPlan
|
2
2
|
class NetworkSettings
|
3
|
-
def initialize(job_name, deployment_name, default_network, desired_reservations,
|
3
|
+
def initialize(job_name, deployment_name, default_network, desired_reservations, current_networks, availability_zone, instance_index, instance_id, dns_manager)
|
4
4
|
@job_name = job_name
|
5
5
|
@desired_reservations = desired_reservations
|
6
6
|
@default_network = default_network
|
7
7
|
@deployment_name = deployment_name
|
8
|
-
@state = state
|
9
8
|
@availability_zone = availability_zone
|
10
9
|
@instance_index = instance_index
|
11
10
|
@instance_id = instance_id
|
12
11
|
@dns_manager = dns_manager
|
12
|
+
@current_networks = current_networks
|
13
13
|
end
|
14
14
|
|
15
15
|
def to_hash
|
@@ -22,16 +22,12 @@ module Bosh::Director::DeploymentPlan
|
|
22
22
|
@desired_reservations.each do |reservation|
|
23
23
|
network_name = reservation.network.name
|
24
24
|
network_settings[network_name] = reservation.network.network_settings(reservation, default_properties[network_name], @availability_zone)
|
25
|
-
|
26
25
|
# Somewhat of a hack: for dynamic networks we might know IP address, Netmask & Gateway
|
27
26
|
# if they're featured in agent state, in that case we put them into network spec to satisfy
|
28
27
|
# ConfigurationHasher in both agent and director.
|
29
|
-
if @
|
30
|
-
@state['networks'].is_a?(Hash) &&
|
31
|
-
@state['networks'][network_name].is_a?(Hash) &&
|
32
|
-
network_settings[network_name]['type'] == 'dynamic'
|
28
|
+
if @current_networks.is_a?(Hash) && @current_networks[network_name].is_a?(Hash) && network_settings[network_name]['type'] == 'dynamic'
|
33
29
|
%w(ip netmask gateway).each do |key|
|
34
|
-
network_settings[network_name][key] = @
|
30
|
+
network_settings[network_name][key] = @current_networks[network_name][key] unless @current_networks[network_name][key].nil?
|
35
31
|
end
|
36
32
|
end
|
37
33
|
end
|
@@ -50,16 +46,34 @@ module Bosh::Director::DeploymentPlan
|
|
50
46
|
dns_record_info
|
51
47
|
end
|
52
48
|
|
49
|
+
def network_address(preferred_network_name = nil)
|
50
|
+
network_name = preferred_network_name || @default_network['gateway']
|
51
|
+
network_hash = to_hash
|
52
|
+
|
53
|
+
if network_hash[network_name]['type'] == 'dynamic'
|
54
|
+
address = @dns_manager.dns_record_name(@instance_id, @job_name, network_name, @deployment_name)
|
55
|
+
else
|
56
|
+
address = network_hash[network_name]['ip']
|
57
|
+
end
|
58
|
+
|
59
|
+
address
|
60
|
+
end
|
61
|
+
|
53
62
|
def network_addresses
|
54
63
|
network_addresses = {}
|
64
|
+
|
55
65
|
to_hash.each do |network_name, network|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
66
|
+
if network['type'] == 'dynamic'
|
67
|
+
address = @dns_manager.dns_record_name(@instance_id, @job_name, network_name, @deployment_name)
|
68
|
+
else
|
69
|
+
address = network['ip']
|
70
|
+
end
|
71
|
+
|
72
|
+
network_addresses[network_name] = address
|
61
73
|
end
|
74
|
+
|
62
75
|
network_addresses
|
63
76
|
end
|
77
|
+
|
64
78
|
end
|
65
79
|
end
|
@@ -6,19 +6,23 @@ module Bosh::Director
|
|
6
6
|
@logger = logger
|
7
7
|
end
|
8
8
|
|
9
|
-
def validate(release_version_model,
|
9
|
+
def validate(release_version_model, stemcell_model)
|
10
10
|
release_desc = "#{release_version_model.release.name}/#{release_version_model.version}"
|
11
11
|
|
12
12
|
@logger.debug("Validating packages for release '#{release_desc}'")
|
13
13
|
release_version_model.packages.each do |package|
|
14
|
-
packages_list = release_version_model.transitive_dependencies(package)
|
14
|
+
packages_list = Bosh::Director::PackageDependenciesManager.new(release_version_model).transitive_dependencies(package)
|
15
15
|
packages_list << package
|
16
16
|
packages_list.each do |needed_package|
|
17
17
|
if needed_package.sha1.nil? || needed_package.blobstore_id.nil?
|
18
|
-
compiled_packages_list = Bosh::Director::Models::CompiledPackage
|
19
|
-
|
18
|
+
compiled_packages_list = Bosh::Director::Models::CompiledPackage.where(:package_id => needed_package.id,
|
19
|
+
:stemcell_os => stemcell_model.operating_system).all
|
20
|
+
compiled_packages_list = compiled_packages_list.select do |compiled_package|
|
21
|
+
Bosh::Common::Version::StemcellVersion.match(compiled_package.stemcell_version, stemcell_model.version)
|
22
|
+
end
|
23
|
+
if compiled_packages_list.empty?
|
20
24
|
@faults[release_desc] ||= Set.new
|
21
|
-
@faults[release_desc] << Fault.new(needed_package,
|
25
|
+
@faults[release_desc] << Fault.new(needed_package, stemcell_model)
|
22
26
|
end
|
23
27
|
end
|
24
28
|
end
|
@@ -19,7 +19,7 @@ module Bosh
|
|
19
19
|
subnet_for_ip = subnets.find { |subnet| subnet.static_ips.include?(static_ip) }
|
20
20
|
if subnet_for_ip.nil?
|
21
21
|
raise JobNetworkInstanceIpMismatch,
|
22
|
-
"
|
22
|
+
"Instance group '#{job_name}' with network '#{job_network.name}' declares static ip '#{format_ip(static_ip)}', " +
|
23
23
|
"which belongs to no subnet"
|
24
24
|
end
|
25
25
|
az_names = subnet_for_ip.availability_zone_names.nil? ? [nil] : subnet_for_ip.availability_zone_names
|
@@ -44,7 +44,7 @@ module Bosh
|
|
44
44
|
end
|
45
45
|
|
46
46
|
raise JobInvalidAvailabilityZone,
|
47
|
-
"
|
47
|
+
"Instance group '#{@job_name}' subnets declare availability zones and the instance group does not"
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -59,7 +59,7 @@ module Bosh
|
|
59
59
|
|
60
60
|
if non_desired_ip_to_az
|
61
61
|
raise JobStaticIpsFromInvalidAvailabilityZone,
|
62
|
-
"
|
62
|
+
"Instance group '#{@job_name}' declares static ip '#{format_ip(non_desired_ip_to_az.ip)}' which does not belong to any of the instance group's availability zones."
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
@@ -79,7 +79,7 @@ module Bosh
|
|
79
79
|
def distribute_evenly_per_zone
|
80
80
|
best_combination = BruteForceIpAllocation.new(@networks_to_static_ips).find_best_combination
|
81
81
|
if best_combination.nil?
|
82
|
-
raise JobNetworkInstanceIpMismatch, "Failed to evenly distribute static IPs between zones for
|
82
|
+
raise JobNetworkInstanceIpMismatch, "Failed to evenly distribute static IPs between zones for instance group '#{@job_name}'"
|
83
83
|
end
|
84
84
|
@networks_to_static_ips = best_combination
|
85
85
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'bosh/director/deployment_plan/deployment_spec_parser'
|
2
2
|
require 'bosh/director/deployment_plan/cloud_manifest_parser'
|
3
|
+
require 'bosh/director/deployment_plan/runtime_manifest_parser'
|
3
4
|
require 'bosh/director/deployment_plan/disk_type'
|
4
5
|
require 'forwardable'
|
5
6
|
require 'common/deep_copy'
|
@@ -51,15 +52,14 @@ module Bosh::Director
|
|
51
52
|
# @return [Boolean] Indicates whether VMs should be drained
|
52
53
|
attr_reader :skip_drain
|
53
54
|
|
54
|
-
def initialize(attrs, manifest_text, cloud_config, deployment_model, options = {})
|
55
|
-
@cloud_config = cloud_config
|
56
|
-
|
55
|
+
def initialize(attrs, manifest_text, cloud_config, runtime_config, deployment_model, options = {})
|
57
56
|
@name = attrs.fetch(:name)
|
58
57
|
@properties = attrs.fetch(:properties)
|
59
58
|
@releases = {}
|
60
59
|
|
61
60
|
@manifest_text = Bosh::Common::DeepCopy.copy(manifest_text)
|
62
61
|
@cloud_config = cloud_config
|
62
|
+
@runtime_config = runtime_config
|
63
63
|
@model = deployment_model
|
64
64
|
|
65
65
|
@stemcells = {}
|
@@ -88,6 +88,8 @@ module Bosh::Director
|
|
88
88
|
:resource_pool,
|
89
89
|
:vm_types,
|
90
90
|
:vm_type,
|
91
|
+
:vm_extensions,
|
92
|
+
:vm_extension,
|
91
93
|
:add_resource_pool,
|
92
94
|
:disk_types,
|
93
95
|
:disk_type,
|
@@ -98,7 +100,7 @@ module Bosh::Director
|
|
98
100
|
Canonicalizer.canonicalize(@name)
|
99
101
|
end
|
100
102
|
|
101
|
-
def bind_models
|
103
|
+
def bind_models(skip_links_binding = false)
|
102
104
|
stemcell_manager = Api::StemcellManager.new
|
103
105
|
dns_manager = DnsManagerProvider.create
|
104
106
|
assembler = DeploymentPlan::Assembler.new(
|
@@ -109,7 +111,7 @@ module Bosh::Director
|
|
109
111
|
@logger
|
110
112
|
)
|
111
113
|
|
112
|
-
assembler.bind_models
|
114
|
+
assembler.bind_models(skip_links_binding)
|
113
115
|
end
|
114
116
|
|
115
117
|
def compile_packages
|
@@ -209,7 +211,7 @@ module Bosh::Director
|
|
209
211
|
def add_job(job)
|
210
212
|
if @jobs_canonical_name_index.include?(job.canonical_name)
|
211
213
|
raise DeploymentCanonicalJobNameTaken,
|
212
|
-
"Invalid
|
214
|
+
"Invalid instance group name '#{job.name}', canonical name already taken"
|
213
215
|
end
|
214
216
|
|
215
217
|
@jobs << job
|
@@ -225,7 +227,19 @@ module Bosh::Director
|
|
225
227
|
end
|
226
228
|
|
227
229
|
def jobs_starting_on_deploy
|
228
|
-
|
230
|
+
jobs = []
|
231
|
+
|
232
|
+
@jobs.each do |job|
|
233
|
+
if job.is_service?
|
234
|
+
jobs << job
|
235
|
+
elsif job.is_errand?
|
236
|
+
if job.instances.any? { |i| nil != i.model && !i.model.vm_cid.to_s.empty? }
|
237
|
+
jobs << job
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
jobs
|
229
243
|
end
|
230
244
|
|
231
245
|
def persist_updates!
|
@@ -241,6 +255,7 @@ module Bosh::Director
|
|
241
255
|
|
242
256
|
model.manifest = Psych.dump(@manifest_text)
|
243
257
|
model.cloud_config = @cloud_config
|
258
|
+
model.runtime_config = @runtime_config
|
244
259
|
model.link_spec = @link_spec
|
245
260
|
model.save
|
246
261
|
end
|
@@ -284,6 +299,7 @@ module Bosh::Director
|
|
284
299
|
@global_network_resolver = options.fetch(:global_network_resolver)
|
285
300
|
@resource_pools = self.class.index_by_name(options.fetch(:resource_pools))
|
286
301
|
@vm_types = self.class.index_by_name(options.fetch(:vm_types, {}))
|
302
|
+
@vm_extensions = self.class.index_by_name(options.fetch(:vm_extensions, {}))
|
287
303
|
@disk_types = self.class.index_by_name(options.fetch(:disk_types))
|
288
304
|
@availability_zones = options.fetch(:availability_zones_list)
|
289
305
|
@compilation = options.fetch(:compilation)
|
@@ -332,6 +348,14 @@ module Bosh::Director
|
|
332
348
|
@vm_types[name]
|
333
349
|
end
|
334
350
|
|
351
|
+
def vm_extensions
|
352
|
+
@vm_extensions.values
|
353
|
+
end
|
354
|
+
|
355
|
+
def vm_extension(name)
|
356
|
+
@vm_extensions[name]
|
357
|
+
end
|
358
|
+
|
335
359
|
def add_resource_pool(resource_pool)
|
336
360
|
@resource_pools[resource_pool.name] = resource_pool
|
337
361
|
end
|
@@ -33,17 +33,17 @@ module Bosh
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def create_from_model(deployment_model, options={})
|
36
|
-
manifest = Manifest.load_from_text(deployment_model.manifest, deployment_model.cloud_config)
|
37
|
-
create_from_manifest(manifest, deployment_model.cloud_config, options)
|
36
|
+
manifest = Manifest.load_from_text(deployment_model.manifest, deployment_model.cloud_config, deployment_model.runtime_config)
|
37
|
+
create_from_manifest(manifest, deployment_model.cloud_config, deployment_model.runtime_config, options)
|
38
38
|
end
|
39
39
|
|
40
|
-
def create_from_manifest(manifest, cloud_config, options)
|
41
|
-
parse_from_manifest(manifest, cloud_config, options)
|
40
|
+
def create_from_manifest(manifest, cloud_config, runtime_config, options)
|
41
|
+
parse_from_manifest(manifest, cloud_config, runtime_config, options)
|
42
42
|
end
|
43
43
|
|
44
44
|
private
|
45
45
|
|
46
|
-
def parse_from_manifest(manifest, cloud_config, options)
|
46
|
+
def parse_from_manifest(manifest, cloud_config, runtime_config, options)
|
47
47
|
manifest.resolve_aliases
|
48
48
|
@manifest_validator.validate(manifest.manifest_hash, manifest.cloud_config_hash)
|
49
49
|
deployment_manifest, cloud_manifest = @deployment_manifest_migrator.migrate(manifest.manifest_hash, manifest.cloud_config_hash)
|
@@ -67,15 +67,156 @@ module Bosh
|
|
67
67
|
@logger.info('Creating deployment plan')
|
68
68
|
@logger.info("Deployment plan options: #{plan_options}")
|
69
69
|
|
70
|
-
deployment = Planner.new(attrs, deployment_manifest, cloud_config, deployment_model, plan_options)
|
70
|
+
deployment = Planner.new(attrs, deployment_manifest, cloud_config, runtime_config, deployment_model, plan_options)
|
71
71
|
global_network_resolver = GlobalNetworkResolver.new(deployment)
|
72
72
|
|
73
73
|
ip_provider_factory = IpProviderFactory.new(deployment.using_global_networking?, @logger)
|
74
74
|
deployment.cloud_planner = CloudManifestParser.new(@logger).parse(cloud_manifest, global_network_resolver, ip_provider_factory)
|
75
75
|
DeploymentSpecParser.new(deployment, Config.event_log, @logger).parse(deployment_manifest, plan_options)
|
76
|
+
|
77
|
+
if runtime_config
|
78
|
+
RuntimeManifestParser.new(@logger, deployment).parse(runtime_config.manifest)
|
79
|
+
end
|
80
|
+
|
81
|
+
process_links(deployment)
|
82
|
+
|
76
83
|
DeploymentValidator.new.validate(deployment)
|
77
84
|
deployment
|
78
85
|
end
|
86
|
+
|
87
|
+
def process_links(deployment)
|
88
|
+
errors = []
|
89
|
+
|
90
|
+
deployment.jobs.each do |current_job|
|
91
|
+
current_job.templates.each do |template|
|
92
|
+
if template.link_infos.has_key?(current_job.name) && template.link_infos[current_job.name].has_key?('consumes')
|
93
|
+
template.link_infos[current_job.name]['consumes'].each do |name, source|
|
94
|
+
link_path = LinkPath.new(deployment, current_job.name, template.name)
|
95
|
+
|
96
|
+
begin
|
97
|
+
link_path.parse(source)
|
98
|
+
rescue Exception => e
|
99
|
+
errors.push e
|
100
|
+
end
|
101
|
+
|
102
|
+
if !link_path.skip
|
103
|
+
current_job.add_link_path(template.name, name, link_path)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
## Choose between using template-scoped and other props.
|
109
|
+
## if job manifest had a "properties key" in the template block
|
110
|
+
if template.template_scoped_properties.has_key?(current_job.name)
|
111
|
+
scoped_properties = template.template_scoped_properties[current_job.name]
|
112
|
+
else
|
113
|
+
scoped_properties = current_job.all_properties || {}
|
114
|
+
end
|
115
|
+
|
116
|
+
if template.link_infos.has_key?(current_job.name) && template.link_infos[current_job.name].has_key?('provides')
|
117
|
+
template.link_infos[current_job.name]['provides'].each do |link_name, provided_link|
|
118
|
+
if provided_link['properties']
|
119
|
+
## Get default values for this job
|
120
|
+
default_properties = get_default_properties(deployment, template)
|
121
|
+
|
122
|
+
provided_link['mapped_properties'] = process_link_properties(scoped_properties, default_properties, provided_link['properties'], errors)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
if errors.length > 0
|
130
|
+
message = 'Unable to process links for deployment. Errors are:'
|
131
|
+
|
132
|
+
errors.each do |e|
|
133
|
+
message = "#{message}\n - \"#{e.message.gsub(/\n/, "\n ")}\""
|
134
|
+
end
|
135
|
+
|
136
|
+
raise message
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def get_default_properties(deployment, template)
|
141
|
+
release_manager = Api::ReleaseManager.new
|
142
|
+
|
143
|
+
release_versions_templates_models_hash = {}
|
144
|
+
|
145
|
+
template_name = template.name
|
146
|
+
release_name = template.release.name
|
147
|
+
|
148
|
+
release = deployment.release(release_name)
|
149
|
+
|
150
|
+
if !release_versions_templates_models_hash.has_key?(release_name)
|
151
|
+
release_model = release_manager.find_by_name(release_name)
|
152
|
+
current_release_version = release_manager.find_version(release_model, release.version)
|
153
|
+
release_versions_templates_models_hash[release_name] = current_release_version.templates
|
154
|
+
end
|
155
|
+
|
156
|
+
templates_models_list = release_versions_templates_models_hash[release_name]
|
157
|
+
current_template_model = templates_models_list.find {|target| target.name == template_name }
|
158
|
+
|
159
|
+
if current_template_model.properties != nil
|
160
|
+
default_prop = {}
|
161
|
+
default_prop['properties'] = current_template_model.properties
|
162
|
+
default_prop["template_name"] = template.name
|
163
|
+
return default_prop
|
164
|
+
end
|
165
|
+
|
166
|
+
return {"template_name" => template.name}
|
167
|
+
end
|
168
|
+
|
169
|
+
def process_link_properties(scoped_properties, default_properties, link_property_list, errors)
|
170
|
+
mapped_properties = {}
|
171
|
+
|
172
|
+
link_property_list.each do |link_property| #list of properties
|
173
|
+
previous_property_in_loop = {}
|
174
|
+
current_property_in_loop = scoped_properties
|
175
|
+
mapped_properties_in_loop = mapped_properties
|
176
|
+
|
177
|
+
use_defaults = false
|
178
|
+
property_path = link_property.split(".")
|
179
|
+
property_path.each do |key|
|
180
|
+
if !current_property_in_loop || !current_property_in_loop.has_key?(key)
|
181
|
+
use_defaults = true
|
182
|
+
else
|
183
|
+
current_property_in_loop = current_property_in_loop[key]
|
184
|
+
end
|
185
|
+
|
186
|
+
if !mapped_properties_in_loop.has_key?(key)
|
187
|
+
mapped_properties_in_loop[key] = {}
|
188
|
+
end
|
189
|
+
previous_property_in_loop = mapped_properties_in_loop
|
190
|
+
mapped_properties_in_loop = mapped_properties_in_loop[key]
|
191
|
+
end
|
192
|
+
|
193
|
+
if use_defaults
|
194
|
+
if default_properties.has_key?('properties') && default_properties['properties'].has_key?(link_property)
|
195
|
+
if default_properties['properties'][link_property].has_key?('default')
|
196
|
+
previous_property_in_loop[property_path.last()] = default_properties['properties'][link_property]['default']
|
197
|
+
else
|
198
|
+
e = Exception.new("Link property #{link_property} in template #{default_properties['template_name']} has no default value or value supplied by the deployment manifest")
|
199
|
+
errors.push(e)
|
200
|
+
end
|
201
|
+
else
|
202
|
+
e = Exception.new("Link property #{link_property} in template #{default_properties['template_name']} is not defined in release spec")
|
203
|
+
errors.push(e)
|
204
|
+
end
|
205
|
+
else
|
206
|
+
previous_property_in_loop[property_path.last()] = current_property_in_loop
|
207
|
+
end
|
208
|
+
|
209
|
+
# if use_defaults && !default_properties.has_key?("properties") && !default_properties['properties'][link_property].has_key?('default')
|
210
|
+
# e = Exception.new("Property #{link_property} in template #{default_properties['template_name']} has no default value or value supplied by the deployment manifest")
|
211
|
+
# errors.push(e)
|
212
|
+
# elsif use_defaults
|
213
|
+
# previous_property_in_loop[property_path.last()] = default_properties['properties'][link_property]['default']
|
214
|
+
# else
|
215
|
+
# previous_property_in_loop[property_path.last()] = current_property_in_loop
|
216
|
+
# end
|
217
|
+
end
|
218
|
+
return mapped_properties
|
219
|
+
end
|
79
220
|
end
|
80
221
|
end
|
81
222
|
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module Bosh::Director
|
2
|
+
module DeploymentPlan
|
3
|
+
class RuntimeManifestParser
|
4
|
+
include ValidationHelper
|
5
|
+
|
6
|
+
def initialize(logger, deployment=nil)
|
7
|
+
@deployment = deployment
|
8
|
+
@logger = logger
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse(runtime_manifest)
|
12
|
+
parse_releases(runtime_manifest)
|
13
|
+
parse_addons(runtime_manifest)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def parse_releases(runtime_manifest)
|
19
|
+
@release_specs = []
|
20
|
+
|
21
|
+
if runtime_manifest['release']
|
22
|
+
if runtime_manifest['releases']
|
23
|
+
raise RuntimeAmbiguousReleaseSpec,
|
24
|
+
"Runtime manifest contains both `release' and `releases' " +
|
25
|
+
'sections, please use one of the two.'
|
26
|
+
end
|
27
|
+
@release_specs << runtime_manifest['release']
|
28
|
+
else
|
29
|
+
safe_property(runtime_manifest, 'releases', :class => Array).each do |release|
|
30
|
+
@release_specs << release
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
@release_specs.each do |release_spec|
|
35
|
+
if release_spec['version'] == 'latest'
|
36
|
+
raise RuntimeInvalidReleaseVersion,
|
37
|
+
"Runtime manifest contains the release `#{release_spec['name']}' with version as `latest'. " +
|
38
|
+
"Please specify the actual version string."
|
39
|
+
end
|
40
|
+
|
41
|
+
if @deployment
|
42
|
+
deployment_release = @deployment.release(release_spec["name"])
|
43
|
+
if deployment_release
|
44
|
+
if deployment_release.version != release_spec["version"]
|
45
|
+
raise RuntimeInvalidDeploymentRelease, "Runtime manifest specifies release `#{release_spec["name"]}' with version as `#{release_spec["version"]}'. " +
|
46
|
+
"This conflicts with version `#{deployment_release.version}' specified in the deployment manifest."
|
47
|
+
else
|
48
|
+
next
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
release_version = DeploymentPlan::ReleaseVersion.new(@deployment.model, release_spec)
|
53
|
+
release_version.bind_model
|
54
|
+
|
55
|
+
@deployment.add_release(release_version)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_addons(runtime_manifest)
|
61
|
+
addons = safe_property(runtime_manifest, 'addons', :class => Array, :default => [])
|
62
|
+
addons.each do |addon_spec|
|
63
|
+
deployment_plan_templates = []
|
64
|
+
|
65
|
+
addon_jobs = safe_property(addon_spec, 'jobs', :class => Array, :default => [])
|
66
|
+
|
67
|
+
addon_jobs.each do |job|
|
68
|
+
if !@release_specs.find { |release_spec| release_spec['name'] == job['release'] }
|
69
|
+
raise RuntimeReleaseNotListedInReleases,
|
70
|
+
"Runtime manifest specifies job `#{job['name']}' which is defined in `#{job['release']}', but `#{job['release']}' is not listed in the releases section."
|
71
|
+
end
|
72
|
+
|
73
|
+
if @deployment
|
74
|
+
valid_release_versions = @deployment.releases.map {|r| r.name }
|
75
|
+
deployment_release_ids = Models::Release.where(:name => valid_release_versions).map {|r| r.id}
|
76
|
+
deployment_jobs = @deployment.jobs
|
77
|
+
|
78
|
+
templates_from_model = Models::Template.where(:name => job['name'], :release_id => deployment_release_ids)
|
79
|
+
if templates_from_model == nil
|
80
|
+
raise "Job '#{job['name']}' not found in Template table"
|
81
|
+
end
|
82
|
+
|
83
|
+
release = @deployment.release(job['release'])
|
84
|
+
release.bind_model
|
85
|
+
|
86
|
+
template = DeploymentPlan::Template.new(release, job['name'])
|
87
|
+
|
88
|
+
deployment_jobs.each do |j|
|
89
|
+
templates_from_model.each do |template_from_model|
|
90
|
+
if template_from_model.consumes != nil
|
91
|
+
template_from_model.consumes.each do |consumes|
|
92
|
+
template.add_link_info(j.name, 'consumes', consumes["name"], consumes)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
if template_from_model.provides != nil
|
96
|
+
template_from_model.provides.each do |provides|
|
97
|
+
template.add_link_info(j.name, 'provides', provides["name"], provides)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
provides_links = safe_property(job, 'provides', class: Hash, optional: true)
|
103
|
+
provides_links.to_a.each do |link_name, source|
|
104
|
+
template.add_link_info(j.name, "provides", link_name, source)
|
105
|
+
end
|
106
|
+
|
107
|
+
consumes_links = safe_property(job, 'consumes', class: Hash, optional: true)
|
108
|
+
consumes_links.to_a.each do |link_name, source|
|
109
|
+
template.add_link_info(j.name, 'consumes', link_name, source)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
template.bind_models
|
114
|
+
deployment_plan_templates.push(template)
|
115
|
+
|
116
|
+
deployment_jobs.each do |job|
|
117
|
+
merge_addon(job, deployment_plan_templates, addon_spec['properties'])
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def merge_addon(job, templates, properties)
|
126
|
+
if job.templates
|
127
|
+
job.templates.concat(templates)
|
128
|
+
else
|
129
|
+
job.templates = templates
|
130
|
+
end
|
131
|
+
|
132
|
+
if properties
|
133
|
+
if job.all_properties
|
134
|
+
job.all_properties.merge!(properties)
|
135
|
+
else
|
136
|
+
job.all_properties = properties
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|