github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/provider/ec2/securitygroups_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package ec2_test
     5  
     6  import (
     7  	stdcontext "context"
     8  	"time"
     9  
    10  	"github.com/aws/aws-sdk-go-v2/aws"
    11  	awsec2 "github.com/aws/aws-sdk-go-v2/service/ec2"
    12  	"github.com/aws/aws-sdk-go-v2/service/ec2/types"
    13  	"github.com/aws/smithy-go"
    14  	"github.com/juju/clock"
    15  	"github.com/juju/clock/testclock"
    16  	"github.com/juju/testing"
    17  	jc "github.com/juju/testing/checkers"
    18  	gc "gopkg.in/check.v1"
    19  
    20  	"github.com/juju/juju/environs/context"
    21  	"github.com/juju/juju/provider/ec2"
    22  	coretesting "github.com/juju/juju/testing"
    23  )
    24  
    25  type SecurityGroupSuite struct {
    26  	coretesting.BaseSuite
    27  
    28  	clientStub   *stubClient
    29  	deleteFunc   func(ec2.SecurityGroupCleaner, context.ProviderCallContext, types.GroupIdentifier, clock.Clock) error
    30  	cloudCallCtx context.ProviderCallContext
    31  }
    32  
    33  var _ = gc.Suite(&SecurityGroupSuite{})
    34  
    35  func (s *SecurityGroupSuite) SetUpSuite(c *gc.C) {
    36  	s.BaseSuite.SetUpSuite(c)
    37  	s.deleteFunc = *ec2.DeleteSecurityGroupInsistently
    38  }
    39  
    40  func (s *SecurityGroupSuite) SetUpTest(c *gc.C) {
    41  	s.BaseSuite.SetUpTest(c)
    42  	s.clientStub = &stubClient{
    43  		Stub: &testing.Stub{},
    44  		deleteSecurityGroup: func(group types.GroupIdentifier) (resp *awsec2.DeleteSecurityGroupOutput, err error) {
    45  			return nil, nil
    46  		},
    47  	}
    48  	s.cloudCallCtx = context.NewEmptyCloudCallContext()
    49  }
    50  
    51  func (s *SecurityGroupSuite) TestDeleteSecurityGroupSuccess(c *gc.C) {
    52  	err := s.deleteFunc(s.clientStub, s.cloudCallCtx, types.GroupIdentifier{}, testclock.NewClock(time.Time{}))
    53  	c.Assert(err, jc.ErrorIsNil)
    54  	s.clientStub.CheckCallNames(c, "DeleteSecurityGroup")
    55  }
    56  
    57  func (s *SecurityGroupSuite) TestDeleteSecurityGroupInvalidGroupNotFound(c *gc.C) {
    58  	s.clientStub.deleteSecurityGroup = func(group types.GroupIdentifier) (resp *awsec2.DeleteSecurityGroupOutput, err error) {
    59  		return nil, &smithy.GenericAPIError{Code: "InvalidGroup.NotFound"}
    60  	}
    61  	err := s.deleteFunc(s.clientStub, s.cloudCallCtx, types.GroupIdentifier{}, testclock.NewClock(time.Time{}))
    62  	c.Assert(err, jc.ErrorIsNil)
    63  	s.clientStub.CheckCallNames(c, "DeleteSecurityGroup")
    64  }
    65  
    66  func (s *SecurityGroupSuite) TestDeleteSecurityGroupFewCalls(c *gc.C) {
    67  	t0 := time.Time{}
    68  	clock := autoAdvancingClock{testclock.NewClock(t0)}
    69  	count := 0
    70  	maxCalls := 4
    71  	expectedTimes := []time.Time{
    72  		t0,
    73  		t0.Add(time.Second),
    74  		t0.Add(3 * time.Second),
    75  		t0.Add(7 * time.Second),
    76  		t0.Add(15 * time.Second),
    77  	}
    78  	s.clientStub.deleteSecurityGroup = func(group types.GroupIdentifier) (resp *awsec2.DeleteSecurityGroupOutput, err error) {
    79  		c.Assert(clock.Now(), gc.Equals, expectedTimes[count])
    80  		if count < maxCalls {
    81  			count++
    82  			return nil, &smithy.GenericAPIError{Code: "keep going"}
    83  		}
    84  		return nil, nil
    85  	}
    86  	err := s.deleteFunc(s.clientStub, s.cloudCallCtx, types.GroupIdentifier{}, clock)
    87  	c.Assert(err, jc.ErrorIsNil)
    88  
    89  	expectedCalls := make([]string, maxCalls+1)
    90  	for i := 0; i < maxCalls+1; i++ {
    91  		expectedCalls[i] = "DeleteSecurityGroup"
    92  	}
    93  	s.clientStub.CheckCallNames(c, expectedCalls...)
    94  }
    95  
    96  type autoAdvancingClock struct {
    97  	*testclock.Clock
    98  }
    99  
   100  func (c autoAdvancingClock) After(d time.Duration) <-chan time.Time {
   101  	ch := c.Clock.After(d)
   102  	c.Advance(d)
   103  	return ch
   104  }
   105  
   106  type stubClient struct {
   107  	*testing.Stub
   108  	deleteSecurityGroup func(group types.GroupIdentifier) (*awsec2.DeleteSecurityGroupOutput, error)
   109  }
   110  
   111  func (s *stubClient) DeleteSecurityGroup(ctx stdcontext.Context, input *awsec2.DeleteSecurityGroupInput, _ ...func(*awsec2.Options)) (*awsec2.DeleteSecurityGroupOutput, error) {
   112  	s.MethodCall(s, "DeleteSecurityGroup", aws.ToString(input.GroupId), aws.ToString(input.GroupName))
   113  	return s.deleteSecurityGroup(types.GroupIdentifier{
   114  		GroupId:   input.GroupId,
   115  		GroupName: input.GroupName,
   116  	})
   117  }