github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/core/lease/store.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package lease
     5  
     6  import (
     7  	"context"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/juju/errors"
    12  )
    13  
    14  // Store manipulates leases directly, and is most likely to be seen set on a
    15  // worker/lease.ManagerConfig struct (and used by the Manager). Implementations
    16  // of Store are not expected to be goroutine-safe.
    17  type Store interface {
    18  	// ClaimLease records the supplied holder's claim to the supplied lease. If
    19  	// it succeeds, the claim is guaranteed until at least the supplied duration
    20  	// after the call to ClaimLease was initiated. If it returns ErrInvalid,
    21  	// check Leases() for updated state.
    22  	ClaimLease(ctx context.Context, lease Key, request Request) error
    23  
    24  	// ExtendLease records the supplied holder's continued claim to the supplied
    25  	// lease, if necessary. If it succeeds, the claim is guaranteed until at
    26  	// least the supplied duration after the call to ExtendLease was initiated.
    27  	// If it returns ErrInvalid, check Leases() for updated state.
    28  	ExtendLease(ctx context.Context, lease Key, request Request) error
    29  
    30  	// RevokeLease records the vacation of the supplied lease. It will fail if
    31  	// the lease is not held by the holder.
    32  	RevokeLease(ctx context.Context, lease Key, holder string) error
    33  
    34  	// Leases returns a recent snapshot of lease state. Expiry times are
    35  	// expressed according to the Clock the store was configured with.
    36  	// Supplying any lease keys will filter the return for those requested.
    37  	Leases(ctx context.Context, keys ...Key) (map[Key]Info, error)
    38  
    39  	// LeaseGroup returns a snapshot of all of the leases for a
    40  	// particular namespace/model combination. This is useful for
    41  	// reporting holder information for a model, and can often be
    42  	// implemented more efficiently than getting all leases when there
    43  	// are many models.
    44  	LeaseGroup(ctx context.Context, namespace, modelUUID string) (map[Key]Info, error)
    45  
    46  	// PinLease ensures that the current holder of the lease for the input key
    47  	// will not lose the lease to expiry.
    48  	// If there is no current holder of the lease, the next claimant will be
    49  	// the recipient of the pin behaviour.
    50  	// The input entity denotes the party responsible for the
    51  	// pinning operation.
    52  	PinLease(ctx context.Context, lease Key, entity string) error
    53  
    54  	// UnpinLease reverses a Pin operation for the same key and entity.
    55  	// Normal expiry behaviour is restored when no entities remain with
    56  	// pins for the application.
    57  	UnpinLease(ctx context.Context, lease Key, entity string) error
    58  
    59  	// Pinned returns a snapshot of pinned leases.
    60  	// The return consists of each pinned lease and the collection of entities
    61  	// requiring its pinned behaviour.
    62  	Pinned(ctx context.Context) (map[Key][]string, error)
    63  }
    64  
    65  // Key fully identifies a lease, including the namespace and
    66  // model it belongs to.
    67  type Key struct {
    68  	Namespace string
    69  	ModelUUID string
    70  	Lease     string
    71  }
    72  
    73  // Info holds substrate-independent information about a lease.
    74  type Info struct {
    75  	// Holder is the name of the current leaseholder.
    76  	Holder string
    77  
    78  	// Expiry is the latest time at which it's possible the lease might still
    79  	// be valid. Attempting to expire the lease before this time will fail.
    80  	Expiry time.Time
    81  }
    82  
    83  // Request describes a lease request.
    84  type Request struct {
    85  
    86  	// Holder identifies the lease holder.
    87  	Holder string
    88  
    89  	// Duration specifies the time for which the lease is required.
    90  	Duration time.Duration
    91  }
    92  
    93  // Validate returns an error if any fields are invalid or inconsistent.
    94  func (request Request) Validate() error {
    95  	if err := ValidateString(request.Holder); err != nil {
    96  		return errors.Annotatef(err, "invalid holder")
    97  	}
    98  	if request.Duration <= 0 {
    99  		return errors.Errorf("invalid duration")
   100  	}
   101  	return nil
   102  }
   103  
   104  // ValidateString returns an error if the string is empty, or if it contains
   105  // whitespace, or if it contains any character in `.#$`. Store implementations
   106  // are expected to always reject invalid strings, and never to produce them.
   107  func ValidateString(s string) error {
   108  	if s == "" {
   109  		return errors.New("string is empty")
   110  	}
   111  	if strings.ContainsAny(s, ".$# \t\r\n") {
   112  		return errors.New("string contains forbidden characters")
   113  	}
   114  	return nil
   115  }