class Bosh::Director::DeploymentPlan::InstanceGroupSpecParser
Public Class Methods
new(deployment, event_log, logger)
click to toggle source
@param [Bosh::Director::DeploymentPlan] deployment Deployment plan
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 11 def initialize(deployment, event_log, logger) @deployment = deployment @event_log = event_log @logger = logger end
Public Instance Methods
parse(job_spec, options = {})
click to toggle source
@param [Hash] job_spec Raw job spec from the deployment manifest @return [DeploymentPlan::Job] Job as build from job_spec
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 19 def parse(job_spec, options = {}) @job_spec = job_spec @job = InstanceGroup.new(@logger) parse_name parse_lifecycle parse_release validate_templates parse_template parse_templates check_template_uniqueness parse_disk parse_properties parse_resource_pool check_remove_dev_tools parse_options = {} parse_options['canaries'] = options['canaries'] if options['canaries'] parse_options['max_in_flight'] = options['max_in_flight'] if options['max_in_flight'] parse_update_config(parse_options) networks = JobNetworksParser.new(Network::VALID_DEFAULTS).parse(@job_spec, @job.name, @deployment.networks) @job.networks = networks assign_default_networks(networks) availability_zones = JobAvailabilityZoneParser.new.parse(@job_spec, @job, @deployment, networks) @job.availability_zones = availability_zones parse_migrated_from desired_instances = parse_desired_instances(availability_zones, networks) @job.desired_instances = desired_instances @job end
Private Instance Methods
assign_default_networks(networks)
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 404 def assign_default_networks(networks) Network::VALID_DEFAULTS.each do |property| network = networks.find { |network| network.default_for?(property) } @job.default_network[property] = network.name if network end end
check_remove_dev_tools()
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 411 def check_remove_dev_tools if Config.remove_dev_tools @job.env.spec['bosh'] ||= {} unless @job.env.spec['bosh'].has_key?('remove_dev_tools') @job.env.spec['bosh']['remove_dev_tools'] = Config.remove_dev_tools end end end
check_template_uniqueness()
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 202 def check_template_uniqueness all_names = @job.templates.map(&:name) @job.templates.each do |template| if all_names.count(template.name) > 1 raise JobInvalidTemplates, "Colocated job '#{template.name}' is already added to the instance group '#{@job.name}'" end end end
parse_desired_instances(availability_zones, networks)
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 335 def parse_desired_instances(availability_zones, networks) @job.state = safe_property(@job_spec, "state", class: String, optional: true) job_size = safe_property(@job_spec, "instances", class: Integer) instance_states = safe_property(@job_spec, "instance_states", class: Hash, default: {}) networks.each do |network| static_ips = network.static_ips if static_ips && static_ips.size != job_size raise JobNetworkInstanceIpMismatch, "Instance group '#{@job.name}' has #{job_size} instances but was allocated #{static_ips.size} static IPs" end end instance_states.each_pair do |index_or_id, state| unless InstanceGroup::VALID_JOB_STATES.include?(state) raise JobInvalidInstanceState, "Invalid state '#{state}' for '#{@job.name}/#{index_or_id}', valid states are: #{InstanceGroup::VALID_JOB_STATES.join(", ")}" end @job.instance_states[index_or_id] = state end if @job.state && !InstanceGroup::VALID_JOB_STATES.include?(@job.state) raise JobInvalidJobState, "Invalid state '#{@job.state}' for '#{@job.name}', valid states are: #{InstanceGroup::VALID_JOB_STATES.join(", ")}" end job_size.times.map { DesiredInstance.new(@job, @deployment) } end
parse_disk()
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 212 def parse_disk disk_size = safe_property(@job_spec, 'persistent_disk', :class => Integer, :optional => true) disk_type_name = safe_property(@job_spec, 'persistent_disk_type', :class => String, :optional => true) disk_pool_name = safe_property(@job_spec, 'persistent_disk_pool', :class => String, :optional => true) if disk_type_name && disk_pool_name raise JobInvalidPersistentDisk, "Instance group '#{@job.name}' specifies both 'disk_types' and 'disk_pools', only one key is allowed. " + "'disk_pools' key will be DEPRECATED in the future." end if disk_type_name disk_name = disk_type_name disk_source = 'type' else disk_name = disk_pool_name disk_source = 'pool' end if disk_size && disk_name raise JobInvalidPersistentDisk, "Instance group '#{@job.name}' references both a persistent disk size '#{disk_size}' " + "and a persistent disk #{disk_source} '#{disk_name}'" end if disk_size if disk_size < 0 raise JobInvalidPersistentDisk, "Instance group '#{@job.name}' references an invalid persistent disk size '#{disk_size}'" else @job.persistent_disk = disk_size end end if disk_name disk_type = @deployment.disk_type(disk_name) if disk_type.nil? raise JobUnknownDiskType, "Instance group '#{@job.name}' references an unknown disk #{disk_source} '#{disk_name}'" else @job.persistent_disk_type = disk_type end end end
parse_lifecycle()
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 65 def parse_lifecycle lifecycle = safe_property(@job_spec, "lifecycle", :class => String, :optional => true, :default => InstanceGroup::DEFAULT_LIFECYCLE_PROFILE, ) unless InstanceGroup::VALID_LIFECYCLE_PROFILES.include?(lifecycle) raise JobInvalidLifecycle, "Invalid lifecycle '#{lifecycle}' for '#{@job.name}', " + "valid lifecycle profiles are: #{InstanceGroup::VALID_LIFECYCLE_PROFILES.join(', ')}" end @job.lifecycle = lifecycle end
parse_migrated_from()
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 365 def parse_migrated_from migrated_from = safe_property(@job_spec, 'migrated_from', class: Array, optional: true, :default => []) migrated_from.each do |migrated_from_job_spec| name = safe_property(migrated_from_job_spec, 'name', class: String) az = safe_property(migrated_from_job_spec, 'az', class: String, optional: true) unless az.nil? unless @job.availability_zones.to_a.map(&:name).include?(az) raise DeploymentInvalidMigratedFromJob, "Instance group '#{name}' specified for migration to instance group '#{@job.name}' refers to availability zone '#{az}'. " + "Az '#{az}' is not in the list of availability zones of instance group '#{@job.name}'." end end @job.migrated_from << MigratedFromJob.new(name, az) end end
parse_name()
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 60 def parse_name @job.name = safe_property(@job_spec, "name", :class => String) @job.canonical_name = Canonicalizer.canonicalize(@job.name) end
parse_properties()
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 257 def parse_properties # Manifest can contain global and per-job properties section job_properties = safe_property(@job_spec, "properties", :class => Hash, :optional => true, :default => {}) @job.all_properties = @deployment.properties.recursive_merge(job_properties) mappings = safe_property(@job_spec, "property_mappings", :class => Hash, :default => {}) mappings.each_pair do |to, from| resolved = lookup_property(@job.all_properties, from) if resolved.nil? raise JobInvalidPropertyMapping, "Cannot satisfy property mapping '#{to}: #{from}', as '#{from}' is not in deployment properties" end @job.all_properties[to] = resolved end end
parse_release()
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 81 def parse_release release_name = safe_property(@job_spec, "release", :class => String, :optional => true) if release_name.nil? if @deployment.releases.size == 1 @job.release = @deployment.releases.first end else @job.release = @deployment.release(release_name) if @job.release.nil? raise JobUnknownRelease, "Instance group '#{@job.name}' references an unknown release '#{release_name}'" end end end
parse_resource_pool()
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 277 def parse_resource_pool env_hash = safe_property(@job_spec, 'env', class: Hash, :default => {}) resource_pool_name = safe_property(@job_spec, "resource_pool", class: String, optional: true) if resource_pool_name resource_pool = @deployment.resource_pool(resource_pool_name) if resource_pool.nil? raise JobUnknownResourcePool, "Instance group '#{@job.name}' references an unknown resource pool '#{resource_pool_name}'" end vm_type = VmType.new({ 'name' => resource_pool.name, 'cloud_properties' => resource_pool.cloud_properties }) vm_extensions = [] stemcell = resource_pool.stemcell if !env_hash.empty? && !resource_pool.env.empty? raise JobAmbiguousEnv, "Instance group '#{@job.name}' and resource pool: '#{resource_pool_name}' both declare env properties" end if env_hash.empty? env_hash = resource_pool.env end else vm_type_name = safe_property(@job_spec, 'vm_type', class: String) vm_type = @deployment.vm_type(vm_type_name) if vm_type.nil? raise JobUnknownVmType, "Instance group '#{@job.name}' references an unknown vm type '#{vm_type_name}'" end vm_extension_names = Array(safe_property(@job_spec, 'vm_extensions', class: Array, optional: true)) vm_extensions = Array(vm_extension_names).map {|vm_extension_name| @deployment.vm_extension(vm_extension_name)} stemcell_name = safe_property(@job_spec, 'stemcell', class: String) stemcell = @deployment.stemcell(stemcell_name) if stemcell.nil? raise JobUnknownStemcell, "Instance group '#{@job.name}' references an unknown stemcell '#{stemcell_name}'" end end @job.vm_type = vm_type @job.vm_extensions = vm_extensions @job.stemcell = stemcell @job.env = Env.new(env_hash) end
parse_template()
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 98 def parse_template template_names = safe_property(@job_spec, "template", optional: true) if template_names if template_names.is_a?(Array) @event_log.warn_deprecated( "Please use 'templates' when specifying multiple templates for a job. " + "'template' for multiple templates will soon be unsupported." ) end unless template_names.is_a?(Array) || template_names.is_a?(String) invalid_type("template", "String or Array", template_names) end unless @job.release raise JobMissingRelease, "Cannot tell what release job '#{@job.name}' is supposed to use, please explicitly specify one" end Array(template_names).each do |template_name| @job.templates << @job.release.get_or_create_template(template_name) end end end
parse_templates()
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 122 def parse_templates templates = safe_property(@job_spec, 'templates', class: Array, optional: true) jobs = safe_property(@job_spec, 'jobs', class: Array, optional: true) if jobs && !jobs.empty? templates = jobs end if templates release_manager = Api::ReleaseManager.new # Key: release name. # Value: list of templates models of release version. release_versions_templates_models_hash = {} templates.each do |template_spec| template_name = safe_property(template_spec, 'name', class: String) release_name = safe_property(template_spec, 'release', class: String, optional: true) if release_name release = @deployment.release(release_name) unless release raise JobUnknownRelease, "Job '#{template_name}' (instance group '#{@job.name}') references an unknown release '#{release_name}'" end else release = @job.release unless release raise JobMissingRelease, "Cannot tell what release template '#{template_name}' (instance group '#{@job.name}') is supposed to use, please explicitly specify one" end end if !release_versions_templates_models_hash.has_key?(release_name) release_model = release_manager.find_by_name(release.name) current_release_version = release_manager.find_version(release_model, release.version) release_versions_templates_models_hash[release_name] = current_release_version.templates end templates_models_list = release_versions_templates_models_hash[release_name] current_template_model = templates_models_list.find {|target| target.name == template_name } template = release.get_or_create_template(template_name) if current_template_model == nil raise "Job '#{template_name}' not found in Template table" end if current_template_model.consumes != nil current_template_model.consumes.each do |consumes| template.add_link_from_release(@job.name,'consumes', consumes["name"], consumes) end end if current_template_model.provides != nil current_template_model.provides.each do |provides| template.add_link_from_release(@job.name, 'provides', provides["name"], provides) end end provides_links = safe_property(template_spec, 'provides', class: Hash, optional: true) provides_links.to_a.each do |link_name, source| template.add_link_from_manifest(@job.name, "provides", link_name, source) end consumes_links = safe_property(template_spec, 'consumes', class: Hash, optional: true) consumes_links.to_a.each do |link_name, source| template.add_link_from_manifest(@job.name, 'consumes', link_name, source) end if template_spec.has_key?("properties") template.add_template_scoped_properties( safe_property(template_spec, 'properties', class: Hash, optional: true, default: nil), @job.name ) end @job.templates << template end end end
parse_update_config(parse_options)
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 330 def parse_update_config(parse_options) update_spec = safe_property(@job_spec, "update", class: Hash, optional: true) @job.update = UpdateConfig.new((update_spec || {}).merge(parse_options), @deployment.update) end
validate_templates()
click to toggle source
# File lib/bosh/director/deployment_plan/instance_group_spec_parser.rb, line 381 def validate_templates template_property = safe_property(@job_spec, 'template', optional: true) templates_property = safe_property(@job_spec, 'templates', optional: true) jobs_property = safe_property(@job_spec, 'jobs', optional: true) if template_property && templates_property raise JobInvalidTemplates, "Instance group '#{@job.name}' specifies both template and templates keys, only one is allowed" end if templates_property && jobs_property raise JobInvalidTemplates, "Instance group '#{@job.name}' specifies both templates and jobs keys, only one is allowed" end if template_property && jobs_property raise JobInvalidTemplates, "Instance group '#{@job.name}' specifies both template and jobs keys, only one is allowed" end if [template_property, templates_property, jobs_property].compact.empty? raise ValidationMissingField, "Instance group '#{@job.name}' does not specify template, templates, or jobs keys, one is required" end end