github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/agent/uniter/leadership.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package uniter 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names/v5" 9 10 "github.com/juju/juju/core/watcher" 11 "github.com/juju/juju/rpc/params" 12 ) 13 14 // NewLeadershipSettingsAccessor returns a new LeadershipSettingsAccessor. 15 func NewLeadershipSettingsAccessor( 16 caller FacadeCallFn, 17 newWatcher NewNotifyWatcherFn, 18 ) *LeadershipSettingsAccessor { 19 return &LeadershipSettingsAccessor{caller, newWatcher} 20 } 21 22 type FacadeCallFn func(request string, params, response interface{}) error 23 type NewNotifyWatcherFn func(params.NotifyWatchResult) watcher.NotifyWatcher 24 25 // LeadershipSettingsAccessor provides a type that can make RPC calls 26 // to a service which can read, write, and watch leadership settings. 27 type LeadershipSettingsAccessor struct { 28 facadeCaller FacadeCallFn 29 newNotifyWatcher NewNotifyWatcherFn 30 } 31 32 // Merge merges the provided settings into the leadership settings for 33 // the given application and unit. Only leaders of a given application may perform 34 // this operation. 35 func (lsa *LeadershipSettingsAccessor) Merge(appId, unitId string, settings map[string]string) error { 36 results, err := lsa.bulkMerge(lsa.prepareMerge(appId, unitId, settings)) 37 if err != nil { 38 return errors.Annotatef(err, "failed to call leadership api") 39 } 40 if count := len(results.Results); count != 1 { 41 return errors.Errorf("expected 1 result from leadership api, got %d", count) 42 } 43 if results.Results[0].Error != nil { 44 return errors.Annotatef(results.Results[0].Error, "failed to merge leadership settings") 45 } 46 return nil 47 } 48 49 // Read retrieves the leadership settings for the given application 50 // ID. Anyone may perform this operation. 51 func (lsa *LeadershipSettingsAccessor) Read(appId string) (map[string]string, error) { 52 results, err := lsa.bulkRead(lsa.prepareRead(appId)) 53 if err != nil { 54 return nil, errors.Annotatef(err, "failed to call leadership api") 55 } 56 if count := len(results.Results); count != 1 { 57 return nil, errors.Errorf("expected 1 result from leadership api, got %d", count) 58 } 59 if results.Results[0].Error != nil { 60 return nil, errors.Annotatef(results.Results[0].Error, "failed to read leadership settings") 61 } 62 return results.Results[0].Settings, nil 63 } 64 65 // WatchLeadershipSettings returns a watcher which can be used to wait 66 // for leadership settings changes to be made for a given application ID. 67 func (lsa *LeadershipSettingsAccessor) WatchLeadershipSettings(appId string) (watcher.NotifyWatcher, error) { 68 var results params.NotifyWatchResults 69 if err := lsa.facadeCaller( 70 "WatchLeadershipSettings", 71 params.Entities{[]params.Entity{{names.NewApplicationTag(appId).String()}}}, 72 &results, 73 ); err != nil { 74 return nil, errors.Annotate(err, "failed to call leadership api") 75 } 76 if count := len(results.Results); count != 1 { 77 return nil, errors.Errorf("expected 1 result from leadership api, got %d", count) 78 } 79 if results.Results[0].Error != nil { 80 return nil, errors.Annotatef(results.Results[0].Error, "failed to watch leadership settings") 81 } 82 return lsa.newNotifyWatcher(results.Results[0]), nil 83 } 84 85 // 86 // Prepare functions for building bulk-calls. 87 // 88 89 func (lsa *LeadershipSettingsAccessor) prepareMerge(appId, unitId string, settings map[string]string) params.MergeLeadershipSettingsParam { 90 return params.MergeLeadershipSettingsParam{ 91 ApplicationTag: names.NewApplicationTag(appId).String(), 92 UnitTag: names.NewUnitTag(unitId).String(), 93 Settings: settings, 94 } 95 } 96 97 func (lsa *LeadershipSettingsAccessor) prepareRead(appId string) params.Entity { 98 return params.Entity{Tag: names.NewApplicationTag(appId).String()} 99 } 100 101 // 102 // Bulk calls. 103 // 104 105 func (lsa *LeadershipSettingsAccessor) bulkMerge(args ...params.MergeLeadershipSettingsParam) (*params.ErrorResults, error) { 106 // Don't make the jump over the network if we don't have to. 107 if len(args) <= 0 { 108 return ¶ms.ErrorResults{}, nil 109 } 110 111 bulkArgs := params.MergeLeadershipSettingsBulkParams{Params: args} 112 var results params.ErrorResults 113 return &results, lsa.facadeCaller("Merge", bulkArgs, &results) 114 } 115 116 func (lsa *LeadershipSettingsAccessor) bulkRead(args ...params.Entity) (*params.GetLeadershipSettingsBulkResults, error) { 117 118 // Don't make the jump over the network if we don't have to. 119 if len(args) <= 0 { 120 return ¶ms.GetLeadershipSettingsBulkResults{}, nil 121 } 122 123 bulkArgs := params.Entities{Entities: args} 124 var results params.GetLeadershipSettingsBulkResults 125 return &results, lsa.facadeCaller("Read", bulkArgs, &results) 126 }