github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/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  	"gopkg.in/juju/names.v2"
    10  
    11  	"github.com/juju/juju/apiserver/common"
    12  	"github.com/juju/juju/apiserver/facade"
    13  	"github.com/juju/juju/apiserver/params"
    14  	"github.com/juju/juju/state"
    15  )
    16  
    17  func init() {
    18  	common.RegisterStandardFacade("Deployer", 1, NewDeployerAPI)
    19  }
    20  
    21  // DeployerAPI provides access to the Deployer API facade.
    22  type DeployerAPI struct {
    23  	*common.Remover
    24  	*common.PasswordChanger
    25  	*common.LifeGetter
    26  	*common.StateAddresser
    27  	*common.APIAddresser
    28  	*common.UnitsWatcher
    29  	*common.StatusSetter
    30  
    31  	st         *state.State
    32  	resources  facade.Resources
    33  	authorizer facade.Authorizer
    34  }
    35  
    36  // NewDeployerAPI creates a new server-side DeployerAPI facade.
    37  func NewDeployerAPI(
    38  	st *state.State,
    39  	resources facade.Resources,
    40  	authorizer facade.Authorizer,
    41  ) (*DeployerAPI, error) {
    42  	if !authorizer.AuthMachineAgent() {
    43  		return nil, common.ErrPerm
    44  	}
    45  	getAuthFunc := func() (common.AuthFunc, error) {
    46  		// Get all units of the machine and cache them.
    47  		thisMachineTag := authorizer.GetAuthTag()
    48  		units, err := getAllUnits(st, thisMachineTag)
    49  		if err != nil {
    50  			return nil, err
    51  		}
    52  		// Then we just check if the unit is already known.
    53  		return func(tag names.Tag) bool {
    54  			for _, unit := range units {
    55  				// TODO (thumper): remove the names.Tag conversion when gccgo
    56  				// implements concrete-type-to-interface comparison correctly.
    57  				if names.Tag(names.NewUnitTag(unit)) == tag {
    58  					return true
    59  				}
    60  			}
    61  			return false
    62  		}, nil
    63  	}
    64  	getCanWatch := func() (common.AuthFunc, error) {
    65  		return authorizer.AuthOwner, nil
    66  	}
    67  	return &DeployerAPI{
    68  		Remover:         common.NewRemover(st, true, getAuthFunc),
    69  		PasswordChanger: common.NewPasswordChanger(st, getAuthFunc),
    70  		LifeGetter:      common.NewLifeGetter(st, getAuthFunc),
    71  		StateAddresser:  common.NewStateAddresser(st),
    72  		APIAddresser:    common.NewAPIAddresser(st, resources),
    73  		UnitsWatcher:    common.NewUnitsWatcher(st, resources, getCanWatch),
    74  		StatusSetter:    common.NewStatusSetter(st, getAuthFunc),
    75  		st:              st,
    76  		resources:       resources,
    77  		authorizer:      authorizer,
    78  	}, nil
    79  }
    80  
    81  // ConnectionInfo returns all the address information that the
    82  // deployer task needs in one call.
    83  func (d *DeployerAPI) ConnectionInfo() (result params.DeployerConnectionValues, err error) {
    84  	stateAddrs, err := d.StateAddresses()
    85  	if err != nil {
    86  		return result, err
    87  	}
    88  
    89  	apiAddrs, err := d.APIAddresses()
    90  	if err != nil {
    91  		return result, err
    92  	}
    93  
    94  	result = params.DeployerConnectionValues{
    95  		StateAddresses: stateAddrs.Result,
    96  		APIAddresses:   apiAddrs.Result,
    97  	}
    98  
    99  	return result, err
   100  }
   101  
   102  // SetStatus sets the status of the specified entities.
   103  func (d *DeployerAPI) SetStatus(args params.SetStatus) (params.ErrorResults, error) {
   104  	return d.StatusSetter.SetStatus(args)
   105  }
   106  
   107  // getAllUnits returns a list of all principal and subordinate units
   108  // assigned to the given machine.
   109  func getAllUnits(st *state.State, tag names.Tag) ([]string, error) {
   110  	machine, err := st.Machine(tag.Id())
   111  	if err != nil {
   112  		return nil, err
   113  	}
   114  	// Start a watcher on machine's units, read the initial event and stop it.
   115  	watch := machine.WatchUnits()
   116  	defer watch.Stop()
   117  	if units, ok := <-watch.Changes(); ok {
   118  		return units, nil
   119  	}
   120  	return nil, fmt.Errorf("cannot obtain units of machine %q: %v", tag, watch.Err())
   121  }