github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/agent/leadership/leadership_test.go (about)

     1  // Copyright 2014-2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package leadership_test
     5  
     6  // Test that the service is translating incoming parameters to the
     7  // manager layer correctly, and also translates the results back into
     8  // network parameters.
     9  
    10  import (
    11  	"context"
    12  	"time"
    13  
    14  	"github.com/juju/errors"
    15  	"github.com/juju/testing"
    16  	jc "github.com/juju/testing/checkers"
    17  	gc "gopkg.in/check.v1"
    18  	"gopkg.in/juju/names.v2"
    19  
    20  	"github.com/juju/juju/apiserver/facade"
    21  	"github.com/juju/juju/apiserver/facades/agent/leadership"
    22  	"github.com/juju/juju/apiserver/params"
    23  	coreleadership "github.com/juju/juju/core/leadership"
    24  )
    25  
    26  type leadershipSuite struct {
    27  	testing.IsolationSuite
    28  }
    29  
    30  var _ = gc.Suite(&leadershipSuite{})
    31  
    32  const (
    33  	StubAppNm  = "stub-application"
    34  	StubUnitNm = "stub-application/0"
    35  )
    36  
    37  type stubClaimer struct {
    38  	ClaimLeadershipFn              func(sid, uid string, duration time.Duration) error
    39  	BlockUntilLeadershipReleasedFn func(serviceId string, cancel <-chan struct{}) error
    40  }
    41  
    42  func (m *stubClaimer) ClaimLeadership(sid, uid string, duration time.Duration) error {
    43  	if m.ClaimLeadershipFn != nil {
    44  		return m.ClaimLeadershipFn(sid, uid, duration)
    45  	}
    46  	return nil
    47  }
    48  
    49  func (m *stubClaimer) BlockUntilLeadershipReleased(serviceId string, cancel <-chan struct{}) error {
    50  	if m.BlockUntilLeadershipReleasedFn != nil {
    51  		return m.BlockUntilLeadershipReleasedFn(serviceId, cancel)
    52  	}
    53  	return nil
    54  }
    55  
    56  type stubAuthorizer struct {
    57  	facade.Authorizer
    58  	tag names.Tag
    59  }
    60  
    61  func (m stubAuthorizer) AuthUnitAgent() bool {
    62  	_, ok := m.tag.(names.UnitTag)
    63  	return ok
    64  }
    65  
    66  func (m stubAuthorizer) AuthApplicationAgent() bool {
    67  	_, ok := m.tag.(names.ApplicationTag)
    68  	return ok
    69  }
    70  
    71  func (m stubAuthorizer) AuthOwner(tag names.Tag) bool {
    72  	return tag == m.tag
    73  }
    74  
    75  func (m stubAuthorizer) GetAuthTag() names.Tag {
    76  	return m.tag
    77  }
    78  
    79  func checkDurationEquals(c *gc.C, actual, expect time.Duration) {
    80  	delta := actual - expect
    81  	if delta < 0 {
    82  		delta = -delta
    83  	}
    84  	c.Check(delta, jc.LessThan, time.Microsecond)
    85  }
    86  
    87  func newLeadershipService(
    88  	c *gc.C, claimer coreleadership.Claimer, authorizer facade.Authorizer,
    89  ) leadership.LeadershipService {
    90  	if authorizer == nil {
    91  		authorizer = stubAuthorizer{tag: names.NewUnitTag(StubUnitNm)}
    92  	}
    93  	result, err := leadership.NewLeadershipService(claimer, authorizer)
    94  	c.Assert(err, jc.ErrorIsNil)
    95  	return result
    96  }
    97  
    98  func (s *leadershipSuite) TestClaimLeadershipTranslation(c *gc.C) {
    99  	claimer := &stubClaimer{
   100  		ClaimLeadershipFn: func(sid, uid string, duration time.Duration) error {
   101  			c.Check(sid, gc.Equals, StubAppNm)
   102  			c.Check(uid, gc.Equals, StubUnitNm)
   103  			expectDuration := time.Duration(299.9 * float64(time.Second))
   104  			checkDurationEquals(c, duration, expectDuration)
   105  			return nil
   106  		},
   107  	}
   108  
   109  	ldrSvc := newLeadershipService(c, claimer, nil)
   110  	results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{
   111  		Params: []params.ClaimLeadershipParams{
   112  			{
   113  				ApplicationTag:  names.NewApplicationTag(StubAppNm).String(),
   114  				UnitTag:         names.NewUnitTag(StubUnitNm).String(),
   115  				DurationSeconds: 299.9,
   116  			},
   117  		},
   118  	})
   119  
   120  	c.Check(err, jc.ErrorIsNil)
   121  	c.Assert(results.Results, gc.HasLen, 1)
   122  	c.Check(results.Results[0].Error, gc.IsNil)
   123  }
   124  
   125  func (s *leadershipSuite) TestClaimLeadershipApplicationAgent(c *gc.C) {
   126  	claimer := &stubClaimer{
   127  		ClaimLeadershipFn: func(sid, uid string, duration time.Duration) error {
   128  			c.Check(sid, gc.Equals, StubAppNm)
   129  			c.Check(uid, gc.Equals, StubUnitNm)
   130  			expectDuration := time.Duration(299.9 * float64(time.Second))
   131  			checkDurationEquals(c, duration, expectDuration)
   132  			return nil
   133  		},
   134  	}
   135  
   136  	authorizer := &stubAuthorizer{
   137  		tag: names.NewApplicationTag(StubAppNm),
   138  	}
   139  	ldrSvc := newLeadershipService(c, claimer, authorizer)
   140  	results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{
   141  		Params: []params.ClaimLeadershipParams{
   142  			{
   143  				ApplicationTag:  names.NewApplicationTag(StubAppNm).String(),
   144  				UnitTag:         names.NewUnitTag(StubUnitNm).String(),
   145  				DurationSeconds: 299.9,
   146  			},
   147  		},
   148  	})
   149  
   150  	c.Check(err, jc.ErrorIsNil)
   151  	c.Assert(results.Results, gc.HasLen, 1)
   152  	c.Check(results.Results[0].Error, gc.IsNil)
   153  }
   154  
   155  func (s *leadershipSuite) TestClaimLeadershipDeniedError(c *gc.C) {
   156  	claimer := &stubClaimer{
   157  		ClaimLeadershipFn: func(sid, uid string, duration time.Duration) error {
   158  			c.Check(sid, gc.Equals, StubAppNm)
   159  			c.Check(uid, gc.Equals, StubUnitNm)
   160  			expectDuration := time.Duration(5.001 * float64(time.Second))
   161  			checkDurationEquals(c, duration, expectDuration)
   162  			return errors.Annotatef(coreleadership.ErrClaimDenied, "obfuscated")
   163  		},
   164  	}
   165  
   166  	ldrSvc := newLeadershipService(c, claimer, nil)
   167  	results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{
   168  		Params: []params.ClaimLeadershipParams{
   169  			{
   170  				ApplicationTag:  names.NewApplicationTag(StubAppNm).String(),
   171  				UnitTag:         names.NewUnitTag(StubUnitNm).String(),
   172  				DurationSeconds: 5.001,
   173  			},
   174  		},
   175  	})
   176  
   177  	c.Check(err, jc.ErrorIsNil)
   178  	c.Assert(results.Results, gc.HasLen, 1)
   179  	c.Check(results.Results[0].Error, jc.Satisfies, params.IsCodeLeadershipClaimDenied)
   180  }
   181  
   182  func (s *leadershipSuite) TestClaimLeadershipBadService(c *gc.C) {
   183  	ldrSvc := newLeadershipService(c, nil, nil)
   184  
   185  	results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{
   186  		Params: []params.ClaimLeadershipParams{
   187  			{
   188  				ApplicationTag:  "application-bad/0",
   189  				UnitTag:         names.NewUnitTag(StubUnitNm).String(),
   190  				DurationSeconds: 123.45,
   191  			},
   192  		},
   193  	})
   194  	c.Check(err, jc.ErrorIsNil)
   195  	c.Assert(results.Results, gc.HasLen, 1)
   196  	c.Check(results.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized)
   197  }
   198  
   199  func (s *leadershipSuite) TestClaimLeadershipBadUnit(c *gc.C) {
   200  	ldrSvc := newLeadershipService(c, nil, nil)
   201  
   202  	results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{
   203  		Params: []params.ClaimLeadershipParams{
   204  			{
   205  				ApplicationTag:  names.NewApplicationTag(StubAppNm).String(),
   206  				UnitTag:         "unit-bad",
   207  				DurationSeconds: 123.45,
   208  			},
   209  		},
   210  	})
   211  	c.Check(err, jc.ErrorIsNil)
   212  	c.Assert(results.Results, gc.HasLen, 1)
   213  	c.Check(results.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized)
   214  }
   215  
   216  func (s *leadershipSuite) TestClaimLeadershipDurationTooShort(c *gc.C) {
   217  	ldrSvc := newLeadershipService(c, nil, nil)
   218  
   219  	results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{
   220  		Params: []params.ClaimLeadershipParams{
   221  			{
   222  				ApplicationTag:  names.NewApplicationTag(StubAppNm).String(),
   223  				UnitTag:         names.NewUnitTag(StubUnitNm).String(),
   224  				DurationSeconds: 4.99,
   225  			},
   226  		},
   227  	})
   228  	c.Check(err, jc.ErrorIsNil)
   229  	c.Assert(results.Results, gc.HasLen, 1)
   230  	c.Check(results.Results[0].Error, gc.ErrorMatches, "invalid duration")
   231  }
   232  
   233  func (s *leadershipSuite) TestClaimLeadershipDurationTooLong(c *gc.C) {
   234  	ldrSvc := newLeadershipService(c, nil, nil)
   235  
   236  	results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{
   237  		Params: []params.ClaimLeadershipParams{
   238  			{
   239  				ApplicationTag:  names.NewApplicationTag(StubAppNm).String(),
   240  				UnitTag:         names.NewUnitTag(StubUnitNm).String(),
   241  				DurationSeconds: 300.1,
   242  			},
   243  		},
   244  	})
   245  	c.Check(err, jc.ErrorIsNil)
   246  	c.Assert(results.Results, gc.HasLen, 1)
   247  	c.Check(results.Results[0].Error, gc.ErrorMatches, "invalid duration")
   248  }
   249  
   250  func (s *leadershipSuite) TestBlockUntilLeadershipReleasedTranslation(c *gc.C) {
   251  	claimer := &stubClaimer{
   252  		BlockUntilLeadershipReleasedFn: func(sid string, cancel <-chan struct{}) error {
   253  			c.Check(sid, gc.Equals, StubAppNm)
   254  			return nil
   255  		},
   256  	}
   257  
   258  	ldrSvc := newLeadershipService(c, claimer, nil)
   259  	result, err := ldrSvc.BlockUntilLeadershipReleased(
   260  		context.Background(),
   261  		names.NewApplicationTag(StubAppNm),
   262  	)
   263  
   264  	c.Check(err, jc.ErrorIsNil)
   265  	c.Check(result.Error, gc.IsNil)
   266  }
   267  
   268  func (s *leadershipSuite) TestBlockUntilLeadershipReleasedContext(c *gc.C) {
   269  	ctx, cancel := context.WithCancel(context.Background())
   270  	cancel()
   271  	claimer := &stubClaimer{
   272  		BlockUntilLeadershipReleasedFn: func(sid string, cancel <-chan struct{}) error {
   273  			c.Check(sid, gc.Equals, StubAppNm)
   274  			c.Check(cancel, gc.Equals, ctx.Done())
   275  			return coreleadership.ErrBlockCancelled
   276  		},
   277  	}
   278  
   279  	ldrSvc := newLeadershipService(c, claimer, nil)
   280  	result, err := ldrSvc.BlockUntilLeadershipReleased(
   281  		ctx,
   282  		names.NewApplicationTag(StubAppNm),
   283  	)
   284  
   285  	c.Check(err, jc.ErrorIsNil)
   286  	c.Check(result.Error, gc.ErrorMatches, "waiting for leadership cancelled by client")
   287  }
   288  
   289  func (s *leadershipSuite) TestClaimLeadershipFailBadUnit(c *gc.C) {
   290  	authorizer := &stubAuthorizer{
   291  		tag: names.NewUnitTag("lol-different/123"),
   292  	}
   293  
   294  	ldrSvc := newLeadershipService(c, nil, authorizer)
   295  	results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{
   296  		Params: []params.ClaimLeadershipParams{
   297  			{
   298  				ApplicationTag:  names.NewApplicationTag(StubAppNm).String(),
   299  				UnitTag:         names.NewUnitTag(StubUnitNm).String(),
   300  				DurationSeconds: 123.45,
   301  			},
   302  		},
   303  	})
   304  
   305  	c.Check(err, jc.ErrorIsNil)
   306  	c.Assert(results.Results, gc.HasLen, 1)
   307  	c.Check(results.Results[0].Error, gc.ErrorMatches, "permission denied")
   308  	c.Check(results.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized)
   309  }
   310  
   311  func (s *leadershipSuite) TestClaimLeadershipFailBadService(c *gc.C) {
   312  	ldrSvc := newLeadershipService(c, nil, nil)
   313  	results, err := ldrSvc.ClaimLeadership(params.ClaimLeadershipBulkParams{
   314  		Params: []params.ClaimLeadershipParams{
   315  			{
   316  				ApplicationTag:  names.NewApplicationTag("lol-different").String(),
   317  				UnitTag:         names.NewUnitTag(StubUnitNm).String(),
   318  				DurationSeconds: 123.45,
   319  			},
   320  		},
   321  	})
   322  
   323  	c.Check(err, jc.ErrorIsNil)
   324  	c.Assert(results.Results, gc.HasLen, 1)
   325  	c.Check(results.Results[0].Error, gc.ErrorMatches, "permission denied")
   326  	c.Check(results.Results[0].Error, jc.Satisfies, params.IsCodeUnauthorized)
   327  }
   328  
   329  func (s *leadershipSuite) TestCreateUnauthorized(c *gc.C) {
   330  	authorizer := &stubAuthorizer{
   331  		tag: names.NewMachineTag("123"),
   332  	}
   333  
   334  	ldrSvc, err := leadership.NewLeadershipService(nil, authorizer)
   335  	c.Check(ldrSvc, gc.IsNil)
   336  	c.Check(err, gc.ErrorMatches, "permission denied")
   337  	c.Check(err, jc.Satisfies, errors.IsUnauthorized)
   338  }