lxd/api_project.go
func projectChange(d *Daemon, project *api.Project, req api.ProjectPut) Response {
	// Flag indicating if any feature has changed.
	featuresChanged := req.Config["features.images"] != project.Config["features.images"] || req.Config["features.profiles"] != project.Config["features.profiles"]

	// Sanity checks
	if project.Name == "default" && featuresChanged {
		return BadRequest(fmt.Errorf("You can't change the features of the default project"))
	}

	if !projectIsEmpty(project) && featuresChanged {
		return BadRequest(fmt.Errorf("Features can only be changed on empty projects"))
	}

	// Validate the configuration
	err := projectValidateConfig(req.Config)
	if err != nil {
		return BadRequest(err)
	}

	// Update the database entry
	err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
		err := tx.ProjectUpdate(project.Name, req)
		if err != nil {
			return errors.Wrap(err, "Persist profile changes")
		}

		if req.Config["features.profiles"] != project.Config["features.profiles"] {
			if req.Config["features.profiles"] == "true" {
				err = projectCreateDefaultProfile(tx, project.Name)
				if err != nil {
					return err
				}
			} else {
				// Delete the project-specific default profile.
				err = tx.ProfileDelete(project.Name, "default")
				if err != nil {
					return errors.Wrap(err, "Delete project default profile")
				}
			}
		}

		return nil

	})

	if err != nil {
		return SmartError(err)
	}

	return EmptySyncResponse
}
func projectChange(d *Daemon, project *api.Project, req api.ProjectPut) Response {
	// Flag indicating if any feature has changed.
	featuresChanged := req.Config["features.images"] != project.Config["features.images"] || req.Config["features.profiles"] != project.Config["features.profiles"]

	// Sanity checks
	if project.Name == "default" && featuresChanged {
		return BadRequest(fmt.Errorf("You can't change the features of the default project"))
	}

	if !projectIsEmpty(project) && featuresChanged {
		return BadRequest(fmt.Errorf("Features can only be changed on empty projects"))
	}

	// Validate the configuration
	err := projectValidateConfig(req.Config)
	if err != nil {
		return BadRequest(err)
	}

	// Update the database entry
	err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
		err := tx.ProjectUpdate(project.Name, req)
		if err != nil {
			return errors.Wrap(err, "Persist profile changes")
		}

		if req.Config["features.profiles"] != project.Config["features.profiles"] {
			if req.Config["features.profiles"] == "true" {
				err = projectCreateDefaultProfile(tx, project.Name)
				if err != nil {
					return err
				}
			} else {
				// Delete the project-specific default profile.
				err = tx.ProfileDelete(project.Name, "default")
				if err != nil {
					return errors.Wrap(err, "Delete project default profile")
				}
			}
		}

		return nil

	})

	if err != nil {
		return SmartError(err)
	}

	return EmptySyncResponse
}
// Common logic between PUT and PATCH.