github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/caasoperator/manifold.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package caasoperator 5 6 import ( 7 "time" 8 9 "github.com/juju/clock" 10 "github.com/juju/errors" 11 "gopkg.in/juju/names.v2" 12 "gopkg.in/juju/worker.v1" 13 "gopkg.in/juju/worker.v1/dependency" 14 15 "github.com/juju/juju/agent" 16 "github.com/juju/juju/api/base" 17 apileadership "github.com/juju/juju/api/leadership" 18 apiuniter "github.com/juju/juju/api/uniter" 19 "github.com/juju/juju/apiserver/params" 20 coreleadership "github.com/juju/juju/core/leadership" 21 "github.com/juju/juju/core/machinelock" 22 "github.com/juju/juju/worker/fortress" 23 "github.com/juju/juju/worker/leadership" 24 "github.com/juju/juju/worker/uniter" 25 "github.com/juju/juju/worker/uniter/operation" 26 ) 27 28 // ManifoldConfig defines the names of the manifolds on which a 29 // Manifold will depend. 30 type ManifoldConfig struct { 31 AgentName string 32 APICallerName string 33 ClockName string 34 35 MachineLock machinelock.Lock 36 LeadershipGuarantee time.Duration 37 CharmDirName string 38 HookRetryStrategyName string 39 TranslateResolverErr func(error) error 40 41 NewWorker func(Config) (worker.Worker, error) 42 NewClient func(base.APICaller) Client 43 NewCharmDownloader func(base.APICaller) Downloader 44 } 45 46 func (config ManifoldConfig) Validate() error { 47 if config.AgentName == "" { 48 return errors.NotValidf("empty AgentName") 49 } 50 if config.APICallerName == "" { 51 return errors.NotValidf("empty APICallerName") 52 } 53 if config.ClockName == "" { 54 return errors.NotValidf("empty ClockName") 55 } 56 if config.NewWorker == nil { 57 return errors.NotValidf("missing NewWorker") 58 } 59 if config.NewClient == nil { 60 return errors.NotValidf("missing NewClient") 61 } 62 if config.NewCharmDownloader == nil { 63 return errors.NotValidf("missing NewCharmDownloader") 64 } 65 if config.CharmDirName == "" { 66 return errors.NotValidf("missing CharmDirName") 67 } 68 if config.MachineLock == nil { 69 return errors.NotValidf("missing MachineLock") 70 } 71 if config.HookRetryStrategyName == "" { 72 return errors.NotValidf("missing HookRetryStrategyName") 73 } 74 if config.LeadershipGuarantee == 0 { 75 return errors.NotValidf("missing LeadershipGuarantee") 76 } 77 return nil 78 } 79 80 // Manifold returns a dependency manifold that runs a caasoperator worker, 81 // using the resource names defined in the supplied config. 82 func Manifold(config ManifoldConfig) dependency.Manifold { 83 return dependency.Manifold{ 84 Inputs: []string{ 85 config.AgentName, 86 config.APICallerName, 87 config.ClockName, 88 config.CharmDirName, 89 config.HookRetryStrategyName, 90 }, 91 Start: func(context dependency.Context) (worker.Worker, error) { 92 if err := config.Validate(); err != nil { 93 return nil, errors.Trace(err) 94 } 95 96 var agent agent.Agent 97 if err := context.Get(config.AgentName, &agent); err != nil { 98 return nil, errors.Trace(err) 99 } 100 101 var apiCaller base.APICaller 102 if err := context.Get(config.APICallerName, &apiCaller); err != nil { 103 return nil, errors.Trace(err) 104 } 105 client := config.NewClient(apiCaller) 106 downloader := config.NewCharmDownloader(apiCaller) 107 108 var clock clock.Clock 109 if err := context.Get(config.ClockName, &clock); err != nil { 110 return nil, errors.Trace(err) 111 } 112 113 model, err := client.Model() 114 if err != nil { 115 return nil, errors.Trace(err) 116 } 117 118 var charmDirGuard fortress.Guard 119 if err := context.Get(config.CharmDirName, &charmDirGuard); err != nil { 120 return nil, err 121 } 122 123 var hookRetryStrategy params.RetryStrategy 124 if err := context.Get(config.HookRetryStrategyName, &hookRetryStrategy); err != nil { 125 return nil, err 126 } 127 128 // Configure and start the caasoperator worker. 129 agentConfig := agent.CurrentConfig() 130 tag := agentConfig.Tag() 131 applicationTag, ok := tag.(names.ApplicationTag) 132 if !ok { 133 return nil, errors.Errorf("expected an application tag, got %v", tag) 134 } 135 newUniterFunc := func(unitTag names.UnitTag) *apiuniter.State { 136 return apiuniter.NewState(apiCaller, unitTag) 137 } 138 leadershipTrackerFunc := func(unitTag names.UnitTag) coreleadership.Tracker { 139 claimer := apileadership.NewClient(apiCaller) 140 return leadership.NewTracker(unitTag, claimer, clock, config.LeadershipGuarantee) 141 } 142 w, err := config.NewWorker(Config{ 143 ModelUUID: agentConfig.Model().Id(), 144 ModelName: model.Name, 145 Application: applicationTag.Id(), 146 CharmGetter: client, 147 Clock: clock, 148 PodSpecSetter: client, 149 DataDir: agentConfig.DataDir(), 150 Downloader: downloader, 151 StatusSetter: client, 152 UnitGetter: client, 153 UnitRemover: client, 154 ApplicationWatcher: client, 155 VersionSetter: client, 156 StartUniterFunc: uniter.StartUniter, 157 158 LeadershipTrackerFunc: leadershipTrackerFunc, 159 UniterFacadeFunc: newUniterFunc, 160 UniterParams: &uniter.UniterParams{ 161 NewOperationExecutor: operation.NewExecutor, 162 DataDir: agentConfig.DataDir(), 163 Clock: clock, 164 MachineLock: config.MachineLock, 165 CharmDirGuard: charmDirGuard, 166 UpdateStatusSignal: uniter.NewUpdateStatusTimer(), 167 HookRetryStrategy: hookRetryStrategy, 168 TranslateResolverErr: config.TranslateResolverErr, 169 }, 170 }) 171 if err != nil { 172 return nil, errors.Trace(err) 173 } 174 return w, nil 175 }, 176 } 177 }