github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/uniter/manifold.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package uniter 5 6 import ( 7 "github.com/juju/clock" 8 "github.com/juju/errors" 9 "gopkg.in/juju/names.v2" 10 "gopkg.in/juju/worker.v1" 11 "gopkg.in/juju/worker.v1/dependency" 12 13 "github.com/juju/juju/agent" 14 "github.com/juju/juju/api" 15 "github.com/juju/juju/api/uniter" 16 "github.com/juju/juju/apiserver/params" 17 "github.com/juju/juju/core/leadership" 18 "github.com/juju/juju/core/machinelock" 19 "github.com/juju/juju/worker/fortress" 20 "github.com/juju/juju/worker/uniter/operation" 21 "github.com/juju/juju/worker/uniter/resolver" 22 ) 23 24 // ManifoldConfig defines the names of the manifolds on which a 25 // Manifold will depend. 26 type ManifoldConfig struct { 27 AgentName string 28 APICallerName string 29 MachineLock machinelock.Lock 30 Clock clock.Clock 31 LeadershipTrackerName string 32 CharmDirName string 33 HookRetryStrategyName string 34 TranslateResolverErr func(error) error 35 } 36 37 // Manifold returns a dependency manifold that runs a uniter worker, 38 // using the resource names defined in the supplied config. 39 func Manifold(config ManifoldConfig) dependency.Manifold { 40 return dependency.Manifold{ 41 Inputs: []string{ 42 config.AgentName, 43 config.APICallerName, 44 config.LeadershipTrackerName, 45 config.CharmDirName, 46 config.HookRetryStrategyName, 47 }, 48 Start: func(context dependency.Context) (worker.Worker, error) { 49 if config.Clock == nil { 50 return nil, errors.NotValidf("missing Clock") 51 } 52 if config.MachineLock == nil { 53 return nil, errors.NotValidf("missing MachineLock") 54 } 55 56 // Collect all required resources. 57 var agent agent.Agent 58 if err := context.Get(config.AgentName, &agent); err != nil { 59 return nil, err 60 } 61 var apiConn api.Connection 62 if err := context.Get(config.APICallerName, &apiConn); err != nil { 63 // TODO(fwereade): absence of an APICaller shouldn't be the end of 64 // the world -- we ought to return a type that can at least run the 65 // leader-deposed hook -- but that's not done yet. 66 return nil, err 67 } 68 var leadershipTracker leadership.Tracker 69 if err := context.Get(config.LeadershipTrackerName, &leadershipTracker); err != nil { 70 return nil, err 71 } 72 var charmDirGuard fortress.Guard 73 if err := context.Get(config.CharmDirName, &charmDirGuard); err != nil { 74 return nil, err 75 } 76 77 var hookRetryStrategy params.RetryStrategy 78 if err := context.Get(config.HookRetryStrategyName, &hookRetryStrategy); err != nil { 79 return nil, err 80 } 81 82 downloader := api.NewCharmDownloader(apiConn) 83 84 manifoldConfig := config 85 // Configure and start the uniter. 86 agentConfig := agent.CurrentConfig() 87 tag := agentConfig.Tag() 88 unitTag, ok := tag.(names.UnitTag) 89 if !ok { 90 return nil, errors.Errorf("expected a unit tag, got %v", tag) 91 } 92 uniterFacade := uniter.NewState(apiConn, unitTag) 93 uniter, err := NewUniter(&UniterParams{ 94 UniterFacade: uniterFacade, 95 UnitTag: unitTag, 96 LeadershipTracker: leadershipTracker, 97 DataDir: agentConfig.DataDir(), 98 Downloader: downloader, 99 MachineLock: manifoldConfig.MachineLock, 100 CharmDirGuard: charmDirGuard, 101 UpdateStatusSignal: NewUpdateStatusTimer(), 102 HookRetryStrategy: hookRetryStrategy, 103 NewOperationExecutor: operation.NewExecutor, 104 TranslateResolverErr: config.TranslateResolverErr, 105 Clock: manifoldConfig.Clock, 106 }) 107 if err != nil { 108 return nil, errors.Trace(err) 109 } 110 return uniter, nil 111 }, 112 } 113 } 114 115 // TranslateFortressErrors turns errors returned by dependent 116 // manifolds due to fortress lockdown (i.e. model migration) into an 117 // error which causes the resolver loop to be restarted. When this 118 // happens the uniter is about to be shut down anyway. 119 func TranslateFortressErrors(err error) error { 120 if fortress.IsFortressError(err) { 121 return resolver.ErrRestart 122 } 123 return err 124 }