github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/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 // 21 // TODO(axw) 2015-10-27 #1510333 22 // Use the same method as in the runcommands resolver 23 // for updating the remote state snapshot when an 24 // action is completed. 25 func NewResolver() resolver.Resolver { 26 return &actionsResolver{} 27 } 28 29 func nextAction(pendingActions []string, completedActions map[string]struct{}) (string, error) { 30 for _, action := range pendingActions { 31 if _, ok := completedActions[action]; !ok { 32 return action, nil 33 } 34 } 35 return "", resolver.ErrNoOperation 36 } 37 38 // NextOp implements the resolver.Resolver interface. 39 func (r *actionsResolver) NextOp( 40 localState resolver.LocalState, 41 remoteState remotestate.Snapshot, 42 opFactory operation.Factory, 43 ) (operation.Operation, error) { 44 nextAction, err := nextAction(remoteState.Actions, localState.CompletedActions) 45 if err != nil { 46 return nil, err 47 } 48 switch localState.Kind { 49 case operation.RunHook: 50 // We can still run actions if the unit is in a hook error state. 51 if localState.Step == operation.Pending { 52 return opFactory.NewAction(nextAction) 53 } 54 case operation.RunAction: 55 // TODO(fwereade): we *should* handle interrupted actions, and make sure 56 // they're marked as failed, but that's not for now. 57 if localState.Hook != nil { 58 logger.Infof("found incomplete action %q; ignoring", localState.ActionId) 59 logger.Infof("recommitting prior %q hook", localState.Hook.Kind) 60 return opFactory.NewSkipHook(*localState.Hook) 61 } else { 62 logger.Infof("%q hook is nil", operation.RunAction) 63 } 64 case operation.Continue: 65 return opFactory.NewAction(nextAction) 66 } 67 return nil, resolver.ErrNoOperation 68 }