github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/upgradeseries/manifold.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package upgradeseries 5 6 import ( 7 "github.com/juju/errors" 8 "gopkg.in/juju/names.v2" 9 "gopkg.in/juju/worker.v1" 10 "gopkg.in/juju/worker.v1/dependency" 11 12 "github.com/juju/juju/agent" 13 "github.com/juju/juju/api/base" 14 "github.com/juju/juju/cmd/jujud/agent/engine" 15 "github.com/juju/juju/service" 16 ) 17 18 // ManifoldConfig holds the information necessary for the dependency engine to 19 // to run an upgrade-series worker. 20 type ManifoldConfig struct { 21 AgentName string 22 APICallerName string 23 24 Logger Logger 25 NewFacade func(base.APICaller, names.Tag) Facade 26 NewWorker func(Config) (worker.Worker, error) 27 } 28 29 // Validate validates the manifold configuration. 30 func (config ManifoldConfig) Validate() error { 31 if config.Logger == nil { 32 return errors.NotValidf("nil Logger") 33 } 34 if config.NewWorker == nil { 35 return errors.NotValidf("nil NewWorker function") 36 } 37 if config.NewFacade == nil { 38 return errors.NotValidf("nil NewFacade function") 39 } 40 return nil 41 } 42 43 // Manifold returns a dependency manifold that runs an upgrade-series worker, 44 // using the resource names defined in the supplied config. 45 func Manifold(config ManifoldConfig) dependency.Manifold { 46 typedConfig := engine.AgentAPIManifoldConfig{ 47 AgentName: config.AgentName, 48 APICallerName: config.APICallerName, 49 } 50 return engine.AgentAPIManifold(typedConfig, config.newWorker) 51 } 52 53 // newWorker wraps NewWorker for use in a engine.AgentAPIManifold. 54 func (config ManifoldConfig) newWorker(a agent.Agent, apiCaller base.APICaller) (worker.Worker, error) { 55 if err := config.Validate(); err != nil { 56 return nil, errors.Trace(err) 57 } 58 59 // Ensure that we have a machine tag. 60 agentCfg := a.CurrentConfig() 61 tag, ok := agentCfg.Tag().(names.MachineTag) 62 if !ok { 63 return nil, errors.Errorf("expected a machine tag, got %v", tag) 64 } 65 66 // Partially apply the NewFacade method and pass it as a factory. 67 // This is so the worker can use the API server in different contexts. 68 // TODO (manadart 2018-08-30): This behaviour is vestigial. 69 // We no longer need a factory and can pass a concrete facade. 70 newFacade := func(t names.Tag) Facade { 71 return config.NewFacade(apiCaller, t) 72 } 73 74 // Partially apply Upgrader factory function so we only need to request 75 // using the getter for the target OS series. 76 newUpgrader := func(targetSeries string) (Upgrader, error) { 77 return NewUpgrader(targetSeries, service.NewServiceManagerWithDefaults(), config.Logger) 78 } 79 80 cfg := Config{ 81 Tag: tag, 82 Logger: config.Logger, 83 FacadeFactory: newFacade, 84 Service: &serviceAccess{}, 85 UpgraderFactory: newUpgrader, 86 } 87 88 w, err := config.NewWorker(cfg) 89 return w, errors.Annotate(err, "starting machine upgrade series worker") 90 }