github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/uniter/leadership/resolver.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package leadership
     5  
     6  import (
     7  	"github.com/juju/loggo"
     8  	"gopkg.in/juju/charm.v6/hooks"
     9  
    10  	"github.com/juju/juju/apiserver/params"
    11  	"github.com/juju/juju/worker/uniter/hook"
    12  	"github.com/juju/juju/worker/uniter/operation"
    13  	"github.com/juju/juju/worker/uniter/remotestate"
    14  	"github.com/juju/juju/worker/uniter/resolver"
    15  )
    16  
    17  var logger = loggo.GetLogger("juju.worker.uniter.leadership")
    18  
    19  type leadershipResolver struct {
    20  }
    21  
    22  // NewResolver returns a new leadership resolver.
    23  func NewResolver() resolver.Resolver {
    24  	return &leadershipResolver{}
    25  }
    26  
    27  // NextOp is defined on the Resolver interface.
    28  func (l *leadershipResolver) NextOp(
    29  	localState resolver.LocalState,
    30  	remoteState remotestate.Snapshot,
    31  	opFactory operation.Factory,
    32  ) (operation.Operation, error) {
    33  
    34  	// TODO(wallyworld) - maybe this can occur before install
    35  	if !localState.Installed {
    36  		return nil, resolver.ErrNoOperation
    37  	}
    38  
    39  	// Check for any leadership change, and enact it if possible.
    40  	logger.Tracef("checking leadership status")
    41  
    42  	// If we've already accepted leadership, we don't need to do it again.
    43  	canAcceptLeader := !localState.Leader
    44  	if remoteState.Life == params.Dying {
    45  		canAcceptLeader = false
    46  	} else {
    47  		// If we're in an unexpected mode (eg pending hook) we shouldn't try either.
    48  		if localState.Kind != operation.Continue {
    49  			canAcceptLeader = false
    50  		}
    51  	}
    52  
    53  	switch {
    54  	case remoteState.Leader && canAcceptLeader:
    55  		return opFactory.NewAcceptLeadership()
    56  
    57  	// If we're the leader but should not be any longer, or
    58  	// if the unit is dying, we should resign leadership.
    59  	case localState.Leader && (!remoteState.Leader || remoteState.Life == params.Dying):
    60  		return opFactory.NewResignLeadership()
    61  	}
    62  
    63  	if localState.Kind == operation.Continue {
    64  		// We want to run the leader settings hook if we're
    65  		// not the leader and the settings have changed.
    66  		if !localState.Leader && localState.LeaderSettingsVersion != remoteState.LeaderSettingsVersion {
    67  			return opFactory.NewRunHook(hook.Info{Kind: hooks.LeaderSettingsChanged})
    68  		}
    69  	}
    70  
    71  	logger.Tracef("leadership status is up-to-date")
    72  	return nil, resolver.ErrNoOperation
    73  }