github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/machiner/manifold.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package machiner 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 apiagent "github.com/juju/juju/api/agent" 14 "github.com/juju/juju/api/base" 15 apimachiner "github.com/juju/juju/api/machiner" 16 ) 17 18 // ManifoldConfig defines the names of the manifolds on which a 19 // Manifold will depend. 20 type ManifoldConfig struct { 21 AgentName string 22 APICallerName string 23 FanConfigurerName string 24 } 25 26 // Manifold returns a dependency manifold that runs a machiner worker, using 27 // the resource names defined in the supplied config. 28 func Manifold(config ManifoldConfig) dependency.Manifold { 29 return dependency.Manifold{ 30 Inputs: []string{ 31 config.AgentName, 32 config.APICallerName, 33 config.FanConfigurerName, 34 }, 35 Start: func(context dependency.Context) (worker.Worker, error) { 36 var agent agent.Agent 37 if err := context.Get(config.AgentName, &agent); err != nil { 38 return nil, err 39 } 40 var apiCaller base.APICaller 41 if err := context.Get(config.APICallerName, &apiCaller); err != nil { 42 return nil, err 43 } 44 var fanConfigurerReady bool 45 if err := context.Get(config.FanConfigurerName, &fanConfigurerReady); err != nil { 46 return nil, err 47 } 48 if !fanConfigurerReady { 49 return nil, dependency.ErrMissing 50 } 51 return newWorker(agent, apiCaller) 52 }, 53 } 54 } 55 56 // newWorker non-trivially wraps NewMachiner to specialise a engine.AgentAPIManifold. 57 // 58 // TODO(waigani) This function is currently covered by functional tests 59 // under the machine agent. Add unit tests once infrastructure to do so is 60 // in place. 61 func newWorker(a agent.Agent, apiCaller base.APICaller) (worker.Worker, error) { 62 currentConfig := a.CurrentConfig() 63 64 // TODO(fwereade): this functionality should be on the 65 // machiner facade instead -- or, better yet, separate 66 // the networking concerns from the lifecycle ones and 67 // have completely separate workers. 68 // 69 // (With their own facades.) 70 agentFacade, err := apiagent.NewState(apiCaller) 71 if err != nil { 72 return nil, errors.Trace(err) 73 } 74 modelConfig, err := agentFacade.ModelConfig() 75 if err != nil { 76 return nil, errors.Errorf("cannot read environment config: %v", err) 77 } 78 79 ignoreMachineAddresses, _ := modelConfig.IgnoreMachineAddresses() 80 // Containers only have machine addresses, so we can't ignore them. 81 tag := currentConfig.Tag() 82 if names.IsContainerMachine(tag.Id()) { 83 ignoreMachineAddresses = false 84 } 85 if ignoreMachineAddresses { 86 logger.Infof("machine addresses not used, only addresses from provider") 87 } 88 accessor := APIMachineAccessor{apimachiner.NewState(apiCaller)} 89 w, err := NewMachiner(Config{ 90 MachineAccessor: accessor, 91 Tag: tag.(names.MachineTag), 92 ClearMachineAddressesOnStart: ignoreMachineAddresses, 93 NotifyMachineDead: func() error { 94 return agent.SetCanUninstall(a) 95 }, 96 }) 97 if err != nil { 98 return nil, errors.Annotate(err, "cannot start machiner worker") 99 } 100 return w, err 101 }