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