github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/controller/singular/singular_test.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package singular_test
     5  
     6  import (
     7  	"context"
     8  	"time"
     9  
    10  	"github.com/juju/errors"
    11  	"github.com/juju/testing"
    12  	jc "github.com/juju/testing/checkers"
    13  	"github.com/juju/utils"
    14  	gc "gopkg.in/check.v1"
    15  	"gopkg.in/juju/names.v2"
    16  
    17  	"github.com/juju/juju/apiserver/common"
    18  	"github.com/juju/juju/apiserver/facades/controller/singular"
    19  	"github.com/juju/juju/apiserver/params"
    20  	"github.com/juju/juju/core/lease"
    21  	coretesting "github.com/juju/juju/testing"
    22  )
    23  
    24  var otherUUID = utils.MustNewUUID().String()
    25  
    26  type SingularSuite struct {
    27  	testing.IsolationSuite
    28  }
    29  
    30  var _ = gc.Suite(&SingularSuite{})
    31  
    32  func (s *SingularSuite) TestRequiresController(c *gc.C) {
    33  	auth := mockAuth{nonController: true}
    34  	facade, err := singular.NewFacade(nil, nil, auth)
    35  	c.Check(facade, gc.IsNil)
    36  	c.Check(err, gc.Equals, common.ErrPerm)
    37  }
    38  
    39  func (s *SingularSuite) TestAcceptsController(c *gc.C) {
    40  	backend := &mockBackend{}
    41  	facade, err := singular.NewFacade(backend, backend, mockAuth{})
    42  	c.Check(facade, gc.NotNil)
    43  	c.Check(err, jc.ErrorIsNil)
    44  
    45  	backend.stub.CheckCallNames(c)
    46  }
    47  
    48  func (s *SingularSuite) TestInvalidClaims(c *gc.C) {
    49  	breakers := []func(claim *params.SingularClaim){
    50  		func(claim *params.SingularClaim) { claim.EntityTag = "machine-123" },
    51  		func(claim *params.SingularClaim) { claim.EntityTag = "model-" + otherUUID },
    52  		func(claim *params.SingularClaim) { claim.ClaimantTag = "" },
    53  		func(claim *params.SingularClaim) { claim.ClaimantTag = "machine-42" },
    54  		func(claim *params.SingularClaim) { claim.Duration = time.Second - time.Millisecond },
    55  		func(claim *params.SingularClaim) { claim.Duration = time.Minute + time.Millisecond },
    56  	}
    57  	count := len(breakers)
    58  
    59  	var claims params.SingularClaims
    60  	claims.Claims = make([]params.SingularClaim, count)
    61  	for i, breaker := range breakers {
    62  		claim := params.SingularClaim{
    63  			EntityTag:   coretesting.ModelTag.String(),
    64  			ClaimantTag: "machine-123",
    65  			Duration:    time.Minute,
    66  		}
    67  		breaker(&claim)
    68  		claims.Claims[i] = claim
    69  	}
    70  
    71  	backend := &mockBackend{}
    72  	facade, err := singular.NewFacade(backend, backend, mockAuth{})
    73  	c.Assert(err, jc.ErrorIsNil)
    74  	result := facade.Claim(claims)
    75  	c.Assert(result.Results, gc.HasLen, count)
    76  
    77  	for i, result := range result.Results {
    78  		c.Logf("checking claim %d", i)
    79  		checkDenied(c, result)
    80  	}
    81  	backend.stub.CheckCallNames(c)
    82  }
    83  
    84  func (s *SingularSuite) TestValidClaims(c *gc.C) {
    85  	durations := []time.Duration{
    86  		time.Second,
    87  		10 * time.Second,
    88  		30 * time.Second,
    89  		time.Minute,
    90  	}
    91  	errors := []error{
    92  		nil,
    93  		errors.New("pow!"),
    94  		lease.ErrClaimDenied,
    95  		nil,
    96  	}
    97  	count := len(durations)
    98  	if len(errors) != count {
    99  		c.Fatalf("please fix your test data")
   100  	}
   101  
   102  	var claims params.SingularClaims
   103  	claims.Claims = make([]params.SingularClaim, count)
   104  	expectCalls := []testing.StubCall{}
   105  	for i, duration := range durations {
   106  		var tag names.Tag = coretesting.ModelTag
   107  		if i%2 == 1 {
   108  			tag = coretesting.ControllerTag
   109  		}
   110  		claims.Claims[i] = params.SingularClaim{
   111  			EntityTag:   tag.String(),
   112  			ClaimantTag: "machine-123",
   113  			Duration:    duration,
   114  		}
   115  		expectCalls = append(expectCalls, testing.StubCall{
   116  			FuncName: "Claim",
   117  			Args: []interface{}{
   118  				tag.Id(),
   119  				"machine-123",
   120  				durations[i],
   121  			},
   122  		})
   123  	}
   124  
   125  	backend := &mockBackend{}
   126  	backend.stub.SetErrors(errors...)
   127  	facade, err := singular.NewFacade(backend, backend, mockAuth{})
   128  	c.Assert(err, jc.ErrorIsNil)
   129  	result := facade.Claim(claims)
   130  	c.Assert(result.Results, gc.HasLen, count)
   131  
   132  	for i, err := range result.Results {
   133  		switch errors[i] {
   134  		case nil:
   135  			c.Check(err.Error, gc.IsNil)
   136  		case lease.ErrClaimDenied:
   137  			c.Check(err.Error, jc.Satisfies, params.IsCodeLeaseClaimDenied)
   138  		default:
   139  			c.Check(err.Error.Error(), gc.Equals, errors[i].Error())
   140  		}
   141  	}
   142  	backend.stub.CheckCalls(c, expectCalls)
   143  }
   144  
   145  func (s *SingularSuite) TestWait(c *gc.C) {
   146  	waits := params.Entities{
   147  		Entities: []params.Entity{{
   148  			"machine-123", // rejected
   149  		}, {
   150  			"model-" + otherUUID, // rejected
   151  		}, {
   152  			coretesting.ModelTag.String(), // stub-error
   153  		}, {
   154  			coretesting.ModelTag.String(), // success
   155  		}, {
   156  			coretesting.ControllerTag.String(), // success
   157  		}},
   158  	}
   159  	count := len(waits.Entities)
   160  
   161  	backend := &mockBackend{}
   162  	backend.stub.SetErrors(errors.New("zap!"), nil)
   163  	facade, err := singular.NewFacade(backend, backend, mockAuth{})
   164  	c.Assert(err, jc.ErrorIsNil)
   165  	result := facade.Wait(context.TODO(), waits)
   166  	c.Assert(result.Results, gc.HasLen, count)
   167  
   168  	checkDenied(c, result.Results[0])
   169  	checkDenied(c, result.Results[1])
   170  	c.Check(result.Results[2].Error, gc.ErrorMatches, "zap!")
   171  	c.Check(result.Results[3].Error, gc.IsNil)
   172  	c.Check(result.Results[4].Error, gc.IsNil)
   173  
   174  	backend.stub.CheckCalls(c, []testing.StubCall{{
   175  		FuncName: "WaitUntilExpired",
   176  		Args:     []interface{}{coretesting.ModelTag.Id()},
   177  	}, {
   178  		FuncName: "WaitUntilExpired",
   179  		Args:     []interface{}{coretesting.ModelTag.Id()},
   180  	}, {
   181  		FuncName: "WaitUntilExpired",
   182  		Args:     []interface{}{coretesting.ControllerTag.Id()},
   183  	}})
   184  }
   185  
   186  func (s *SingularSuite) TestWaitCancelled(c *gc.C) {
   187  	waits := params.Entities{
   188  		Entities: []params.Entity{{
   189  			coretesting.ModelTag.String(), // success
   190  		}},
   191  	}
   192  	count := len(waits.Entities)
   193  
   194  	backend := &mockBackend{}
   195  	facade, err := singular.NewFacade(backend, backend, mockAuth{})
   196  	c.Assert(err, jc.ErrorIsNil)
   197  
   198  	ctx, cancel := context.WithCancel(context.Background())
   199  	cancel()
   200  	result := facade.Wait(ctx, waits)
   201  	c.Assert(result.Results, gc.HasLen, count)
   202  	c.Check(result.Results[0].Error, gc.ErrorMatches, "waiting for lease cancelled by client")
   203  }
   204  
   205  func checkDenied(c *gc.C, result params.ErrorResult) {
   206  	if !c.Check(result.Error, gc.NotNil) {
   207  		return
   208  	}
   209  	c.Check(result.Error, gc.ErrorMatches, "permission denied")
   210  	c.Check(result.Error, jc.Satisfies, params.IsCodeUnauthorized)
   211  }