github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/facades/controller/firewaller/modelfirewallruleswatcher.go (about)

     1  // Copyright 2023 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package firewaller
     5  
     6  import (
     7  	"github.com/juju/collections/set"
     8  	"github.com/juju/errors"
     9  	"github.com/juju/worker/v3/catacomb"
    10  )
    11  
    12  type modelFirewallRulesWatcher struct {
    13  	catacomb catacomb.Catacomb
    14  	backend  State
    15  
    16  	out chan struct{}
    17  
    18  	sshAllowCache set.Strings
    19  }
    20  
    21  // NewModelFirewallRulesWatcher returns a worker that notifies when a change to something
    22  // determining the model firewall rules takes place
    23  //
    24  // NOTE: At this time, ssh-allow model config item is the only thing that needs to be watched
    25  func NewModelFirewallRulesWatcher(st State) (*modelFirewallRulesWatcher, error) {
    26  	w := &modelFirewallRulesWatcher{
    27  		backend: st,
    28  		out:     make(chan struct{}),
    29  	}
    30  
    31  	err := catacomb.Invoke(catacomb.Plan{
    32  		Site: &w.catacomb,
    33  		Work: w.loop,
    34  	})
    35  	return w, err
    36  }
    37  
    38  func (w *modelFirewallRulesWatcher) loop() error {
    39  	defer close(w.out)
    40  
    41  	configWatcher := w.backend.WatchForModelConfigChanges()
    42  	if err := w.catacomb.Add(configWatcher); err != nil {
    43  		return errors.Trace(err)
    44  	}
    45  
    46  	var out chan struct{}
    47  
    48  	for {
    49  		select {
    50  		case <-w.catacomb.Dying():
    51  			return w.catacomb.ErrDying()
    52  		case out <- struct{}{}:
    53  			out = nil
    54  		case _, ok := <-configWatcher.Changes():
    55  			if !ok {
    56  				return w.catacomb.ErrDying()
    57  			}
    58  			cfg, err := w.backend.ModelConfig()
    59  			if err != nil {
    60  				return errors.Trace(err)
    61  			}
    62  			sshAllow := set.NewStrings(cfg.SSHAllow()...)
    63  			if !setEquals(sshAllow, w.sshAllowCache) {
    64  				out = w.out
    65  				w.sshAllowCache = sshAllow
    66  			}
    67  		}
    68  	}
    69  }
    70  
    71  func (w *modelFirewallRulesWatcher) Changes() <-chan struct{} {
    72  	return w.out
    73  }
    74  
    75  func (w *modelFirewallRulesWatcher) Kill() {
    76  	w.catacomb.Kill(nil)
    77  }
    78  
    79  func (w *modelFirewallRulesWatcher) Wait() error {
    80  	return w.catacomb.Wait()
    81  }
    82  
    83  func (w *modelFirewallRulesWatcher) Stop() error {
    84  	w.Kill()
    85  	return w.Wait()
    86  }
    87  
    88  func (w *modelFirewallRulesWatcher) Err() error {
    89  	return w.catacomb.Err()
    90  }