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  }