func (u *Undertaker) processDyingModel() error { watcher, err := u.config.Facade.WatchModelResources() if err != nil { return errors.Trace(err) } if err := u.catacomb.Add(watcher); err != nil { return errors.Trace(err) } defer watcher.Kill() // The watcher is not needed once this func returns. for { select { case <-u.catacomb.Dying(): return u.catacomb.ErrDying() case <-watcher.Changes(): // TODO(fwereade): this is wrong. If there's a time // it's ok to ignore an error, it's when we know // exactly what an error is/means. If there's a // specific code for "not done yet", *that* is what // we should be ignoring. But unknown errors are // *unknown*, and we can't just assume that it's // safe to continue. err := u.config.Facade.ProcessDyingModel() if err == nil { // ProcessDyingModel succeeded. We're free to // destroy any remaining environ resources. return nil } // Yes, we ignore the error. See comment above. } } }
func (w *Worker) loop() error { model := w.config.Model facade := w.config.Facade watcher, err := facade.Watch(model) if err != nil { return errors.Trace(err) } if err := w.catacomb.Add(watcher); err != nil { return errors.Trace(err) } for { select { case <-w.catacomb.Dying(): return w.catacomb.ErrDying() case <-watcher.Changes(): phase, err := facade.Phase(model) if err != nil { return errors.Trace(err) } if w.Check() != w.config.Check(phase) { return ErrChanged } } } }
func (w *Worker) loop() error { watcher, err := w.config.Facade.Watch(w.config.Entity) if err != nil { return errors.Trace(err) } if err := w.catacomb.Add(watcher); err != nil { return errors.Trace(err) } for { select { case <-w.catacomb.Dying(): return w.catacomb.ErrDying() case <-watcher.Changes(): life, err := w.config.Facade.Life(w.config.Entity) if err != nil { return errors.Trace(err) } if w.config.Result(life) != w.Check() { return ErrValueChanged } } } }
func (w *Worker) loop() error { watcher, err := w.config.Facade.Watch() if err != nil { return errors.Annotate(err, "setting up watcher") } if err := w.catacomb.Add(watcher); err != nil { return errors.Trace(err) } for { select { case <-w.catacomb.Dying(): return w.catacomb.ErrDying() case status, ok := <-watcher.Changes(): if !ok { return errors.New("watcher channel closed") } if err := w.handle(status); err != nil { return errors.Trace(err) } } } }
func (w *Worker) waitForActiveMigration() (migrationmaster.MigrationStatus, error) { var empty migrationmaster.MigrationStatus watcher, err := w.config.Facade.Watch() if err != nil { return empty, errors.Annotate(err, "watching for migration") } if err := w.catacomb.Add(watcher); err != nil { return empty, errors.Trace(err) } defer watcher.Kill() for { select { case <-w.catacomb.Dying(): return empty, w.catacomb.ErrDying() case <-watcher.Changes(): } status, err := w.config.Facade.GetMigrationStatus() switch { case params.IsCodeNotFound(err): if err := w.config.Guard.Unlock(); err != nil { return empty, errors.Trace(err) } continue case err != nil: return empty, errors.Annotate(err, "retrieving migration status") } if modelHasMigrated(status.Phase) { return empty, dependency.ErrUninstall } if !status.Phase.IsTerminal() { return status, nil } } }