github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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/utils/set"
    11  	"gopkg.in/juju/names.v2"
    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.Application(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  		if !names.IsValidUnit(unitName) {
    37  			return nil, errors.Errorf("invalid unit name %q", unitName)
    38  		}
    39  		result = append(result, names.NewUnitTag(unitName))
    40  	}
    41  	return result, nil
    42  }
    43  
    44  // Run the commands specified on the machines identified through the
    45  // list of machines, units and services.
    46  func (a *ActionAPI) Run(run params.RunParams) (results params.ActionResults, err error) {
    47  	if err := a.checkCanAdmin(); err != nil {
    48  		return results, err
    49  	}
    50  	if err := a.check.ChangeAllowed(); err != nil {
    51  		return results, errors.Trace(err)
    52  	}
    53  
    54  	units, err := getAllUnitNames(a.state, run.Units, run.Applications)
    55  	if err != nil {
    56  		return results, errors.Trace(err)
    57  	}
    58  
    59  	machines := make([]names.Tag, len(run.Machines))
    60  	for i, machineId := range run.Machines {
    61  		if !names.IsValidMachine(machineId) {
    62  			return results, errors.Errorf("invalid machine id %q", machineId)
    63  		}
    64  		machines[i] = names.NewMachineTag(machineId)
    65  	}
    66  
    67  	actionParams := a.createActionsParams(append(units, machines...), run.Commands, run.Timeout)
    68  
    69  	return queueActions(a, actionParams)
    70  }
    71  
    72  // RunOnAllMachines attempts to run the specified command on all the machines.
    73  func (a *ActionAPI) RunOnAllMachines(run params.RunParams) (results params.ActionResults, err error) {
    74  	if err := a.checkCanAdmin(); err != nil {
    75  		return results, err
    76  	}
    77  
    78  	if err := a.check.ChangeAllowed(); err != nil {
    79  		return results, errors.Trace(err)
    80  	}
    81  
    82  	machines, err := a.state.AllMachines()
    83  	if err != nil {
    84  		return results, err
    85  	}
    86  	machineTags := make([]names.Tag, len(machines))
    87  	for i, machine := range machines {
    88  		machineTags[i] = machine.Tag()
    89  	}
    90  
    91  	actionParams := a.createActionsParams(machineTags, run.Commands, run.Timeout)
    92  
    93  	return queueActions(a, actionParams)
    94  }
    95  
    96  func (a *ActionAPI) createActionsParams(actionReceiverTags []names.Tag, quotedCommands string, timeout time.Duration) params.Actions {
    97  
    98  	apiActionParams := params.Actions{Actions: []params.Action{}}
    99  
   100  	actionParams := map[string]interface{}{}
   101  	actionParams["command"] = quotedCommands
   102  	actionParams["timeout"] = timeout.Nanoseconds()
   103  
   104  	for _, tag := range actionReceiverTags {
   105  		apiActionParams.Actions = append(apiActionParams.Actions, params.Action{
   106  			Receiver:   tag.String(),
   107  			Name:       actions.JujuRunActionName,
   108  			Parameters: actionParams,
   109  		})
   110  	}
   111  
   112  	return apiActionParams
   113  }
   114  
   115  var queueActions = func(a *ActionAPI, args params.Actions) (results params.ActionResults, err error) {
   116  	return a.Enqueue(args)
   117  }