github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/leadership.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package apiserver 5 6 import ( 7 "time" 8 9 "github.com/juju/errors" 10 11 "github.com/juju/juju/core/leadership" 12 "github.com/juju/juju/core/lease" 13 ) 14 15 // leadershipChecker implements leadership.Checker by wrapping a lease.Checker. 16 type leadershipChecker struct { 17 checker lease.Checker 18 } 19 20 // LeadershipCheck is part of the leadership.Checker interface. 21 func (m leadershipChecker) LeadershipCheck(applicationName, unitName string) leadership.Token { 22 token := m.checker.Token(applicationName, unitName) 23 return leadershipToken{ 24 applicationName: applicationName, 25 unitName: unitName, 26 token: token, 27 } 28 } 29 30 // leadershipToken implements leadership.Token by wrapping a lease.Token. 31 type leadershipToken struct { 32 applicationName string 33 unitName string 34 token lease.Token 35 } 36 37 // Check is part of the leadership.Token interface. 38 func (t leadershipToken) Check() error { 39 err := t.token.Check() 40 if errors.Cause(err) == lease.ErrNotHeld { 41 return leadership.NewNotLeaderError(t.unitName, t.applicationName) 42 } 43 return errors.Trace(err) 44 } 45 46 // leadershipClaimer implements leadership.Claimer by wrapping a lease.Claimer. 47 type leadershipClaimer struct { 48 claimer lease.Claimer 49 } 50 51 // ClaimLeadership is part of the leadership.Claimer interface. 52 func (m leadershipClaimer) ClaimLeadership(applicationName, unitName string, duration time.Duration) error { 53 err := m.claimer.Claim(applicationName, unitName, duration) 54 if errors.Cause(err) == lease.ErrClaimDenied { 55 return leadership.ErrClaimDenied 56 } 57 return errors.Trace(err) 58 } 59 60 // BlockUntilLeadershipReleased is part of the leadership.Claimer interface. 61 func (m leadershipClaimer) BlockUntilLeadershipReleased(applicationName string, cancel <-chan struct{}) error { 62 err := m.claimer.WaitUntilExpired(applicationName, cancel) 63 if errors.Cause(err) == lease.ErrWaitCancelled { 64 return leadership.ErrBlockCancelled 65 } 66 return errors.Trace(err) 67 } 68 69 // leadershipRevoker implements leadership.Revoker by wrapping a lease.Revoker. 70 type leadershipRevoker struct { 71 claimer lease.Revoker 72 } 73 74 // RevokeLeadership is part of the leadership.Claimer interface. 75 func (m leadershipRevoker) RevokeLeadership(applicationName, unitName string) error { 76 err := m.claimer.Revoke(applicationName, unitName) 77 if errors.Cause(err) == lease.ErrNotHeld { 78 return leadership.ErrClaimNotHeld 79 } 80 return errors.Trace(err) 81 } 82 83 // leadershipPinner implements leadership.Pinner by wrapping a lease.Pinner. 84 type leadershipPinner struct { 85 pinner lease.Pinner 86 } 87 88 // PinLeadership (leadership.Pinner) pins the lease 89 // for the input application and entity. 90 func (m leadershipPinner) PinLeadership(applicationName string, entity string) error { 91 return errors.Trace(m.pinner.Pin(applicationName, entity)) 92 } 93 94 // UnpinLeadership (leadership.Pinner) unpins the lease 95 // for the input application and entity. 96 func (m leadershipPinner) UnpinLeadership(applicationName string, entity string) error { 97 return errors.Trace(m.pinner.Unpin(applicationName, entity)) 98 } 99 100 // PinnedLeadership (leadership.Pinner) returns applications for which 101 // leadership is pinned, along with the entities requiring the 102 // pinned behaviour. 103 func (m leadershipPinner) PinnedLeadership() (map[string][]string, error) { 104 pinned, err := m.pinner.Pinned() 105 return pinned, errors.Trace(err) 106 } 107 108 // leadershipReader implements leadership.Reader by wrapping a lease.Reader. 109 type leadershipReader struct { 110 reader lease.Reader 111 } 112 113 // Leaders (leadership.Reader) returns all application leaders in the 114 // current model. 115 func (r leadershipReader) Leaders() (map[string]string, error) { 116 leaders, err := r.reader.Leases() 117 return leaders, errors.Trace(err) 118 }