github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/upgradesteps/manifold.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package upgradesteps 5 6 import ( 7 "time" 8 9 "github.com/juju/clock" 10 "github.com/juju/errors" 11 "github.com/juju/names/v5" 12 "github.com/juju/retry" 13 "github.com/juju/worker/v3" 14 "github.com/juju/worker/v3/dependency" 15 16 "github.com/juju/juju/agent" 17 "github.com/juju/juju/api" 18 apiagent "github.com/juju/juju/api/agent/agent" 19 "github.com/juju/juju/state" 20 "github.com/juju/juju/upgrades" 21 "github.com/juju/juju/worker/gate" 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 UpgradeStepsGateName string 30 OpenStateForUpgrade func() (*state.StatePool, error) 31 PreUpgradeSteps upgrades.PreUpgradeStepsFunc 32 NewAgentStatusSetter func(apiConn api.Connection) (StatusSetter, error) 33 } 34 35 // Manifold returns a dependency manifold that runs an upgrader 36 // worker, using the resource names defined in the supplied config. 37 func Manifold(config ManifoldConfig) dependency.Manifold { 38 return dependency.Manifold{ 39 Inputs: []string{ 40 config.AgentName, 41 config.APICallerName, 42 config.UpgradeStepsGateName, 43 }, 44 Start: func(context dependency.Context) (worker.Worker, error) { 45 // Sanity checks 46 if config.OpenStateForUpgrade == nil { 47 return nil, errors.New("missing OpenStateForUpgrade in config") 48 } 49 if config.PreUpgradeSteps == nil { 50 return nil, errors.New("missing PreUpgradeSteps in config") 51 } 52 53 // Get the agent. 54 var localAgent agent.Agent 55 if err := context.Get(config.AgentName, &localAgent); err != nil { 56 return nil, errors.Trace(err) 57 } 58 59 // Get API connection. 60 // TODO(fwereade): can we make the worker use an 61 // APICaller instead? should be able to depend on 62 // the Engine to abort us when conn is closed... 63 var apiConn api.Connection 64 if err := context.Get(config.APICallerName, &apiConn); err != nil { 65 return nil, errors.Trace(err) 66 } 67 68 // Get upgradeSteps completed lock. 69 var upgradeStepsLock gate.Lock 70 if err := context.Get(config.UpgradeStepsGateName, &upgradeStepsLock); err != nil { 71 return nil, errors.Trace(err) 72 } 73 74 // Get a component capable of setting machine status 75 // to indicate progress to the user. 76 statusSetter, err := config.NewAgentStatusSetter(apiConn) 77 if err != nil { 78 return nil, errors.Trace(err) 79 } 80 // Application tag for CAAS operator; controller, 81 // machine or unit tag for agents. 82 agentTag := localAgent.CurrentConfig().Tag() 83 isOperator := agentTag.Kind() == names.ApplicationTagKind 84 85 var isController bool 86 if !isOperator { 87 isController, err = apiagent.IsController(apiConn, agentTag) 88 if err != nil { 89 return nil, errors.Trace(err) 90 } 91 } 92 return NewWorker( 93 upgradeStepsLock, 94 localAgent, 95 apiConn, 96 isController, 97 config.OpenStateForUpgrade, 98 config.PreUpgradeSteps, 99 retry.CallArgs{ 100 Clock: clock.WallClock, 101 Delay: 2 * time.Minute, 102 Attempts: 5, 103 }, 104 statusSetter, 105 isOperator, 106 ) 107 }, 108 } 109 }