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  }