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  }