예제 #1
0
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")
}
예제 #2
0
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")
}
예제 #3
0
// 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
}
예제 #4
0
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)
}
예제 #5
0
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())
		}
	}
}
예제 #6
0
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",
	)
}
예제 #7
0
파일: firewaller.go 프로젝트: rogpeppe/juju
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")
			}
		}
	}
}