github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/caasfirewaller/worker.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package caasfirewaller
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/loggo"
     9  	"gopkg.in/juju/worker.v1"
    10  	"gopkg.in/juju/worker.v1/catacomb"
    11  
    12  	"github.com/juju/juju/core/life"
    13  )
    14  
    15  var logger = loggo.GetLogger("juju.workers.caasfirewaller")
    16  
    17  // Config holds configuration for the CAAS unit firewaller worker.
    18  type Config struct {
    19  	ControllerUUID    string
    20  	ModelUUID         string
    21  	ApplicationGetter ApplicationGetter
    22  	LifeGetter        LifeGetter
    23  	ServiceExposer    ServiceExposer
    24  }
    25  
    26  // Validate validates the worker configuration.
    27  func (config Config) Validate() error {
    28  	if config.ControllerUUID == "" {
    29  		return errors.NotValidf("missing ControllerUUID")
    30  	}
    31  	if config.ModelUUID == "" {
    32  		return errors.NotValidf("missing ModelUUID")
    33  	}
    34  	if config.ApplicationGetter == nil {
    35  		return errors.NotValidf("missing ApplicationGetter")
    36  	}
    37  	if config.ServiceExposer == nil {
    38  		return errors.NotValidf("missing ServiceExposer")
    39  	}
    40  	if config.LifeGetter == nil {
    41  		return errors.NotValidf("missing LifeGetter")
    42  	}
    43  	return nil
    44  }
    45  
    46  // NewWorker starts and returns a new CAAS unit firewaller worker.
    47  func NewWorker(config Config) (worker.Worker, error) {
    48  	if err := config.Validate(); err != nil {
    49  		return nil, errors.Trace(err)
    50  	}
    51  	p := &firewaller{config: config}
    52  	err := catacomb.Invoke(catacomb.Plan{
    53  		Site: &p.catacomb,
    54  		Work: p.loop,
    55  	})
    56  	return p, err
    57  }
    58  
    59  type firewaller struct {
    60  	catacomb catacomb.Catacomb
    61  	config   Config
    62  }
    63  
    64  // Kill is part of the worker.Worker interface.
    65  func (p *firewaller) Kill() {
    66  	p.catacomb.Kill(nil)
    67  }
    68  
    69  // Wait is part of the worker.Worker interface.
    70  func (p *firewaller) Wait() error {
    71  	return p.catacomb.Wait()
    72  }
    73  
    74  func (p *firewaller) loop() error {
    75  	w, err := p.config.ApplicationGetter.WatchApplications()
    76  	if err != nil {
    77  		return errors.Trace(err)
    78  	}
    79  	if err := p.catacomb.Add(w); err != nil {
    80  		return errors.Trace(err)
    81  	}
    82  
    83  	appWorkers := make(map[string]worker.Worker)
    84  	for {
    85  		select {
    86  		case <-p.catacomb.Dying():
    87  			return p.catacomb.ErrDying()
    88  		case apps, ok := <-w.Changes():
    89  			if !ok {
    90  				return errors.New("watcher closed channel")
    91  			}
    92  			for _, appId := range apps {
    93  				appLife, err := p.config.LifeGetter.Life(appId)
    94  				if errors.IsNotFound(err) {
    95  					w, ok := appWorkers[appId]
    96  					if ok {
    97  						if err := worker.Stop(w); err != nil {
    98  							logger.Errorf("error stopping caas firewaller: %v", err)
    99  						}
   100  						delete(appWorkers, appId)
   101  					}
   102  					continue
   103  				}
   104  				if err != nil {
   105  					return errors.Trace(err)
   106  				}
   107  				if _, ok := appWorkers[appId]; ok || appLife == life.Dead {
   108  					// Already watching the application. or we're
   109  					// not yet watching it and it's dead.
   110  					continue
   111  				}
   112  				w, err := newApplicationWorker(
   113  					p.config.ControllerUUID,
   114  					p.config.ModelUUID,
   115  					appId,
   116  					p.config.ApplicationGetter,
   117  					p.config.ServiceExposer,
   118  					p.config.LifeGetter,
   119  				)
   120  				if err != nil {
   121  					return errors.Trace(err)
   122  				}
   123  				appWorkers[appId] = w
   124  				p.catacomb.Add(w)
   125  			}
   126  		}
   127  	}
   128  }