app/app.go
func (app *App) Update(updateData App, w io.Writer) (err error) {
	description := updateData.Description
	planName := updateData.Plan.Name
	poolName := updateData.Pool
	teamOwner := updateData.TeamOwner
	platform := updateData.Platform
	tags := processTags(updateData.Tags)
	oldApp := *app

	if description != "" {
		app.Description = description
	}
	if poolName != "" {
		app.Pool = poolName
		app.provisioner = nil
		_, err = app.getPoolForApp(app.Pool)
		if err != nil {
			return err
		}
	}
	newProv, err := app.getProvisioner()
	if err != nil {
		return err
	}
	oldProv, err := oldApp.getProvisioner()
	if err != nil {
		return err
	}
	if planName != "" {
		plan, errFind := servicemanager.Plan.FindByName(planName)
		if errFind != nil {
			return errFind
		}
		app.Plan = *plan
	}
	if teamOwner != "" {
		team, errTeam := servicemanager.Team.FindByName(teamOwner)
		if errTeam != nil {
			return errTeam
		}
		app.TeamOwner = team.Name
		defer func() {
			if err == nil {
				app.Grant(team)
			}
		}()
	}
	if tags != nil {
		app.Tags = tags
	}
	if platform != "" {
		var p, v string
		p, v, err = getPlatformNameAndVersion(platform)
		if err != nil {
			return err
		}
		if app.Platform != p || app.PlatformVersion != v {
			app.UpdatePlatform = true
		}
		app.Platform = p
		app.PlatformVersion = v
	}
	if updateData.UpdatePlatform {
		app.UpdatePlatform = true
	}
	err = app.validate()
	if err != nil {
		return err
	}
	actions := []*action.Action{
		&saveApp,
	}
	if newProv.GetName() == oldProv.GetName() {
		actions = append(actions, &updateAppProvisioner)
	}
	if newProv.GetName() != oldProv.GetName() {
		defer func() {
			rebuild.RoutesRebuildOrEnqueue(app.Name)
		}()
		err = validateVolumes(app)
		if err != nil {
			return err
		}
		actions = append(actions,
			&provisionAppNewProvisioner,
			&provisionAppAddUnits,
			&destroyAppOldProvisioner)
	} else if app.Plan != oldApp.Plan {
		actions = append(actions, &restartApp)
	}
	return action.NewPipeline(actions...).Execute(app, &oldApp, w)
}
func (app *App) Update(updateData App, w io.Writer) (err error) {
	description := updateData.Description
	planName := updateData.Plan.Name
	poolName := updateData.Pool
	teamOwner := updateData.TeamOwner
	platform := updateData.Platform
	tags := processTags(updateData.Tags)
	oldApp := *app

	if description != "" {
		app.Description = description
	}
	if poolName != "" {
		app.Pool = poolName
		app.provisioner = nil
		_, err = app.getPoolForApp(app.Pool)
		if err != nil {
			return err
		}
	}
	newProv, err := app.getProvisioner()
	if err != nil {
		return err
	}
	oldProv, err := oldApp.getProvisioner()
	if err != nil {
		return err
	}
	if planName != "" {
		plan, errFind := servicemanager.Plan.FindByName(planName)
		if errFind != nil {
			return errFind
		}
		app.Plan = *plan
	}
	if teamOwner != "" {
		team, errTeam := servicemanager.Team.FindByName(teamOwner)
		if errTeam != nil {
			return errTeam
		}
		app.TeamOwner = team.Name
		defer func() {
			if err == nil {
				app.Grant(team)
			}
		}()
	}
	if tags != nil {
		app.Tags = tags
	}
	if platform != "" {
		var p, v string
		p, v, err = getPlatformNameAndVersion(platform)
		if err != nil {
			return err
		}
		if app.Platform != p || app.PlatformVersion != v {
			app.UpdatePlatform = true
		}
		app.Platform = p
		app.PlatformVersion = v
	}
	if updateData.UpdatePlatform {
		app.UpdatePlatform = true
	}
	err = app.validate()
	if err != nil {
		return err
	}
	actions := []*action.Action{
		&saveApp,
	}
	if newProv.GetName() == oldProv.GetName() {
		actions = append(actions, &updateAppProvisioner)
	}
	if newProv.GetName() != oldProv.GetName() {
		defer func() {
			rebuild.RoutesRebuildOrEnqueue(app.Name)
		}()
		err = validateVolumes(app)
		if err != nil {
			return err
		}
		actions = append(actions,
			&provisionAppNewProvisioner,
			&provisionAppAddUnits,
			&destroyAppOldProvisioner)
	} else if app.Plan != oldApp.Plan {
		actions = append(actions, &restartApp)
	}
	return action.NewPipeline(actions...).Execute(app, &oldApp, w)
}
// Update changes informations of the application.