github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/action/run.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package action
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/names"
    11  	"github.com/juju/utils/set"
    12  
    13  	"github.com/juju/juju/apiserver/params"
    14  	"github.com/juju/juju/core/actions"
    15  	"github.com/juju/juju/state"
    16  )
    17  
    18  // getAllUnitNames returns a sequence of valid Unit objects from state. If any
    19  // of the service names or unit names are not found, an error is returned.
    20  func getAllUnitNames(st *state.State, units, services []string) (result []names.Tag, err error) {
    21  	unitsSet := set.NewStrings(units...)
    22  	for _, name := range services {
    23  		service, err := st.Service(name)
    24  		if err != nil {
    25  			return nil, err
    26  		}
    27  		units, err := service.AllUnits()
    28  		if err != nil {
    29  			return nil, err
    30  		}
    31  		for _, unit := range units {
    32  			unitsSet.Add(unit.Name())
    33  		}
    34  	}
    35  	for _, unitName := range unitsSet.SortedValues() {
    36  		result = append(result, names.NewUnitTag(unitName))
    37  	}
    38  	return result, nil
    39  }
    40  
    41  // Run the commands specified on the machines identified through the
    42  // list of machines, units and services.
    43  func (a *ActionAPI) Run(run params.RunParams) (results params.ActionResults, err error) {
    44  	if err := a.check.ChangeAllowed(); err != nil {
    45  		return results, errors.Trace(err)
    46  	}
    47  
    48  	units, err := getAllUnitNames(a.state, run.Units, run.Services)
    49  	if err != nil {
    50  		return results, errors.Trace(err)
    51  	}
    52  
    53  	machines := make([]names.Tag, len(run.Machines))
    54  	for i, machineId := range run.Machines {
    55  		if !names.IsValidMachine(machineId) {
    56  			return results, errors.Errorf("invalid machine id %q", machineId)
    57  		}
    58  		machines[i] = names.NewMachineTag(machineId)
    59  	}
    60  
    61  	actionParams := a.createActionsParams(append(units, machines...), run.Commands, run.Timeout)
    62  
    63  	return queueActions(a, actionParams)
    64  }
    65  
    66  // RunOnAllMachines attempts to run the specified command on all the machines.
    67  func (a *ActionAPI) RunOnAllMachines(run params.RunParams) (results params.ActionResults, err error) {
    68  	if err := a.check.ChangeAllowed(); err != nil {
    69  		return results, errors.Trace(err)
    70  	}
    71  
    72  	machines, err := a.state.AllMachines()
    73  	if err != nil {
    74  		return results, err
    75  	}
    76  	machineTags := make([]names.Tag, len(machines))
    77  	for i, machine := range machines {
    78  		machineTags[i] = machine.Tag()
    79  	}
    80  
    81  	actionParams := a.createActionsParams(machineTags, run.Commands, run.Timeout)
    82  
    83  	return queueActions(a, actionParams)
    84  }
    85  
    86  func (a *ActionAPI) createActionsParams(actionReceiverTags []names.Tag, quotedCommands string, timeout time.Duration) params.Actions {
    87  
    88  	apiActionParams := params.Actions{Actions: []params.Action{}}
    89  
    90  	actionParams := map[string]interface{}{}
    91  	actionParams["command"] = quotedCommands
    92  	actionParams["timeout"] = timeout.Nanoseconds()
    93  
    94  	for _, tag := range actionReceiverTags {
    95  		apiActionParams.Actions = append(apiActionParams.Actions, params.Action{
    96  			Receiver:   tag.String(),
    97  			Name:       actions.JujuRunActionName,
    98  			Parameters: actionParams,
    99  		})
   100  	}
   101  
   102  	return apiActionParams
   103  }
   104  
   105  var queueActions = func(a *ActionAPI, args params.Actions) (results params.ActionResults, err error) {
   106  	return a.Enqueue(args)
   107  }