1
// Copyright 2015 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
7
"github.com/juju/errors"
8
"gopkg.in/juju/names.v2"
10
"github.com/juju/juju/apiserver/params"
11
"github.com/juju/juju/watcher"
14
// NewLeadershipSettingsAccessor returns a new LeadershipSettingsAccessor.
15
func NewLeadershipSettingsAccessor(
17
newWatcher NewNotifyWatcherFn,
18
checkApiVersion CheckApiVersionFn,
19
) *LeadershipSettingsAccessor {
20
return &LeadershipSettingsAccessor{caller, newWatcher, checkApiVersion}
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
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
35
// Merge merges the provided settings into the leadership settings for
36
// the given service ID. Only leaders of a given service may perform
38
func (lsa *LeadershipSettingsAccessor) Merge(serviceId string, settings map[string]string) error {
40
if err := lsa.checkApiVersion("Merge"); err != nil {
41
return errors.Annotatef(err, "cannot access leadership api")
44
results, err := lsa.bulkMerge(lsa.prepareMerge(serviceId, settings))
46
return errors.Annotatef(err, "failed to call leadership api")
48
if count := len(results.Results); count != 1 {
49
return errors.Errorf("expected 1 result from leadership api, got %d", count)
51
if results.Results[0].Error != nil {
52
return errors.Annotatef(results.Results[0].Error, "failed to merge leadership settings")
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) {
61
if err := lsa.checkApiVersion("Read"); err != nil {
62
return nil, errors.Annotatef(err, "cannot access leadership api")
65
results, err := lsa.bulkRead(lsa.prepareRead(serviceId))
67
return nil, errors.Annotatef(err, "failed to call leadership api")
69
if count := len(results.Results); count != 1 {
70
return nil, errors.Errorf("expected 1 result from leadership api, got %d", count)
72
if results.Results[0].Error != nil {
73
return nil, errors.Annotatef(results.Results[0].Error, "failed to read leadership settings")
75
return results.Results[0].Settings, nil
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) {
82
if err := lsa.checkApiVersion("WatchLeadershipSettings"); err != nil {
83
return nil, errors.Annotatef(err, "cannot access leadership api")
85
var results params.NotifyWatchResults
86
if err := lsa.facadeCaller(
87
"WatchLeadershipSettings",
88
params.Entities{[]params.Entity{{names.NewApplicationTag(serviceId).String()}}},
91
return nil, errors.Annotate(err, "failed to call leadership api")
93
if count := len(results.Results); count != 1 {
94
return nil, errors.Errorf("expected 1 result from leadership api, got %d", count)
96
if results.Results[0].Error != nil {
97
return nil, errors.Annotatef(results.Results[0].Error, "failed to watch leadership settings")
99
return lsa.newNotifyWatcher(results.Results[0]), nil
103
// Prepare functions for building bulk-calls.
106
func (lsa *LeadershipSettingsAccessor) prepareMerge(serviceId string, settings map[string]string) params.MergeLeadershipSettingsParam {
107
return params.MergeLeadershipSettingsParam{
108
ApplicationTag: names.NewApplicationTag(serviceId).String(),
113
func (lsa *LeadershipSettingsAccessor) prepareRead(serviceId string) params.Entity {
114
return params.Entity{Tag: names.NewApplicationTag(serviceId).String()}
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.
124
return ¶ms.ErrorResults{}, nil
127
bulkArgs := params.MergeLeadershipSettingsBulkParams{Params: args}
128
var results params.ErrorResults
129
return &results, lsa.facadeCaller("Merge", bulkArgs, &results)
132
func (lsa *LeadershipSettingsAccessor) bulkRead(args ...params.Entity) (*params.GetLeadershipSettingsBulkResults, error) {
134
// Don't make the jump over the network if we don't have to.
136
return ¶ms.GetLeadershipSettingsBulkResults{}, nil
139
bulkArgs := params.Entities{Entities: args}
140
var results params.GetLeadershipSettingsBulkResults
141
return &results, lsa.facadeCaller("Read", bulkArgs, &results)