github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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 if localState.Hook != nil { 56 logger.Infof("found incomplete action %q; ignoring", localState.ActionId) 57 logger.Infof("recommitting prior %q hook", localState.Hook.Kind) 58 return opFactory.NewSkipHook(*localState.Hook) 59 } else { 60 logger.Infof("%q hook is nil", operation.RunAction) 61 return opFactory.NewFailAction(*localState.ActionId) 62 } 63 case operation.Continue: 64 return opFactory.NewAction(nextAction) 65 } 66 return nil, resolver.ErrNoOperation 67 }