class Bosh::Director::Jobs::UpdateDeployment

Public Class Methods

job_type() click to toggle source
# File lib/bosh/director/jobs/update_deployment.rb, line 11
def self.job_type
  :update_deployment
end
new(manifest_file_path, cloud_config_id, runtime_config_id, options = {}) click to toggle source
# File lib/bosh/director/jobs/update_deployment.rb, line 15
def initialize(manifest_file_path, cloud_config_id, runtime_config_id, options = {})
  @blobstore = App.instance.blobstores.blobstore
  @manifest_file_path = manifest_file_path
  @cloud_config_id = cloud_config_id
  @runtime_config_id = runtime_config_id
  @options = options
  @event_log = Config.event_log
end

Public Instance Methods

perform() click to toggle source
# File lib/bosh/director/jobs/update_deployment.rb, line 24
def perform
  logger.info('Reading deployment manifest')

  manifest_text = File.read(@manifest_file_path)
  manifest_hash = Psych.load(manifest_text)
  logger.debug("Manifest:\n#{manifest_text}")

  if Config.parse_config_values
    manifest_hash = Bosh::Director::Jobs::Helpers::ConfigParser.parse(manifest_hash)
  end

  if ignore_cloud_config?(manifest_hash)
    warning = "Ignoring cloud config. Manifest contains 'networks' section."
    logger.debug(warning)
    @event_log.warn_deprecated(warning)
    cloud_config_model = nil
  else
    cloud_config_model = Bosh::Director::Models::CloudConfig[@cloud_config_id]
    if cloud_config_model.nil?
      logger.debug("No cloud config uploaded yet.")
    else
      logger.debug("Cloud config:\n#{cloud_config_model.manifest}")
    end
  end

  runtime_config_model = Bosh::Director::Models::RuntimeConfig[@runtime_config_id]
  if runtime_config_model.nil?
    logger.debug("No runtime config uploaded yet.")
  else
    logger.debug("Runtime config:\n#{runtime_config_model.manifest}")
  end

  deployment_manifest = Manifest.load_from_hash(manifest_hash, cloud_config_model, runtime_config_model)

  @deployment_name = deployment_manifest.to_hash['name']

  previous_releases, previous_stemcells = get_stemcells_and_releases
  context = {}
  parent_id = add_event

  with_deployment_lock(@deployment_name) do
    @notifier = DeploymentPlan::Notifier.new(@deployment_name, Config.nats_rpc, logger)
    @notifier.send_start_event

    deployment_plan = nil

    event_log_stage = @event_log.begin_stage('Preparing deployment', 1)
    event_log_stage.advance_and_track('Preparing deployment') do
      planner_factory = DeploymentPlan::PlannerFactory.create(logger)
      deployment_plan = planner_factory.create_from_manifest(deployment_manifest, cloud_config_model, runtime_config_model, @options)
      deployment_plan.bind_models
    end

    if deployment_plan.instance_models.any?(&:ignore)
      @event_log.warn('You have ignored instances. They will not be changed.')
    end

    next_releases, next_stemcells  = get_stemcells_and_releases
    context = event_context(next_releases, previous_releases, next_stemcells, previous_stemcells)

    render_job_templates(deployment_plan.jobs_starting_on_deploy)
    deployment_plan.compile_packages

    update_step(deployment_plan).perform

    if check_for_changes(deployment_plan)
      PostDeploymentScriptRunner.run_post_deploys_after_deployment(deployment_plan)
    end

    @notifier.send_end_event
    logger.info('Finished updating deployment')
    add_event(context, parent_id)

    "/deployments/#{deployment_plan.name}"
  end
rescue Exception => e
  begin
    @notifier.send_error_event e
  rescue Exception => e2
    # log the second error
  ensure
    add_event(context, parent_id, e)
    raise e
  end
ensure
  FileUtils.rm_rf(@manifest_file_path)
end

Private Instance Methods

add_event(context = {}, parent_id = nil, error = nil) click to toggle source
# File lib/bosh/director/jobs/update_deployment.rb, line 114
def add_event(context = {}, parent_id = nil, error = nil)
  action = @options.fetch('new', false) ? "create" : "update"
  event  = event_manager.create_event(
      {
          parent_id:   parent_id,
          user:        username,
          action:      action,
          object_type: "deployment",
          object_name: @deployment_name,
          deployment:  @deployment_name,
          task:        task_id,
          error:       error,
          context:     context
      })
  event.id
end
check_for_changes(deployment_plan) click to toggle source

Job tasks

# File lib/bosh/director/jobs/update_deployment.rb, line 133
def check_for_changes(deployment_plan)
  deployment_plan.instance_groups.each do |job|
    return true if job.did_change
  end
  false
end
current_deployment() click to toggle source
# File lib/bosh/director/jobs/update_deployment.rb, line 194
def current_deployment
  Models::Deployment[name: @deployment_name]
end
event_context(next_releases, previous_releases, next_stemcells, previous_stemcells) click to toggle source
# File lib/bosh/director/jobs/update_deployment.rb, line 198
def event_context(next_releases, previous_releases, next_stemcells, previous_stemcells)
  after_objects = {}
  after_objects['releases'] = next_releases unless next_releases.empty?
  after_objects['stemcells'] = next_stemcells unless next_stemcells.empty?

  before_objects = {}
  before_objects['releases'] = previous_releases unless previous_releases.empty?
  before_objects['stemcells'] = previous_stemcells unless previous_stemcells.empty?

  context = {}
  context['before'] = before_objects
  context['after'] = after_objects
  context
end
get_stemcells_and_releases() click to toggle source
# File lib/bosh/director/jobs/update_deployment.rb, line 179
def get_stemcells_and_releases
  deployment = current_deployment
  stemcells = []
  releases = []
  if deployment
    releases = deployment.release_versions.map do |rv|
      "#{rv.release.name}/#{rv.version}"
    end
    stemcells = deployment.stemcells.map do |sc|
      "#{sc.name}/#{sc.version}"
    end
  end
  return releases, stemcells
end
multi_job_updater() click to toggle source

Job dependencies

# File lib/bosh/director/jobs/update_deployment.rb, line 151
def multi_job_updater
  @multi_job_updater ||= begin
    DeploymentPlan::BatchMultiJobUpdater.new(JobUpdaterFactory.new(Config.cloud, logger))
  end
end
render_job_templates(jobs) click to toggle source
# File lib/bosh/director/jobs/update_deployment.rb, line 157
def render_job_templates(jobs)
  errors = []
  job_renderer = JobRenderer.create
  jobs.each do |job|
    begin
      job_renderer.render_job_instances(job.needed_instance_plans)
    rescue Exception => e
      errors.push e
    end
  end

  if errors.length > 0
    message = 'Unable to render instance groups for deployment. Errors are:'

    errors.each do |e|
      message = "#{message}\n   - #{e.message.gsub(/\n/, "\n  ")}"
    end

    raise message
  end
end
update_step(deployment_plan) click to toggle source
# File lib/bosh/director/jobs/update_deployment.rb, line 140
def update_step(deployment_plan)
  DeploymentPlan::Steps::UpdateStep.new(
    self,
    deployment_plan,
    multi_job_updater,
    Config.cloud
  )
end