github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/worker/uniter/operation/leader_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package operation_test
     5  
     6  import (
     7  	"github.com/juju/charm/v12/hooks"
     8  	"github.com/juju/loggo"
     9  	"github.com/juju/testing"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  
    13  	"github.com/juju/juju/worker/uniter/hook"
    14  	"github.com/juju/juju/worker/uniter/operation"
    15  )
    16  
    17  type LeaderSuite struct {
    18  	testing.IsolationSuite
    19  }
    20  
    21  var _ = gc.Suite(&LeaderSuite{})
    22  
    23  func (s *LeaderSuite) newFactory() operation.Factory {
    24  	return operation.NewFactory(operation.FactoryParams{
    25  		Logger: loggo.GetLogger("test"),
    26  	})
    27  }
    28  
    29  func (s *LeaderSuite) TestAcceptLeadership_Prepare_BadState(c *gc.C) {
    30  	factory := s.newFactory()
    31  	op, err := factory.NewAcceptLeadership()
    32  	c.Assert(err, jc.ErrorIsNil)
    33  
    34  	newState, err := op.Prepare(operation.State{})
    35  	c.Check(newState, gc.IsNil)
    36  	// accept is only valid in Continue mode, when we're sure nothing is queued
    37  	// or in progress.
    38  	c.Check(err, gc.Equals, operation.ErrCannotAcceptLeadership)
    39  }
    40  
    41  func (s *LeaderSuite) TestAcceptLeadership_Prepare_NotLeader(c *gc.C) {
    42  	factory := s.newFactory()
    43  	op, err := factory.NewAcceptLeadership()
    44  	c.Assert(err, jc.ErrorIsNil)
    45  
    46  	newState, err := op.Prepare(operation.State{Kind: operation.Continue})
    47  	c.Check(newState, gc.IsNil)
    48  	// *execute* is currently just a no-op -- all the meat happens in commit.
    49  	c.Check(err, gc.Equals, operation.ErrSkipExecute)
    50  }
    51  
    52  func (s *LeaderSuite) TestAcceptLeadership_Prepare_AlreadyLeader(c *gc.C) {
    53  	factory := s.newFactory()
    54  	op, err := factory.NewAcceptLeadership()
    55  	c.Assert(err, jc.ErrorIsNil)
    56  
    57  	newState, err := op.Prepare(operation.State{
    58  		Kind:   operation.Continue,
    59  		Leader: true,
    60  	})
    61  	c.Check(newState, gc.IsNil)
    62  	// *execute* is currently just a no-op -- all the meat happens in commit.
    63  	c.Check(err, gc.Equals, operation.ErrSkipExecute)
    64  }
    65  
    66  func (s *LeaderSuite) TestAcceptLeadership_Commit_NotLeader_BlankSlate(c *gc.C) {
    67  	factory := s.newFactory()
    68  	op, err := factory.NewAcceptLeadership()
    69  	c.Assert(err, jc.ErrorIsNil)
    70  	_, err = op.Prepare(operation.State{Kind: operation.Continue})
    71  	c.Check(err, gc.Equals, operation.ErrSkipExecute)
    72  
    73  	newState, err := op.Commit(operation.State{
    74  		Kind: operation.Continue,
    75  	})
    76  	c.Check(err, jc.ErrorIsNil)
    77  	c.Check(newState, gc.DeepEquals, &operation.State{
    78  		Kind:   operation.RunHook,
    79  		Step:   operation.Queued,
    80  		Hook:   &hook.Info{Kind: hooks.LeaderElected},
    81  		Leader: true,
    82  	})
    83  }
    84  
    85  func (s *LeaderSuite) TestAcceptLeadership_Commit_NotLeader_Preserve(c *gc.C) {
    86  	factory := s.newFactory()
    87  	op, err := factory.NewAcceptLeadership()
    88  	c.Assert(err, jc.ErrorIsNil)
    89  	_, err = op.Prepare(operation.State{Kind: operation.Continue})
    90  	c.Check(err, gc.Equals, operation.ErrSkipExecute)
    91  
    92  	newState, err := op.Commit(operation.State{
    93  		Kind:    operation.Continue,
    94  		Started: true,
    95  		Hook:    &hook.Info{Kind: hooks.Install},
    96  	})
    97  	c.Check(err, jc.ErrorIsNil)
    98  	c.Check(newState, gc.DeepEquals, &operation.State{
    99  		Kind:    operation.RunHook,
   100  		Step:    operation.Queued,
   101  		Hook:    &hook.Info{Kind: hooks.LeaderElected},
   102  		Leader:  true,
   103  		Started: true,
   104  	})
   105  }
   106  
   107  func (s *LeaderSuite) TestAcceptLeadership_Commit_AlreadyLeader(c *gc.C) {
   108  	factory := s.newFactory()
   109  	op, err := factory.NewAcceptLeadership()
   110  	c.Assert(err, jc.ErrorIsNil)
   111  	_, err = op.Prepare(operation.State{Kind: operation.Continue})
   112  	c.Check(err, gc.Equals, operation.ErrSkipExecute)
   113  
   114  	newState, err := op.Commit(operation.State{
   115  		Kind:   operation.Continue,
   116  		Leader: true,
   117  	})
   118  	c.Check(newState, gc.IsNil)
   119  	c.Check(err, jc.ErrorIsNil)
   120  }
   121  
   122  func (s *LeaderSuite) TestAcceptLeadership_DoesNotNeedGlobalMachineLock(c *gc.C) {
   123  	factory := s.newFactory()
   124  	op, err := factory.NewAcceptLeadership()
   125  	c.Assert(err, jc.ErrorIsNil)
   126  	c.Assert(op.NeedsGlobalMachineLock(), jc.IsFalse)
   127  }
   128  
   129  func (s *LeaderSuite) TestResignLeadership_Prepare_Leader(c *gc.C) {
   130  	factory := s.newFactory()
   131  	op, err := factory.NewResignLeadership()
   132  	c.Assert(err, jc.ErrorIsNil)
   133  
   134  	newState, err := op.Prepare(operation.State{Leader: true})
   135  	c.Check(newState, gc.IsNil)
   136  	c.Check(err, jc.ErrorIsNil)
   137  }
   138  
   139  func (s *LeaderSuite) TestResignLeadership_Prepare_NotLeader(c *gc.C) {
   140  	factory := s.newFactory()
   141  	op, err := factory.NewResignLeadership()
   142  	c.Assert(err, jc.ErrorIsNil)
   143  
   144  	newState, err := op.Prepare(operation.State{})
   145  	c.Check(newState, gc.IsNil)
   146  	c.Check(err, gc.Equals, operation.ErrSkipExecute)
   147  }
   148  
   149  func (s *LeaderSuite) TestResignLeadership_Execute(c *gc.C) {
   150  	factory := s.newFactory()
   151  	op, err := factory.NewResignLeadership()
   152  	c.Assert(err, jc.ErrorIsNil)
   153  
   154  	_, err = op.Prepare(operation.State{Leader: true})
   155  	c.Check(err, jc.ErrorIsNil)
   156  
   157  	// Execute is a no-op (which logs that we should run leader-deposed)
   158  	newState, err := op.Execute(operation.State{})
   159  	c.Check(newState, gc.IsNil)
   160  	c.Check(err, jc.ErrorIsNil)
   161  }
   162  
   163  func (s *LeaderSuite) TestResignLeadership_Commit_ClearLeader(c *gc.C) {
   164  	factory := s.newFactory()
   165  	op, err := factory.NewResignLeadership()
   166  	c.Assert(err, jc.ErrorIsNil)
   167  
   168  	newState, err := op.Commit(operation.State{Leader: true})
   169  	c.Check(newState, gc.DeepEquals, &operation.State{})
   170  	c.Check(err, jc.ErrorIsNil)
   171  }
   172  
   173  func (s *LeaderSuite) TestResignLeadership_Commit_PreserveOthers(c *gc.C) {
   174  	factory := s.newFactory()
   175  	op, err := factory.NewResignLeadership()
   176  	c.Assert(err, jc.ErrorIsNil)
   177  
   178  	newState, err := op.Commit(overwriteState)
   179  	c.Check(newState, gc.DeepEquals, &overwriteState)
   180  	c.Check(err, jc.ErrorIsNil)
   181  }
   182  
   183  func (s *LeaderSuite) TestResignLeadership_Commit_All(c *gc.C) {
   184  	factory := s.newFactory()
   185  	op, err := factory.NewResignLeadership()
   186  	c.Assert(err, jc.ErrorIsNil)
   187  
   188  	leaderState := overwriteState
   189  	leaderState.Leader = true
   190  	newState, err := op.Commit(leaderState)
   191  	c.Check(newState, gc.DeepEquals, &overwriteState)
   192  	c.Check(err, jc.ErrorIsNil)
   193  }
   194  
   195  func (s *LeaderSuite) TestResignLeadership_DoesNotNeedGlobalMachineLock(c *gc.C) {
   196  	factory := s.newFactory()
   197  	op, err := factory.NewResignLeadership()
   198  	c.Assert(err, jc.ErrorIsNil)
   199  	c.Assert(op.NeedsGlobalMachineLock(), jc.IsFalse)
   200  }