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 }