github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/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  	"github.com/juju/names"
    10  
    11  	"github.com/juju/juju/state"
    12  	"github.com/juju/juju/state/api/params"
    13  	"github.com/juju/juju/state/apiserver/common"
    14  )
    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, err
    45  		}
    46  		// Then we just check if the unit is already known.
    47  		return func(tag string) bool {
    48  			for _, unit := range units {
    49  				if names.UnitTag(unit) == tag {
    50  					return true
    51  				}
    52  			}
    53  			return false
    54  		}, nil
    55  	}
    56  	getCanWatch := func() (common.AuthFunc, error) {
    57  		return authorizer.AuthOwner, nil
    58  	}
    59  	return &DeployerAPI{
    60  		Remover:         common.NewRemover(st, true, getAuthFunc),
    61  		PasswordChanger: common.NewPasswordChanger(st, getAuthFunc),
    62  		LifeGetter:      common.NewLifeGetter(st, getAuthFunc),
    63  		StateAddresser:  common.NewStateAddresser(st),
    64  		APIAddresser:    common.NewAPIAddresser(st, resources),
    65  		UnitsWatcher:    common.NewUnitsWatcher(st, resources, getCanWatch),
    66  		st:              st,
    67  		resources:       resources,
    68  		authorizer:      authorizer,
    69  	}, nil
    70  }
    71  
    72  // ConnectionInfo returns all the address information that the
    73  // deployer task needs in one call.
    74  func (d *DeployerAPI) ConnectionInfo() (result params.DeployerConnectionValues, err error) {
    75  	info, err := d.st.DeployerConnectionInfo()
    76  	if info != nil {
    77  		result = params.DeployerConnectionValues{
    78  			StateAddresses: info.StateAddresses,
    79  			APIAddresses:   info.APIAddresses,
    80  		}
    81  	}
    82  	return result, err
    83  }
    84  
    85  // getAllUnits returns a list of all principal and subordinate units
    86  // assigned to the given machine.
    87  func getAllUnits(st *state.State, machineTag string) ([]string, error) {
    88  	_, id, err := names.ParseTag(machineTag, names.MachineTagKind)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	machine, err := st.Machine(id)
    93  	if err != nil {
    94  		return nil, err
    95  	}
    96  	// Start a watcher on machine's units, read the initial event and stop it.
    97  	watch := machine.WatchUnits()
    98  	defer watch.Stop()
    99  	if units, ok := <-watch.Changes(); ok {
   100  		return units, nil
   101  	}
   102  	return nil, fmt.Errorf("cannot obtain units of machine %q: %v", machineTag, watch.Err())
   103  }