github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/api/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 "gopkg.in/juju/names.v2" 9 10 "github.com/juju/juju/apiserver/params" 11 "github.com/juju/juju/watcher" 12 ) 13 14 // NewLeadershipSettingsAccessor returns a new LeadershipSettingsAccessor. 15 func NewLeadershipSettingsAccessor( 16 caller FacadeCallFn, 17 newWatcher NewNotifyWatcherFn, 18 checkAPIVersion CheckAPIVersionFn, 19 ) *LeadershipSettingsAccessor { 20 return &LeadershipSettingsAccessor{caller, newWatcher, checkAPIVersion} 21 } 22 23 type FacadeCallFn func(request string, params, response interface{}) error 24 type NewNotifyWatcherFn func(params.NotifyWatchResult) watcher.NotifyWatcher 25 type CheckAPIVersionFn func(functionName string) error 26 27 // LeadershipSettingsAccessor provides a type that can make RPC calls 28 // to a service which can read, write, and watch leadership settings. 29 type LeadershipSettingsAccessor struct { 30 facadeCaller FacadeCallFn 31 newNotifyWatcher NewNotifyWatcherFn 32 checkAPIVersion CheckAPIVersionFn 33 } 34 35 // Merge merges the provided settings into the leadership settings for 36 // the given service ID. Only leaders of a given service may perform 37 // this operation. 38 func (lsa *LeadershipSettingsAccessor) Merge(serviceId string, settings map[string]string) error { 39 40 if err := lsa.checkAPIVersion("Merge"); err != nil { 41 return errors.Annotatef(err, "cannot access leadership api") 42 } 43 44 results, err := lsa.bulkMerge(lsa.prepareMerge(serviceId, settings)) 45 if err != nil { 46 return errors.Annotatef(err, "failed to call leadership api") 47 } 48 if count := len(results.Results); count != 1 { 49 return errors.Errorf("expected 1 result from leadership api, got %d", count) 50 } 51 if results.Results[0].Error != nil { 52 return errors.Annotatef(results.Results[0].Error, "failed to merge leadership settings") 53 } 54 return nil 55 } 56 57 // Read retrieves the leadership settings for the given service 58 // ID. Anyone may perform this operation. 59 func (lsa *LeadershipSettingsAccessor) Read(serviceId string) (map[string]string, error) { 60 61 if err := lsa.checkAPIVersion("Read"); err != nil { 62 return nil, errors.Annotatef(err, "cannot access leadership api") 63 } 64 65 results, err := lsa.bulkRead(lsa.prepareRead(serviceId)) 66 if err != nil { 67 return nil, errors.Annotatef(err, "failed to call leadership api") 68 } 69 if count := len(results.Results); count != 1 { 70 return nil, errors.Errorf("expected 1 result from leadership api, got %d", count) 71 } 72 if results.Results[0].Error != nil { 73 return nil, errors.Annotatef(results.Results[0].Error, "failed to read leadership settings") 74 } 75 return results.Results[0].Settings, nil 76 } 77 78 // WatchLeadershipSettings returns a watcher which can be used to wait 79 // for leadership settings changes to be made for a given service ID. 80 func (lsa *LeadershipSettingsAccessor) WatchLeadershipSettings(serviceId string) (watcher.NotifyWatcher, error) { 81 82 if err := lsa.checkAPIVersion("WatchLeadershipSettings"); err != nil { 83 return nil, errors.Annotatef(err, "cannot access leadership api") 84 } 85 var results params.NotifyWatchResults 86 if err := lsa.facadeCaller( 87 "WatchLeadershipSettings", 88 params.Entities{[]params.Entity{{names.NewApplicationTag(serviceId).String()}}}, 89 &results, 90 ); err != nil { 91 return nil, errors.Annotate(err, "failed to call leadership api") 92 } 93 if count := len(results.Results); count != 1 { 94 return nil, errors.Errorf("expected 1 result from leadership api, got %d", count) 95 } 96 if results.Results[0].Error != nil { 97 return nil, errors.Annotatef(results.Results[0].Error, "failed to watch leadership settings") 98 } 99 return lsa.newNotifyWatcher(results.Results[0]), nil 100 } 101 102 // 103 // Prepare functions for building bulk-calls. 104 // 105 106 func (lsa *LeadershipSettingsAccessor) prepareMerge(serviceId string, settings map[string]string) params.MergeLeadershipSettingsParam { 107 return params.MergeLeadershipSettingsParam{ 108 ApplicationTag: names.NewApplicationTag(serviceId).String(), 109 Settings: settings, 110 } 111 } 112 113 func (lsa *LeadershipSettingsAccessor) prepareRead(serviceId string) params.Entity { 114 return params.Entity{Tag: names.NewApplicationTag(serviceId).String()} 115 } 116 117 // 118 // Bulk calls. 119 // 120 121 func (lsa *LeadershipSettingsAccessor) bulkMerge(args ...params.MergeLeadershipSettingsParam) (*params.ErrorResults, error) { 122 // Don't make the jump over the network if we don't have to. 123 if len(args) <= 0 { 124 return ¶ms.ErrorResults{}, nil 125 } 126 127 bulkArgs := params.MergeLeadershipSettingsBulkParams{Params: args} 128 var results params.ErrorResults 129 return &results, lsa.facadeCaller("Merge", bulkArgs, &results) 130 } 131 132 func (lsa *LeadershipSettingsAccessor) bulkRead(args ...params.Entity) (*params.GetLeadershipSettingsBulkResults, error) { 133 134 // Don't make the jump over the network if we don't have to. 135 if len(args) <= 0 { 136 return ¶ms.GetLeadershipSettingsBulkResults{}, nil 137 } 138 139 bulkArgs := params.Entities{Entities: args} 140 var results params.GetLeadershipSettingsBulkResults 141 return &results, lsa.facadeCaller("Read", bulkArgs, &results) 142 }