github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/migrationmaster/manifold.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package migrationmaster 5 6 import ( 7 "github.com/juju/clock" 8 "github.com/juju/errors" 9 "github.com/juju/worker/v3" 10 "github.com/juju/worker/v3/dependency" 11 12 "github.com/juju/juju/agent" 13 "github.com/juju/juju/api" 14 "github.com/juju/juju/api/base" 15 "github.com/juju/juju/api/client/charms" 16 "github.com/juju/juju/api/http" 17 "github.com/juju/juju/migration" 18 "github.com/juju/juju/worker/fortress" 19 ) 20 21 // logger is here to stop the desire of creating a package level logger. 22 // Don't do this, instead pass one passed as manifold config. 23 type logger interface{} 24 25 var _ logger = struct{}{} 26 27 // ManifoldConfig defines the names of the manifolds on which a 28 // Worker manifold will depend. 29 type ManifoldConfig struct { 30 AgentName string 31 APICallerName string 32 FortressName string 33 34 Clock clock.Clock 35 NewFacade func(base.APICaller) (Facade, error) 36 NewWorker func(Config) (worker.Worker, error) 37 } 38 39 // Validate is called by start to check for bad configuration. 40 func (config ManifoldConfig) Validate() error { 41 if config.AgentName == "" { 42 return errors.NotValidf("empty AgentName") 43 } 44 if config.APICallerName == "" { 45 return errors.NotValidf("empty APICallerName") 46 } 47 if config.FortressName == "" { 48 return errors.NotValidf("empty FortressName") 49 } 50 if config.NewFacade == nil { 51 return errors.NotValidf("nil NewFacade") 52 } 53 if config.NewWorker == nil { 54 return errors.NotValidf("nil NewWorker") 55 } 56 if config.Clock == nil { 57 return errors.NotValidf("nil Clock") 58 } 59 return nil 60 } 61 62 // start is a StartFunc for a Worker manifold. 63 func (config ManifoldConfig) start(context dependency.Context) (worker.Worker, error) { 64 if err := config.Validate(); err != nil { 65 return nil, errors.Trace(err) 66 } 67 68 var agent agent.Agent 69 if err := context.Get(config.AgentName, &agent); err != nil { 70 return nil, errors.Trace(err) 71 } 72 var apiConn api.Connection 73 if err := context.Get(config.APICallerName, &apiConn); err != nil { 74 return nil, errors.Trace(err) 75 } 76 var guard fortress.Guard 77 if err := context.Get(config.FortressName, &guard); err != nil { 78 return nil, errors.Trace(err) 79 } 80 facade, err := config.NewFacade(apiConn) 81 if err != nil { 82 return nil, errors.Trace(err) 83 } 84 charmDownloader, err := charms.NewCharmOpener(apiConn) 85 if err != nil { 86 return nil, errors.Trace(err) 87 } 88 toolsDownloader, err := http.NewURIOpener(apiConn) 89 if err != nil { 90 return nil, errors.Trace(err) 91 } 92 w, err := config.NewWorker(Config{ 93 ModelUUID: agent.CurrentConfig().Model().Id(), 94 Facade: facade, 95 Guard: guard, 96 APIOpen: api.Open, 97 UploadBinaries: migration.UploadBinaries, 98 CharmDownloader: charmDownloader, 99 ToolsDownloader: toolsDownloader, 100 Clock: config.Clock, 101 }) 102 if err != nil { 103 return nil, errors.Trace(err) 104 } 105 return w, nil 106 } 107 108 func errorFilter(err error) error { 109 switch errors.Cause(err) { 110 case ErrMigrated: 111 // If the model has migrated, the migrationmaster should no 112 // longer be running. 113 return dependency.ErrUninstall 114 case ErrInactive: 115 // If the migration is no longer active, restart the 116 // migrationmaster immediately so it can wait for the next 117 // attempt. 118 return dependency.ErrBounce 119 default: 120 return err 121 } 122 } 123 124 // Manifold packages a Worker for use in a dependency.Engine. 125 func Manifold(config ManifoldConfig) dependency.Manifold { 126 return dependency.Manifold{ 127 Inputs: []string{ 128 config.AgentName, 129 config.APICallerName, 130 config.FortressName, 131 }, 132 Start: config.start, 133 Filter: errorFilter, 134 } 135 }