github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/worker/conv2state/converter.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package conv2state 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/loggo" 9 "github.com/juju/names" 10 11 apimachiner "github.com/juju/juju/api/machiner" 12 "github.com/juju/juju/api/watcher" 13 "github.com/juju/juju/apiserver/params" 14 "github.com/juju/juju/state/multiwatcher" 15 "github.com/juju/juju/worker" 16 ) 17 18 var logger = loggo.GetLogger("juju.worker.conv2state") 19 20 // New returns a new notify watch handler that will convert the given machine & 21 // agent to a state server. 22 func New(m *apimachiner.State, agent Agent) worker.NotifyWatchHandler { 23 return &converter{machiner: wrapper{m}, agent: agent} 24 } 25 26 // converter is a NotifyWatchHandler that converts a unit hosting machine to a 27 // state machine. 28 type converter struct { 29 agent Agent 30 machiner machiner 31 machine machine 32 } 33 34 // Agent is an interface that can have its password set and be told to restart. 35 type Agent interface { 36 Restart() error 37 Tag() names.Tag 38 } 39 40 // machiner is a type that creates machines from a tag. 41 type machiner interface { 42 Machine(tag names.MachineTag) (machine, error) 43 } 44 45 // machine is a type that has a list of jobs and can be watched. 46 type machine interface { 47 Jobs() (*params.JobsResult, error) 48 Watch() (watcher.NotifyWatcher, error) 49 } 50 51 // wrapper is a wrapper around api/machiner.State to match the (local) machiner 52 // interface. 53 type wrapper struct { 54 m *apimachiner.State 55 } 56 57 // Machines implements machiner.Machine and returns a machine from the wrapper 58 // api/machiner. 59 func (w wrapper) Machine(tag names.MachineTag) (machine, error) { 60 m, err := w.m.Machine(tag) 61 if err != nil { 62 return nil, err 63 } 64 return m, nil 65 } 66 67 // SetUp implements NotifyWatchHandler's SetUp method. It returns a watcher that 68 // checks for changes to the current machine. 69 func (c *converter) SetUp() (watcher.NotifyWatcher, error) { 70 m, err := c.machiner.Machine(c.agent.Tag().(names.MachineTag)) 71 if err != nil { 72 return nil, errors.Trace(err) 73 } 74 c.machine = m 75 return m.Watch() 76 } 77 78 // Handle implements NotifyWatchHandler's Handle method. If the change means 79 // that the machine is now expected to manage the environment, we change its 80 // password (to set its password in mongo) and restart the agent. 81 func (c *converter) Handle(_ <-chan struct{}) error { 82 results, err := c.machine.Jobs() 83 if err != nil { 84 return errors.Annotate(err, "can't get jobs for machine") 85 } 86 if !multiwatcher.AnyJobNeedsState(results.Jobs...) { 87 return nil 88 } 89 90 return errors.Trace(c.agent.Restart()) 91 } 92 93 // TearDown implements NotifyWatchHandler's TearDown method. 94 func (c *converter) TearDown() error { 95 return nil 96 }