github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/worker/uniter/actions/resolver.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package actions
     5  
     6  import (
     7  	"github.com/juju/loggo"
     8  
     9  	"github.com/juju/juju/worker/uniter/operation"
    10  	"github.com/juju/juju/worker/uniter/remotestate"
    11  	"github.com/juju/juju/worker/uniter/resolver"
    12  )
    13  
    14  var logger = loggo.GetLogger("juju.worker.uniter.actions")
    15  
    16  type actionsResolver struct{}
    17  
    18  // NewResolver returns a new resolver with determines which action related operation
    19  // should be run based on local and remote uniter states.
    20  func NewResolver() resolver.Resolver {
    21  	return &actionsResolver{}
    22  }
    23  
    24  func nextAction(pendingActions []string, completedActions map[string]struct{}) (string, error) {
    25  	for _, action := range pendingActions {
    26  		if _, ok := completedActions[action]; !ok {
    27  			return action, nil
    28  		}
    29  	}
    30  	return "", resolver.ErrNoOperation
    31  }
    32  
    33  // NextOp implements the resolver.Resolver interface.
    34  func (r *actionsResolver) NextOp(
    35  	localState resolver.LocalState,
    36  	remoteState remotestate.Snapshot,
    37  	opFactory operation.Factory,
    38  ) (operation.Operation, error) {
    39  	nextAction, err := nextAction(remoteState.Actions, localState.CompletedActions)
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	switch localState.Kind {
    44  	case operation.RunHook:
    45  		// We can still run actions if the unit is in a hook error state.
    46  		if localState.Step == operation.Pending {
    47  			return opFactory.NewAction(nextAction)
    48  		}
    49  	case operation.RunAction:
    50  		// TODO(fwereade): we *should* handle interrupted actions, and make sure
    51  		// they're marked as failed, but that's not for now.
    52  		if localState.Hook != nil {
    53  			logger.Infof("found incomplete action %q; ignoring", localState.ActionId)
    54  			logger.Infof("recommitting prior %q hook", localState.Hook.Kind)
    55  			return opFactory.NewSkipHook(*localState.Hook)
    56  		} else {
    57  			logger.Infof("%q hook is nil", operation.RunAction)
    58  		}
    59  	case operation.Continue:
    60  		return opFactory.NewAction(nextAction)
    61  	}
    62  	return nil, resolver.ErrNoOperation
    63  }