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 }