github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/common/leadership.go (about)

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names/v5"
     9  
    10  	"github.com/juju/juju/api/base"
    11  	"github.com/juju/juju/rpc/params"
    12  )
    13  
    14  const leadershipFacade = "LeadershipPinning"
    15  
    16  // LeadershipPinningAPI provides common client-side API functions
    17  // for manipulating and querying application leadership pinning.
    18  type LeadershipPinningAPI struct {
    19  	facade base.FacadeCaller
    20  }
    21  
    22  // NewLeadershipPinningAPI creates and returns a new leadership API client.
    23  func NewLeadershipPinningAPI(caller base.APICaller) *LeadershipPinningAPI {
    24  	facadeCaller := base.NewFacadeCaller(
    25  		caller,
    26  		leadershipFacade,
    27  	)
    28  	return NewLeadershipPinningAPIFromFacade(facadeCaller)
    29  }
    30  
    31  // NewLeadershipPinningAPIFromFacade creates and returns a new leadership API
    32  // client based on the input client facade and facade caller.
    33  func NewLeadershipPinningAPIFromFacade(facade base.FacadeCaller) *LeadershipPinningAPI {
    34  	return &LeadershipPinningAPI{
    35  		facade: facade,
    36  	}
    37  }
    38  
    39  // PinnedLeadership returns a collection of application names for which
    40  // leadership is currently pinned, with the entities requiring each
    41  // application's pinned behaviour.
    42  func (a *LeadershipPinningAPI) PinnedLeadership() (map[string][]names.Tag, error) {
    43  	var callResult params.PinnedLeadershipResult
    44  	err := a.facade.FacadeCall("PinnedLeadership", nil, &callResult)
    45  	if err != nil {
    46  		return nil, errors.Trace(err)
    47  	}
    48  
    49  	if callResult.Error != nil {
    50  		return nil, errors.Trace(callResult.Error)
    51  	}
    52  
    53  	pinned := make(map[string][]names.Tag, len(callResult.Result))
    54  	for app, entities := range callResult.Result {
    55  		entityTags := make([]names.Tag, len(entities))
    56  		for i, e := range entities {
    57  			tag, err := names.ParseTag(e)
    58  			if err != nil {
    59  				return nil, errors.Trace(err)
    60  			}
    61  			entityTags[i] = tag
    62  		}
    63  
    64  		pinned[app] = entityTags
    65  	}
    66  	return pinned, nil
    67  }
    68  
    69  // PinMachineApplications pins leadership for applications represented by units
    70  // running on the local machine.
    71  // If the caller is not a machine agent, an error will be returned.
    72  // The return is a collection of applications determined to be running on the
    73  // machine, with the result of each individual pin operation.
    74  func (a *LeadershipPinningAPI) PinMachineApplications() (map[string]error, error) {
    75  	res, err := a.pinMachineAppsOps("PinMachineApplications")
    76  	return res, errors.Trace(err)
    77  }
    78  
    79  // UnpinMachineApplications pins leadership for applications represented by
    80  // units running on the local machine.
    81  // If the caller is not a machine agent, an error will be returned.
    82  // The return is a collection of applications determined to be running on the
    83  // machine, with the result of each individual unpin operation.
    84  func (a *LeadershipPinningAPI) UnpinMachineApplications() (map[string]error, error) {
    85  	res, err := a.pinMachineAppsOps("UnpinMachineApplications")
    86  	return res, errors.Trace(err)
    87  }
    88  
    89  // pinMachineAppsOps makes a facade call to the input method name and
    90  // transforms the response into map.
    91  func (a *LeadershipPinningAPI) pinMachineAppsOps(callName string) (map[string]error, error) {
    92  	var callResult params.PinApplicationsResults
    93  	err := a.facade.FacadeCall(callName, nil, &callResult)
    94  	if err != nil {
    95  		return nil, errors.Trace(err)
    96  	}
    97  
    98  	callResults := callResult.Results
    99  	result := make(map[string]error, len(callResults))
   100  	for _, res := range callResults {
   101  		var appErr error
   102  		if res.Error != nil {
   103  			appErr = res.Error
   104  		}
   105  		result[res.ApplicationName] = appErr
   106  	}
   107  	return result, nil
   108  }