github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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/core/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 application and unit. Only leaders of a given application may perform
    37  // this operation.
    38  func (lsa *LeadershipSettingsAccessor) Merge(appId, unitId 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  	results, err := lsa.bulkMerge(lsa.prepareMerge(appId, unitId, settings))
    44  	if err != nil {
    45  		return errors.Annotatef(err, "failed to call leadership api")
    46  	}
    47  	if count := len(results.Results); count != 1 {
    48  		return errors.Errorf("expected 1 result from leadership api, got %d", count)
    49  	}
    50  	if results.Results[0].Error != nil {
    51  		return errors.Annotatef(results.Results[0].Error, "failed to merge leadership settings")
    52  	}
    53  	return nil
    54  }
    55  
    56  // Read retrieves the leadership settings for the given application
    57  // ID. Anyone may perform this operation.
    58  func (lsa *LeadershipSettingsAccessor) Read(appId string) (map[string]string, error) {
    59  
    60  	if err := lsa.checkAPIVersion("Read"); err != nil {
    61  		return nil, errors.Annotatef(err, "cannot access leadership api")
    62  	}
    63  
    64  	results, err := lsa.bulkRead(lsa.prepareRead(appId))
    65  	if err != nil {
    66  		return nil, errors.Annotatef(err, "failed to call leadership api")
    67  	}
    68  	if count := len(results.Results); count != 1 {
    69  		return nil, errors.Errorf("expected 1 result from leadership api, got %d", count)
    70  	}
    71  	if results.Results[0].Error != nil {
    72  		return nil, errors.Annotatef(results.Results[0].Error, "failed to read leadership settings")
    73  	}
    74  	return results.Results[0].Settings, nil
    75  }
    76  
    77  // WatchLeadershipSettings returns a watcher which can be used to wait
    78  // for leadership settings changes to be made for a given application ID.
    79  func (lsa *LeadershipSettingsAccessor) WatchLeadershipSettings(appId string) (watcher.NotifyWatcher, error) {
    80  
    81  	if err := lsa.checkAPIVersion("WatchLeadershipSettings"); err != nil {
    82  		return nil, errors.Annotatef(err, "cannot access leadership api")
    83  	}
    84  	var results params.NotifyWatchResults
    85  	if err := lsa.facadeCaller(
    86  		"WatchLeadershipSettings",
    87  		params.Entities{[]params.Entity{{names.NewApplicationTag(appId).String()}}},
    88  		&results,
    89  	); err != nil {
    90  		return nil, errors.Annotate(err, "failed to call leadership api")
    91  	}
    92  	if count := len(results.Results); count != 1 {
    93  		return nil, errors.Errorf("expected 1 result from leadership api, got %d", count)
    94  	}
    95  	if results.Results[0].Error != nil {
    96  		return nil, errors.Annotatef(results.Results[0].Error, "failed to watch leadership settings")
    97  	}
    98  	return lsa.newNotifyWatcher(results.Results[0]), nil
    99  }
   100  
   101  //
   102  // Prepare functions for building bulk-calls.
   103  //
   104  
   105  func (lsa *LeadershipSettingsAccessor) prepareMerge(appId, unitId string, settings map[string]string) params.MergeLeadershipSettingsParam {
   106  	return params.MergeLeadershipSettingsParam{
   107  		ApplicationTag: names.NewApplicationTag(appId).String(),
   108  		UnitTag:        names.NewUnitTag(unitId).String(),
   109  		Settings:       settings,
   110  	}
   111  }
   112  
   113  func (lsa *LeadershipSettingsAccessor) prepareRead(appId string) params.Entity {
   114  	return params.Entity{Tag: names.NewApplicationTag(appId).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 &params.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 &params.GetLeadershipSettingsBulkResults{}, nil
   137  	}
   138  
   139  	bulkArgs := params.Entities{Entities: args}
   140  	var results params.GetLeadershipSettingsBulkResults
   141  	return &results, lsa.facadeCaller("Read", bulkArgs, &results)
   142  }