github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/migrationflag/manifold.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package migrationflag 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/worker/v3" 9 "github.com/juju/worker/v3/dependency" 10 11 "github.com/juju/juju/api/base" 12 "github.com/juju/juju/cmd/jujud/agent/engine" 13 ) 14 15 // logger is here to stop the desire of creating a package level logger. 16 // Don't do this, instead pass one passed as manifold config. 17 type logger interface{} 18 19 var _ logger = struct{}{} 20 21 // ManifoldConfig holds the dependencies and configuration for a 22 // Worker manifold. 23 type ManifoldConfig struct { 24 APICallerName string 25 Check Predicate 26 27 NewFacade func(base.APICaller) (Facade, error) 28 NewWorker func(Config) (worker.Worker, error) 29 } 30 31 // validate is called by start to check for bad configuration. 32 func (config ManifoldConfig) validate() error { 33 if config.APICallerName == "" { 34 return errors.NotValidf("empty APICallerName") 35 } 36 if config.Check == nil { 37 return errors.NotValidf("nil Check") 38 } 39 if config.NewFacade == nil { 40 return errors.NotValidf("nil NewFacade") 41 } 42 if config.NewWorker == nil { 43 return errors.NotValidf("nil NewWorker") 44 } 45 return nil 46 } 47 48 // start is a StartFunc for a Worker manifold. 49 func (config ManifoldConfig) start(context dependency.Context) (worker.Worker, error) { 50 if err := config.validate(); err != nil { 51 return nil, errors.Trace(err) 52 } 53 var apiCaller base.APICaller 54 if err := context.Get(config.APICallerName, &apiCaller); err != nil { 55 return nil, errors.Trace(err) 56 } 57 facade, err := config.NewFacade(apiCaller) 58 if err != nil { 59 return nil, errors.Trace(err) 60 } 61 modelTag, ok := apiCaller.ModelTag() 62 if !ok { 63 return nil, errors.New("API connection is controller-only (should never happen)") 64 } 65 worker, err := config.NewWorker(Config{ 66 Facade: facade, 67 Model: modelTag.Id(), 68 Check: config.Check, 69 }) 70 if err != nil { 71 return nil, errors.Trace(err) 72 } 73 return worker, nil 74 } 75 76 // Manifold packages a Worker for use in a dependency.Engine. 77 func Manifold(config ManifoldConfig) dependency.Manifold { 78 return dependency.Manifold{ 79 Inputs: []string{config.APICallerName}, 80 Start: config.start, 81 Output: engine.FlagOutput, 82 Filter: bounceErrChanged, 83 } 84 } 85 86 // bounceErrChanged converts ErrChanged to dependency.ErrBounce. 87 func bounceErrChanged(err error) error { 88 if errors.Cause(err) == ErrChanged { 89 return dependency.ErrBounce 90 } 91 return err 92 }