github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/common/leadership_test.go (about)

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package common_test
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names/v5"
     9  	jc "github.com/juju/testing/checkers"
    10  	"github.com/juju/utils/v3"
    11  	"go.uber.org/mock/gomock"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/apiserver/common"
    15  	commonmocks "github.com/juju/juju/apiserver/common/mocks"
    16  	apiservererrors "github.com/juju/juju/apiserver/errors"
    17  	apiservertesting "github.com/juju/juju/apiserver/testing"
    18  	"github.com/juju/juju/core/leadership/mocks"
    19  	"github.com/juju/juju/rpc/params"
    20  	coretesting "github.com/juju/juju/testing"
    21  )
    22  
    23  type LeadershipSuite struct {
    24  	coretesting.BaseSuite
    25  
    26  	backend *commonmocks.MockLeadershipPinningBackend
    27  	machine *commonmocks.MockLeadershipMachine
    28  	pinner  *mocks.MockPinner
    29  
    30  	modelTag    names.ModelTag
    31  	authTag     names.Tag
    32  	api         *common.LeadershipPinning
    33  	machineApps []string
    34  }
    35  
    36  var _ = gc.Suite(&LeadershipSuite{})
    37  
    38  func (s *LeadershipSuite) SetUpSuite(c *gc.C) {
    39  	s.BaseSuite.SetUpSuite(c)
    40  
    41  	s.modelTag = names.NewModelTag(utils.MustNewUUID().String())
    42  	s.machineApps = []string{"mysql", "redis", "wordpress"}
    43  }
    44  
    45  func (s *LeadershipSuite) SetUpTest(c *gc.C) {
    46  	s.BaseSuite.SetUpTest(c)
    47  	s.authTag = nil
    48  }
    49  
    50  func (s *LeadershipSuite) TestPinnedLeadershipSuccess(c *gc.C) {
    51  	s.authTag = names.NewUserTag("admin")
    52  	defer s.setup(c).Finish()
    53  
    54  	pinned := map[string][]string{"redis": {"machine-0", "machine-1"}}
    55  	s.pinner.EXPECT().PinnedLeadership().Return(pinned, nil)
    56  
    57  	res, err := s.api.PinnedLeadership()
    58  	c.Assert(err, jc.ErrorIsNil)
    59  	c.Check(res.Result, gc.DeepEquals, pinned)
    60  }
    61  
    62  func (s *LeadershipSuite) TestPinnedLeadershipPermissionDenied(c *gc.C) {
    63  	defer s.setup(c).Finish()
    64  
    65  	_, err := s.api.PinnedLeadership()
    66  	c.Check(err, gc.ErrorMatches, "permission denied")
    67  }
    68  
    69  func (s *LeadershipSuite) TestPinApplicationLeadersSuccess(c *gc.C) {
    70  	defer s.setup(c).Finish()
    71  
    72  	for _, app := range s.machineApps {
    73  		s.pinner.EXPECT().PinLeadership(app, s.authTag.String()).Return(nil)
    74  	}
    75  
    76  	res, err := s.api.PinApplicationLeaders()
    77  	c.Assert(err, jc.ErrorIsNil)
    78  	c.Check(res, gc.DeepEquals, params.PinApplicationsResults{Results: s.pinApplicationsSuccessResults()})
    79  }
    80  
    81  func (s *LeadershipSuite) TestPinApplicationLeadersPartialError(c *gc.C) {
    82  	defer s.setup(c).Finish()
    83  
    84  	errorRes := errors.New("boom")
    85  	s.pinner.EXPECT().PinLeadership("mysql", s.authTag.String()).Return(nil)
    86  	s.pinner.EXPECT().PinLeadership("redis", s.authTag.String()).Return(nil)
    87  	s.pinner.EXPECT().PinLeadership("wordpress", s.authTag.String()).Return(errorRes)
    88  
    89  	res, err := s.api.PinApplicationLeaders()
    90  	c.Assert(err, jc.ErrorIsNil)
    91  
    92  	results := s.pinApplicationsSuccessResults()
    93  	results[2].Error = apiservererrors.ServerError(errorRes)
    94  	c.Check(res, gc.DeepEquals, params.PinApplicationsResults{Results: results})
    95  }
    96  
    97  func (s *LeadershipSuite) TestUnpinApplicationLeadersSuccess(c *gc.C) {
    98  	defer s.setup(c).Finish()
    99  
   100  	for _, app := range s.machineApps {
   101  		s.pinner.EXPECT().UnpinLeadership(app, s.authTag.String()).Return(nil)
   102  	}
   103  
   104  	res, err := s.api.UnpinApplicationLeaders()
   105  	c.Assert(err, jc.ErrorIsNil)
   106  	c.Check(res, gc.DeepEquals, params.PinApplicationsResults{Results: s.pinApplicationsSuccessResults()})
   107  }
   108  
   109  func (s *LeadershipSuite) TestUnpinApplicationLeadersPartialError(c *gc.C) {
   110  	defer s.setup(c).Finish()
   111  
   112  	errorRes := errors.New("boom")
   113  	s.pinner.EXPECT().UnpinLeadership("mysql", s.authTag.String()).Return(nil)
   114  	s.pinner.EXPECT().UnpinLeadership("redis", s.authTag.String()).Return(errorRes)
   115  	s.pinner.EXPECT().UnpinLeadership("wordpress", s.authTag.String()).Return(nil)
   116  
   117  	res, err := s.api.UnpinApplicationLeaders()
   118  	c.Assert(err, jc.ErrorIsNil)
   119  
   120  	results := s.pinApplicationsSuccessResults()
   121  	results[1].Error = apiservererrors.ServerError(errorRes)
   122  	c.Check(res, gc.DeepEquals, params.PinApplicationsResults{Results: results})
   123  }
   124  
   125  func (s *LeadershipSuite) TestPinApplicationLeadersPermissionDenied(c *gc.C) {
   126  	s.authTag = names.NewUserTag("some-random-cat")
   127  	defer s.setup(c).Finish()
   128  
   129  	_, err := s.api.PinApplicationLeaders()
   130  	c.Assert(err, gc.ErrorMatches, "permission denied")
   131  
   132  	_, err = s.api.UnpinApplicationLeaders()
   133  	c.Assert(err, gc.ErrorMatches, "permission denied")
   134  }
   135  
   136  func (s *LeadershipSuite) TestGetMachineApplicationNamesSuccess(c *gc.C) {
   137  	defer s.setup(c).Finish()
   138  
   139  	appNames, err := s.api.GetMachineApplicationNames(s.authTag.Id())
   140  	c.Assert(err, jc.ErrorIsNil)
   141  	c.Check(appNames, gc.DeepEquals, s.machineApps)
   142  }
   143  
   144  func (s *LeadershipSuite) TestPinApplicationLeadersByNameSuccess(c *gc.C) {
   145  	defer s.setup(c).Finish()
   146  
   147  	for _, app := range s.machineApps {
   148  		s.pinner.EXPECT().PinLeadership(app, s.authTag.String()).Return(nil)
   149  	}
   150  
   151  	res, err := s.api.PinApplicationLeadersByName(s.authTag, s.machineApps)
   152  	c.Assert(err, jc.ErrorIsNil)
   153  	c.Check(res, gc.DeepEquals, params.PinApplicationsResults{Results: s.pinApplicationsSuccessResults()})
   154  }
   155  
   156  func (s *LeadershipSuite) TestPinApplicationLeadersByNamePartialError(c *gc.C) {
   157  	defer s.setup(c).Finish()
   158  
   159  	errorRes := errors.New("boom")
   160  	s.pinner.EXPECT().PinLeadership("mysql", s.authTag.String()).Return(nil)
   161  	s.pinner.EXPECT().PinLeadership("redis", s.authTag.String()).Return(errorRes)
   162  	s.pinner.EXPECT().PinLeadership("wordpress", s.authTag.String()).Return(nil)
   163  
   164  	res, err := s.api.PinApplicationLeadersByName(s.authTag, s.machineApps)
   165  	c.Assert(err, jc.ErrorIsNil)
   166  
   167  	results := s.pinApplicationsSuccessResults()
   168  	results[1].Error = apiservererrors.ServerError(errorRes)
   169  	c.Check(res, gc.DeepEquals, params.PinApplicationsResults{Results: results})
   170  }
   171  
   172  func (s *LeadershipSuite) TestUnpinApplicationLeadersByNameSuccess(c *gc.C) {
   173  	defer s.setup(c).Finish()
   174  
   175  	for _, app := range s.machineApps {
   176  		s.pinner.EXPECT().UnpinLeadership(app, s.authTag.String()).Return(nil)
   177  	}
   178  
   179  	res, err := s.api.UnpinApplicationLeadersByName(s.authTag, s.machineApps)
   180  	c.Assert(err, jc.ErrorIsNil)
   181  	c.Check(res, gc.DeepEquals, params.PinApplicationsResults{Results: s.pinApplicationsSuccessResults()})
   182  }
   183  
   184  func (s *LeadershipSuite) TestUnpinApplicationLeadersByNamePartialError(c *gc.C) {
   185  	defer s.setup(c).Finish()
   186  
   187  	errorRes := errors.New("boom")
   188  	s.pinner.EXPECT().UnpinLeadership("mysql", s.authTag.String()).Return(nil)
   189  	s.pinner.EXPECT().UnpinLeadership("redis", s.authTag.String()).Return(errorRes)
   190  	s.pinner.EXPECT().UnpinLeadership("wordpress", s.authTag.String()).Return(nil)
   191  
   192  	res, err := s.api.UnpinApplicationLeadersByName(s.authTag, s.machineApps)
   193  	c.Assert(err, jc.ErrorIsNil)
   194  
   195  	results := s.pinApplicationsSuccessResults()
   196  	results[1].Error = apiservererrors.ServerError(errorRes)
   197  	c.Check(res, gc.DeepEquals, params.PinApplicationsResults{Results: results})
   198  }
   199  
   200  func (s *LeadershipSuite) setup(c *gc.C) *gomock.Controller {
   201  	ctrl := gomock.NewController(c)
   202  
   203  	s.backend = commonmocks.NewMockLeadershipPinningBackend(ctrl)
   204  	s.machine = commonmocks.NewMockLeadershipMachine(ctrl)
   205  	s.pinner = mocks.NewMockPinner(ctrl)
   206  
   207  	s.backend.EXPECT().Machine("0").Return(s.machine, nil).AnyTimes()
   208  	s.machine.EXPECT().ApplicationNames().Return(s.machineApps, nil).AnyTimes()
   209  
   210  	if s.authTag == nil {
   211  		s.authTag = names.NewMachineTag("0")
   212  	}
   213  
   214  	var err error
   215  	s.api, err = common.NewLeadershipPinning(
   216  		s.backend,
   217  		s.modelTag,
   218  		s.pinner,
   219  		&apiservertesting.FakeAuthorizer{Tag: s.authTag},
   220  	)
   221  	c.Assert(err, jc.ErrorIsNil)
   222  
   223  	return ctrl
   224  }
   225  
   226  func (s *LeadershipSuite) pinApplicationsSuccessResults() []params.PinApplicationResult {
   227  	results := make([]params.PinApplicationResult, len(s.machineApps))
   228  	for i, app := range s.machineApps {
   229  		results[i] = params.PinApplicationResult{ApplicationName: app}
   230  	}
   231  	return results
   232  }