func (s *environSuite) TestInvalidConfig(c *gc.C) { var oldType string oldType = s.Environ.Config().AllAttrs()["type"].(string) // Create an invalid config by taking the current config and // tweaking the provider type. info := s.MongoInfo(c) opts := mongo.DefaultDialOpts() st2, err := state.Open(info, opts, state.Policy(nil)) c.Assert(err, gc.IsNil) defer st2.Close() err = st2.UpdateEnvironConfig(map[string]interface{}{"type": "unknown"}, nil, nil) c.Assert(err, gc.IsNil) w := st2.WatchForEnvironConfigChanges() defer stopWatcher(c, w) done := make(chan environs.Environ) go func() { env, err := worker.WaitForEnviron(w, st2, nil) c.Check(err, gc.IsNil) done <- env }() // Wait for the loop to process the invalid configuratrion <-worker.LoadedInvalid st2.UpdateEnvironConfig(map[string]interface{}{ "type": oldType, "secret": "environ_test", }, nil, nil) env := <-done c.Assert(env, gc.NotNil) c.Assert(env.Config().AllAttrs()["secret"], gc.Equals, "environ_test") }
func (s *environSuite) TestStop(c *gc.C) { s.st.SetErrors( nil, // WatchForEnvironConfigChanges errors.New("err1"), // Changes (closing the channel) ) s.st.SetConfig(c, coretesting.Attrs{ "type": "invalid", }) w, err := s.st.WatchForEnvironConfigChanges() c.Assert(err, jc.ErrorIsNil) defer stopWatcher(c, w) stop := make(chan struct{}) close(stop) // close immediately so the loop exits. done := make(chan error) go func() { env, err := worker.WaitForEnviron(w, s.st, stop) c.Check(env, gc.IsNil) done <- err }() select { case <-worker.LoadedInvalid: c.Errorf("expected changes watcher to be closed") case err := <-done: c.Assert(err, gc.Equals, tomb.ErrDying) case <-time.After(coretesting.LongWait): c.Fatalf("timeout waiting for the WaitForEnviron to stop") } s.st.CheckCallNames(c, "WatchForEnvironConfigChanges", "Changes") }
// NewFirewaller returns a new Firewaller or a new FirewallerV0, // depending on what the API supports. func NewFirewaller(st *apifirewaller.State) (_ worker.Worker, err error) { fw := &Firewaller{ st: st, machineds: make(map[names.MachineTag]*machineData), unitsChange: make(chan *unitsChange), unitds: make(map[names.UnitTag]*unitData), serviceds: make(map[names.ServiceTag]*serviceData), exposedChange: make(chan *exposedChange), machinePorts: make(map[names.MachineTag]machineRanges), } defer func() { if err != nil { fw.stopWatchers() } }() fw.environWatcher, err = st.WatchForEnvironConfigChanges() if err != nil { return nil, err } fw.machinesWatcher, err = st.WatchEnvironMachines() if err != nil { return nil, err } fw.portsWatcher, err = st.WatchOpenedPorts() if err != nil { return nil, errors.Annotatef(err, "failed to start ports watcher") } logger.Debugf("started watching opened port ranges for the environment") // We won't "wait" actually, because the environ is already // available and has a guaranteed valid config, but until // WaitForEnviron goes away, this code needs to stay. fw.environ, err = worker.WaitForEnviron(fw.environWatcher, fw.st, fw.tomb.Dying()) if err != nil { return nil, err } switch fw.environ.Config().FirewallMode() { case config.FwGlobal: fw.globalMode = true fw.globalPortRef = make(map[network.PortRange]int) case config.FwNone: logger.Warningf("stopping firewaller - firewall-mode is %q", config.FwNone) return nil, errors.Errorf("firewaller is disabled when firewall-mode is %q", config.FwNone) } go func() { defer fw.tomb.Done() fw.tomb.Kill(fw.loop()) }() return fw, nil }
func (s *environSuite) TestStop(c *gc.C) { w := s.State.WatchForEnvironConfigChanges() defer stopWatcher(c, w) stop := make(chan struct{}) done := make(chan error) go func() { env, err := worker.WaitForEnviron(w, s.State, stop) c.Check(env, gc.IsNil) done <- err }() close(stop) c.Assert(<-done, gc.Equals, tomb.ErrDying) }
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 (s *environSuite) TestInvalidConfig(c *gc.C) { s.st.SetConfig(c, coretesting.Attrs{ "type": "unknown", }) w, err := s.st.WatchForEnvironConfigChanges() c.Assert(err, jc.ErrorIsNil) defer stopWatcher(c, w) done := make(chan environs.Environ) go func() { env, err := worker.WaitForEnviron(w, s.st, nil) c.Check(err, jc.ErrorIsNil) done <- env }() <-worker.LoadedInvalid s.st.CheckCallNames(c, "WatchForEnvironConfigChanges", "Changes", "EnvironConfig", "Changes", ) }
func (fw *Firewaller) loop() error { defer fw.stopWatchers() var err error var reconciled bool fw.environ, err = worker.WaitForEnviron(fw.environWatcher, fw.st, fw.tomb.Dying()) if err != nil { return err } if fw.environ.Config().FirewallMode() == config.FwGlobal { fw.globalMode = true fw.globalPortRef = make(map[network.Port]int) } for { select { case <-fw.tomb.Dying(): return tomb.ErrDying case _, ok := <-fw.environWatcher.Changes(): if !ok { return watcher.MustErr(fw.environWatcher) } config, err := fw.st.EnvironConfig() if err != nil { return err } if err := fw.environ.SetConfig(config); err != nil { logger.Errorf("loaded invalid environment configuration: %v", err) } case change, ok := <-fw.machinesWatcher.Changes(): if !ok { return watcher.MustErr(fw.machinesWatcher) } for _, machineId := range change { fw.machineLifeChanged(names.NewMachineTag(machineId).String()) } if !reconciled { reconciled = true var err error if fw.globalMode { err = fw.reconcileGlobal() } else { err = fw.reconcileInstances() } if err != nil { return err } } case change := <-fw.unitsChange: if err := fw.unitsChanged(change); err != nil { return err } case change := <-fw.portsChange: change.unitd.ports = change.ports if err := fw.flushUnits([]*unitData{change.unitd}); err != nil { return errors.Annotate(err, "cannot change firewall ports") } case change := <-fw.exposedChange: change.serviced.exposed = change.exposed unitds := []*unitData{} for _, unitd := range change.serviced.unitds { unitds = append(unitds, unitd) } if err := fw.flushUnits(unitds); err != nil { return errors.Annotate(err, "cannot change firewall ports") } } } }