// stopWatchers stops all the firewaller's watchers. func (fw *Firewaller) stopWatchers() { watcher.Stop(fw.environWatcher, &fw.tomb) watcher.Stop(fw.machinesWatcher, &fw.tomb) for _, unitd := range fw.unitds { watcher.Stop(unitd, &fw.tomb) } for _, serviced := range fw.serviceds { watcher.Stop(serviced, &fw.tomb) } for _, machined := range fw.machineds { watcher.Stop(machined, &fw.tomb) } }
func (nw *notifyWorker) loop() error { w, err := nw.handler.SetUp() if err != nil { if w != nil { // We don't bother to propagate an error, because we // already have an error w.Stop() } return err } defer propagateTearDown(nw.handler, &nw.tomb) defer watcher.Stop(w, &nw.tomb) for { select { case <-nw.tomb.Dying(): return tomb.ErrDying case _, ok := <-w.Changes(): if !ok { return mustErr(w) } if err := nw.handler.Handle(); err != nil { return err } } } }
func (p *environProvisioner) loop() error { var environConfigChanges <-chan struct{} environWatcher, err := p.st.WatchForEnvironConfigChanges() if err != nil { return err } environConfigChanges = environWatcher.Changes() defer watcher.Stop(environWatcher, &p.tomb) p.environ, err = worker.WaitForEnviron(environWatcher, p.st, p.tomb.Dying()) if err != nil { return err } p.broker = p.environ safeMode := p.environ.Config().ProvisionerSafeMode() task, err := p.getStartTask(safeMode) if err != nil { return err } defer watcher.Stop(task, &p.tomb) for { select { case <-p.tomb.Dying(): return tomb.ErrDying case <-task.Dying(): err := task.Err() logger.Errorf("environ provisioner died: %v", err) return err case _, ok := <-environConfigChanges: if !ok { return watcher.MustErr(environWatcher) } environConfig, err := p.st.EnvironConfig() if err != nil { logger.Errorf("cannot load environment configuration: %v", err) return err } if err := p.setConfig(environConfig); err != nil { logger.Errorf("loaded invalid environment configuration: %v", err) } task.SetSafeMode(environConfig.ProvisionerSafeMode()) } } }
func (p *containerProvisioner) loop() error { task, err := p.getStartTask(false) if err != nil { return err } defer watcher.Stop(task, &p.tomb) for { select { case <-p.tomb.Dying(): return tomb.ErrDying case <-task.Dying(): err := task.Err() logger.Errorf("%s provisioner died: %v", p.containerType, err) return err } } }
// watchLoop watches the service's exposed flag for changes. func (sd *serviceData) watchLoop(exposed bool) { defer sd.tomb.Done() w, err := sd.service.Watch() if err != nil { sd.fw.tomb.Kill(err) return } defer watcher.Stop(w, &sd.tomb) for { select { case <-sd.tomb.Dying(): return case _, ok := <-w.Changes(): if !ok { sd.fw.tomb.Kill(watcher.MustErr(w)) return } if err := sd.service.Refresh(); err != nil { if !params.IsCodeNotFound(err) { sd.fw.tomb.Kill(err) } return } change, err := sd.service.IsExposed() if err != nil { sd.fw.tomb.Kill(err) return } if change == exposed { continue } exposed = change select { case sd.fw.exposedChange <- &exposedChange{sd, change}: case <-sd.tomb.Dying(): return } } } }
// watchLoop watches the unit for port changes. func (ud *unitData) watchLoop(latestPorts []instance.Port) { defer ud.tomb.Done() w, err := ud.unit.Watch() if err != nil { ud.fw.tomb.Kill(err) return } defer watcher.Stop(w, &ud.tomb) for { select { case <-ud.tomb.Dying(): return case _, ok := <-w.Changes(): if !ok { ud.fw.tomb.Kill(watcher.MustErr(w)) return } if err := ud.unit.Refresh(); err != nil { if !params.IsCodeNotFound(err) { ud.fw.tomb.Kill(err) } return } change, err := ud.unit.OpenedPorts() if err != nil { ud.fw.tomb.Kill(err) return } if samePorts(change, latestPorts) { continue } latestPorts = append(latestPorts[:0], change...) select { case ud.fw.portsChange <- &portsChange{ud, change}: case <-ud.tomb.Dying(): return } } } }
// watchLoop watches the machine for units added or removed. func (md *machineData) watchLoop(unitw apiwatcher.StringsWatcher) { defer md.tomb.Done() defer watcher.Stop(unitw, &md.tomb) for { select { case <-md.tomb.Dying(): return case change, ok := <-unitw.Changes(): if !ok { _, err := md.machine() if !params.IsCodeNotFound(err) { md.fw.tomb.Kill(watcher.MustErr(unitw)) } return } select { case md.fw.unitsChange <- &unitsChange{md, change}: case <-md.tomb.Dying(): return } } } }
func (f *filter) loop(unitTag string) (err error) { defer func() { if params.IsCodeNotFoundOrCodeUnauthorized(err) { err = worker.ErrTerminateAgent } }() if f.unit, err = f.st.Unit(unitTag); err != nil { return err } if err = f.unitChanged(); err != nil { return err } f.service, err = f.unit.Service() if err != nil { return err } if err = f.serviceChanged(); err != nil { return err } unitw, err := f.unit.Watch() if err != nil { return err } defer f.maybeStopWatcher(unitw) servicew, err := f.service.Watch() if err != nil { return err } defer f.maybeStopWatcher(servicew) // configw and relationsw can get restarted, so we need to use // their eventual values in the defer calls. var configw apiwatcher.NotifyWatcher var configChanges <-chan struct{} curl, err := f.unit.CharmURL() if err == nil { configw, err = f.unit.WatchConfigSettings() if err != nil { return err } configChanges = configw.Changes() f.upgradeFrom.url = curl } else if err != uniter.ErrNoCharmURLSet { filterLogger.Errorf("unit charm: %v", err) return err } defer func() { if configw != nil { watcher.Stop(configw, &f.tomb) } }() relationsw, err := f.service.WatchRelations() if err != nil { return err } defer func() { if relationsw != nil { watcher.Stop(relationsw, &f.tomb) } }() // Config events cannot be meaningfully discarded until one is available; // once we receive the initial change, we unblock discard requests by // setting this channel to its namesake on f. var discardConfig chan struct{} for { var ok bool select { case <-f.tomb.Dying(): return tomb.ErrDying // Handle watcher changes. case _, ok = <-unitw.Changes(): filterLogger.Debugf("got unit change") if !ok { return watcher.MustErr(unitw) } if err = f.unitChanged(); err != nil { return err } case _, ok = <-servicew.Changes(): filterLogger.Debugf("got service change") if !ok { return watcher.MustErr(servicew) } if err = f.serviceChanged(); err != nil { return err } case _, ok = <-configChanges: filterLogger.Debugf("got config change") if !ok { return watcher.MustErr(configw) } filterLogger.Debugf("preparing new config event") f.outConfig = f.outConfigOn discardConfig = f.discardConfig case keys, ok := <-relationsw.Changes(): filterLogger.Debugf("got relations change") if !ok { return watcher.MustErr(relationsw) } var ids []int for _, key := range keys { relationTag := names.RelationTag(key) rel, err := f.st.Relation(relationTag) if params.IsCodeNotFoundOrCodeUnauthorized(err) { // If it's actually gone, this unit cannot have entered // scope, and therefore never needs to know about it. } else if err != nil { return err } else { ids = append(ids, rel.Id()) } } f.relationsChanged(ids) // Send events on active out chans. case f.outUpgrade <- f.upgrade: filterLogger.Debugf("sent upgrade event") f.outUpgrade = nil case f.outResolved <- f.resolved: filterLogger.Debugf("sent resolved event") f.outResolved = nil case f.outConfig <- nothing: filterLogger.Debugf("sent config event") f.outConfig = nil case f.outRelations <- f.relations: filterLogger.Debugf("sent relations event") f.outRelations = nil f.relations = nil // Handle explicit requests. case curl := <-f.setCharm: filterLogger.Debugf("changing charm to %q", curl) // We need to restart the config watcher after setting the // charm, because service config settings are distinct for // different service charms. if configw != nil { if err := configw.Stop(); err != nil { return err } } if err := f.unit.SetCharmURL(curl); err != nil { filterLogger.Debugf("failed setting charm url %q: %v", curl, err) return err } select { case <-f.tomb.Dying(): return tomb.ErrDying case f.didSetCharm <- nothing: } configw, err = f.unit.WatchConfigSettings() if err != nil { return err } configChanges = configw.Changes() // Restart the relations watcher. if err := relationsw.Stop(); err != nil { return err } relationsw, err = f.service.WatchRelations() if err != nil { return err } f.upgradeFrom.url = curl if err = f.upgradeChanged(); err != nil { return err } case force := <-f.wantForcedUpgrade: filterLogger.Debugf("want forced upgrade %v", force) f.upgradeFrom.force = force if err = f.upgradeChanged(); err != nil { return err } case <-f.wantResolved: filterLogger.Debugf("want resolved event") if f.resolved != params.ResolvedNone { f.outResolved = f.outResolvedOn } case <-f.clearResolved: filterLogger.Debugf("resolved event handled") f.outResolved = nil if err := f.unit.ClearResolved(); err != nil { return err } if err := f.unitChanged(); err != nil { return err } select { case <-f.tomb.Dying(): return tomb.ErrDying case f.didClearResolved <- nothing: } case <-discardConfig: filterLogger.Debugf("discarded config event") f.outConfig = nil } } }
func (f *filter) maybeStopWatcher(w watcher.Stopper) { if w != nil { watcher.Stop(w, &f.tomb) } }