github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/worker/leadership/manifold.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package leadership 5 6 import ( 7 "fmt" 8 "time" 9 10 "github.com/juju/errors" 11 "github.com/juju/utils/clock" 12 "gopkg.in/juju/names.v2" 13 14 "github.com/juju/juju/agent" 15 "github.com/juju/juju/api/base" 16 "github.com/juju/juju/api/leadership" 17 coreleadership "github.com/juju/juju/core/leadership" 18 "github.com/juju/juju/worker" 19 "github.com/juju/juju/worker/dependency" 20 ) 21 22 // ManifoldConfig defines the names of the manifolds on which a Manifold will depend. 23 type ManifoldConfig struct { 24 AgentName string 25 APICallerName string 26 Clock clock.Clock 27 LeadershipGuarantee time.Duration 28 } 29 30 // Manifold returns a manifold whose worker wraps a Tracker working on behalf of 31 // the dependency identified by AgentName. 32 func Manifold(config ManifoldConfig) dependency.Manifold { 33 return dependency.Manifold{ 34 Inputs: []string{ 35 config.AgentName, 36 config.APICallerName, 37 }, 38 Start: startFunc(config), 39 Output: outputFunc, 40 } 41 } 42 43 // startFunc returns a StartFunc that creates a worker based on the manifolds 44 // named in the supplied config. 45 func startFunc(config ManifoldConfig) dependency.StartFunc { 46 return func(context dependency.Context) (worker.Worker, error) { 47 if config.Clock == nil { 48 return nil, errors.NotValidf("missing Clock") 49 } 50 var agent agent.Agent 51 if err := context.Get(config.AgentName, &agent); err != nil { 52 return nil, err 53 } 54 var apiCaller base.APICaller 55 if err := context.Get(config.APICallerName, &apiCaller); err != nil { 56 return nil, err 57 } 58 return NewManifoldWorker(agent, apiCaller, config.Clock, config.LeadershipGuarantee) 59 } 60 } 61 62 // NewManifoldWorker wraps NewTracker for the convenience of startFunc. It 63 // exists primarily to be patched out via NewManifoldWorker for ease of testing, 64 // and is not itself directly tested. It would almost certainly be better to 65 // pass the constructor dependencies in as explicit manifold config. 66 var NewManifoldWorker = func(agent agent.Agent, apiCaller base.APICaller, clock clock.Clock, guarantee time.Duration) (worker.Worker, error) { 67 tag := agent.CurrentConfig().Tag() 68 unitTag, ok := tag.(names.UnitTag) 69 if !ok { 70 return nil, fmt.Errorf("expected a unit tag; got %q", tag) 71 } 72 claimer := leadership.NewClient(apiCaller) 73 return NewTracker(unitTag, claimer, clock, guarantee), nil 74 } 75 76 // outputFunc extracts the coreleadership.Tracker from a *Tracker passed in as a Worker. 77 func outputFunc(in worker.Worker, out interface{}) error { 78 inWorker, _ := in.(*Tracker) 79 if inWorker == nil { 80 return errors.Errorf("expected *Tracker input; got %T", in) 81 } 82 outPointer, _ := out.(*coreleadership.Tracker) 83 if outPointer == nil { 84 return errors.Errorf("expected *leadership.Tracker output; got %T", out) 85 } 86 *outPointer = inWorker 87 return nil 88 }