// ServerError returns an error suitable for returning to an API // client, with an error code suitable for various kinds of errors // generated in packages outside the API. func ServerError(err error) *params.Error { if err == nil { return nil } logger.Tracef("server RPC error %v", errors.Details(err)) msg := err.Error() // Skip past annotations when looking for the code. err = errors.Cause(err) code, ok := singletonCode(err) var info *params.ErrorInfo switch { case ok: case errors.IsUnauthorized(err): code = params.CodeUnauthorized case errors.IsNotFound(err): code = params.CodeNotFound case errors.IsUserNotFound(err): code = params.CodeUserNotFound case errors.IsAlreadyExists(err): code = params.CodeAlreadyExists case errors.IsNotAssigned(err): code = params.CodeNotAssigned case state.IsHasAssignedUnitsError(err): code = params.CodeHasAssignedUnits case state.IsHasHostedModelsError(err): code = params.CodeHasHostedModels case isNoAddressSetError(err): code = params.CodeNoAddressSet case errors.IsNotProvisioned(err): code = params.CodeNotProvisioned case IsUpgradeInProgressError(err): code = params.CodeUpgradeInProgress case state.IsHasAttachmentsError(err): code = params.CodeMachineHasAttachedStorage case isUnknownModelError(err): code = params.CodeModelNotFound case errors.IsNotSupported(err): code = params.CodeNotSupported case errors.IsBadRequest(err): code = params.CodeBadRequest case errors.IsMethodNotAllowed(err): code = params.CodeMethodNotAllowed default: if err, ok := err.(*DischargeRequiredError); ok { code = params.CodeDischargeRequired info = ¶ms.ErrorInfo{ Macaroon: err.Macaroon, // One macaroon fits all. MacaroonPath: "/", } break } code = params.ErrCode(err) } return ¶ms.Error{ Message: msg, Code: code, Info: info, } }
// DestroyController will attempt to destroy the controller. If the args // specify the removal of blocks or the destruction of the models, this // method will attempt to do so. func (s *ControllerAPI) DestroyController(args params.DestroyControllerArgs) error { controllerEnv, err := s.state.ControllerModel() if err != nil { return errors.Trace(err) } systemTag := controllerEnv.ModelTag() if err = s.ensureNotBlocked(args); err != nil { return errors.Trace(err) } // If we are destroying models, we need to tolerate living // models but set the controller to dying to prevent new // models sneaking in. If we are not destroying hosted models, // this will fail if any hosted models are found. if args.DestroyModels { return errors.Trace(common.DestroyModelIncludingHosted(s.state, systemTag)) } if err = common.DestroyModel(s.state, systemTag); state.IsHasHostedModelsError(err) { err = errors.New("controller model cannot be destroyed before all other models are destroyed") } return errors.Trace(err) }