// 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 } }
// unitsChanged responds to changes to the assigned units. func (fw *Firewaller) unitsChanged(change *unitsChange) error { changed := []*unitData{} for _, name := range change.units { unitTag := names.NewUnitTag(name) unit, err := fw.st.Unit(unitTag) if err != nil && !params.IsCodeNotFound(err) { return err } var machineTag names.MachineTag if unit != nil { machineTag, err = unit.AssignedMachine() if params.IsCodeNotFound(err) { continue } else if err != nil && !params.IsCodeNotAssigned(err) { return err } } if unitd, known := fw.unitds[unitTag]; known { knownMachineTag := fw.unitds[unitTag].machined.tag if unit == nil || unit.Life() == params.Dead || machineTag != knownMachineTag { fw.forgetUnit(unitd) changed = append(changed, unitd) logger.Debugf("stopped watching unit %s", name) } // TODO(dfc) fw.machineds should be map[names.Tag] } else if unit != nil && unit.Life() != params.Dead && fw.machineds[machineTag] != nil { err = fw.startUnit(unit, machineTag) if err != nil { return err } changed = append(changed, fw.unitds[unitTag]) logger.Debugf("started watching %q", unitTag) } } if err := fw.flushUnits(changed); err != nil { return errors.Annotate(err, "cannot change firewall ports") } return nil }