// RestoreError makes a best effort at converting the given error // back into an error originally converted by ServerError(). If the // error could not be converted then false is returned. func RestoreError(err error) (error, bool) { err = errors.Cause(err) if apiErr, ok := err.(*params.Error); !ok { return err, false } else if apiErr == nil { return nil, true } if params.ErrCode(err) == "" { return err, false } msg := err.Error() if singleton, ok := singletonError(err); ok { return singleton, true } // TODO(ericsnow) Support the other error types handled by ServerError(). switch { case params.IsCodeUnauthorized(err): return errors.NewUnauthorized(nil, msg), true case params.IsCodeNotFound(err): // TODO(ericsnow) UnknownModelError should be handled here too. // ...by parsing msg? return errors.NewNotFound(nil, msg), true case params.IsCodeAlreadyExists(err): return errors.NewAlreadyExists(nil, msg), true case params.IsCodeNotAssigned(err): return errors.NewNotAssigned(nil, msg), true case params.IsCodeHasAssignedUnits(err): // TODO(ericsnow) Handle state.HasAssignedUnitsError here. // ...by parsing msg? return err, false case params.IsCodeNoAddressSet(err): // TODO(ericsnow) Handle isNoAddressSetError here. // ...by parsing msg? return err, false case params.IsCodeNotProvisioned(err): return errors.NewNotProvisioned(nil, msg), true case params.IsCodeUpgradeInProgress(err): // TODO(ericsnow) Handle state.UpgradeInProgressError here. // ...by parsing msg? return err, false case params.IsCodeMachineHasAttachedStorage(err): // TODO(ericsnow) Handle state.HasAttachmentsError here. // ...by parsing msg? return err, false case params.IsCodeNotSupported(err): return errors.NewNotSupported(nil, msg), true case params.IsBadRequest(err): return errors.NewBadRequest(nil, msg), true case params.IsMethodNotAllowed(err): return errors.NewMethodNotAllowed(nil, msg), true case params.ErrCode(err) == params.CodeDischargeRequired: // TODO(ericsnow) Handle DischargeRequiredError here. return err, false default: return err, false } }
// ListSpaces lists all available spaces and their associated subnets. func (api *API) ListSpaces() ([]params.Space, error) { var response params.ListSpacesResults err := api.facade.FacadeCall("ListSpaces", nil, &response) if params.IsCodeNotSupported(err) { return response.Results, errors.NewNotSupported(nil, err.Error()) } return response.Results, err }
// CreateSpace creates a new Juju network space, associating the // specified subnets with it (optional; can be empty). func (api *API) CreateSpace(name string, subnetIds []string, public bool) error { var response params.ErrorResults createSpacesParams := params.CreateSpacesParams{ Spaces: []params.CreateSpaceParams{makeCreateSpaceParams(name, subnetIds, public)}, } err := api.facade.FacadeCall("CreateSpaces", createSpacesParams, &response) if err != nil { if params.IsCodeNotSupported(err) { return errors.NewNotSupported(nil, err.Error()) } return errors.Trace(err) } return response.OneError() }