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 }