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 }