github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/upgradedatabase/manifold.go (about) 1 // Copyright 2019 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package upgradedatabase 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 "github.com/juju/retry" 11 "github.com/juju/version/v2" 12 "github.com/juju/worker/v3" 13 "github.com/juju/worker/v3/dependency" 14 15 "github.com/juju/juju/agent" 16 "github.com/juju/juju/state" 17 "github.com/juju/juju/upgrades" 18 "github.com/juju/juju/worker/gate" 19 ) 20 21 // ManifoldConfig defines the configuration on which this manifold depends. 22 type ManifoldConfig struct { 23 AgentName string 24 UpgradeDBGateName string 25 Logger Logger 26 OpenState func() (*state.StatePool, error) 27 Clock Clock 28 } 29 30 // Validate returns an error if the manifold config is not valid. 31 func (cfg ManifoldConfig) Validate() error { 32 if cfg.UpgradeDBGateName == "" { 33 return errors.NotValidf("empty UpgradeDBGateName") 34 } 35 if cfg.Logger == nil { 36 return errors.NotValidf("nil Logger") 37 } 38 if cfg.OpenState == nil { 39 return errors.NotValidf("nil OpenState function") 40 } 41 if cfg.Clock == nil { 42 return errors.NotValidf("nil Clock") 43 } 44 return nil 45 } 46 47 // Manifold returns a dependency manifold that runs a database upgrade worker 48 // using the resource names defined in the supplied config. 49 func Manifold(cfg ManifoldConfig) dependency.Manifold { 50 return dependency.Manifold{ 51 Inputs: []string{ 52 cfg.AgentName, 53 cfg.UpgradeDBGateName, 54 }, 55 Start: func(context dependency.Context) (worker.Worker, error) { 56 // Get the completed lock. 57 var upgradeStepsLock gate.Lock 58 if err := context.Get(cfg.UpgradeDBGateName, &upgradeStepsLock); err != nil { 59 return nil, errors.Trace(err) 60 } 61 62 // Determine this controller's agent and tag. 63 var controllerAgent agent.Agent 64 if err := context.Get(cfg.AgentName, &controllerAgent); err != nil { 65 return nil, errors.Trace(err) 66 } 67 tag := controllerAgent.CurrentConfig().Tag() 68 69 // Wrap the state pool factory to return our implementation. 70 openState := func() (Pool, error) { 71 p, err := cfg.OpenState() 72 if err != nil { 73 return nil, errors.Trace(err) 74 } 75 return &pool{p}, nil 76 } 77 78 // Wrap the upgrade steps execution so that we can generate a context lazily. 79 performUpgrade := func(v version.Number, t []upgrades.Target, c func() upgrades.Context) error { 80 return errors.Trace(upgrades.PerformStateUpgrade(v, t, c())) 81 } 82 83 workerCfg := Config{ 84 UpgradeComplete: upgradeStepsLock, 85 Tag: tag, 86 Agent: controllerAgent, 87 Logger: cfg.Logger, 88 OpenState: openState, 89 PerformUpgrade: performUpgrade, 90 RetryStrategy: retry.CallArgs{Clock: cfg.Clock, Delay: 2 * time.Minute, Attempts: 5}, 91 Clock: cfg.Clock, 92 } 93 w, err := NewWorker(workerCfg) 94 return w, errors.Annotate(err, "starting database upgrade worker") 95 }, 96 } 97 }