launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/state/apiserver/deployer/deployer.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package deployer 5 6 import ( 7 "launchpad.net/errgo/errors" 8 "launchpad.net/juju-core/names" 9 "launchpad.net/juju-core/state" 10 "launchpad.net/juju-core/state/api/params" 11 "launchpad.net/juju-core/state/apiserver/common" 12 ) 13 14 var mask = errors.Mask 15 16 // DeployerAPI provides access to the Deployer API facade. 17 type DeployerAPI struct { 18 *common.Remover 19 *common.PasswordChanger 20 *common.LifeGetter 21 *common.StateAddresser 22 *common.APIAddresser 23 *common.UnitsWatcher 24 25 st *state.State 26 resources *common.Resources 27 authorizer common.Authorizer 28 } 29 30 // NewDeployerAPI creates a new server-side DeployerAPI facade. 31 func NewDeployerAPI( 32 st *state.State, 33 resources *common.Resources, 34 authorizer common.Authorizer, 35 ) (*DeployerAPI, error) { 36 if !authorizer.AuthMachineAgent() { 37 return nil, common.ErrPerm 38 } 39 getAuthFunc := func() (common.AuthFunc, error) { 40 // Get all units of the machine and cache them. 41 thisMachineTag := authorizer.GetAuthTag() 42 units, err := getAllUnits(st, thisMachineTag) 43 if err != nil { 44 return nil, mask(err) 45 } 46 47 // Then we just check if the unit is already known. 48 return func(tag string) bool { 49 for _, unit := range units { 50 if names.UnitTag(unit) == tag { 51 return true 52 } 53 } 54 return false 55 }, nil 56 } 57 getCanWatch := func() (common.AuthFunc, error) { 58 return authorizer.AuthOwner, nil 59 } 60 return &DeployerAPI{ 61 Remover: common.NewRemover(st, true, getAuthFunc), 62 PasswordChanger: common.NewPasswordChanger(st, getAuthFunc), 63 LifeGetter: common.NewLifeGetter(st, getAuthFunc), 64 StateAddresser: common.NewStateAddresser(st), 65 APIAddresser: common.NewAPIAddresser(st), 66 UnitsWatcher: common.NewUnitsWatcher(st, resources, getCanWatch), 67 st: st, 68 resources: resources, 69 authorizer: authorizer, 70 }, nil 71 } 72 73 // ConnectionInfo returns all the address information that the 74 // deployer task needs in one call. 75 func (d *DeployerAPI) ConnectionInfo() (result params.DeployerConnectionValues, err error) { 76 info, err := d.st.DeployerConnectionInfo() 77 if info != nil { 78 result = params.DeployerConnectionValues{ 79 StateAddresses: info.StateAddresses, 80 APIAddresses: info.APIAddresses, 81 SyslogPort: info.SyslogPort, 82 } 83 } 84 return result, err 85 } 86 87 // getAllUnits returns a list of all principal and subordinate units 88 // assigned to the given machine. 89 func getAllUnits(st *state.State, machineTag string) ([]string, error) { 90 _, id, err := names.ParseTag(machineTag, names.MachineTagKind) 91 if err != nil { 92 return nil, mask(err) 93 } 94 machine, err := st.Machine(id) 95 if err != nil { 96 return nil, mask(err) 97 } 98 99 // Start a watcher on machine's units, read the initial event and stop it. 100 watch := machine.WatchUnits() 101 defer watch.Stop() 102 if units, ok := <-watch.Changes(); ok { 103 return units, nil 104 } 105 return nil, errors.Newf("cannot obtain units of machine %q: %v", machineTag, watch.Err()) 106 }