sigs.k8s.io/cluster-api-provider-aws@v1.5.5/pkg/cloud/services/instancestate/queue_test.go (about) 1 /* 2 Copyright 2020 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package instancestate 18 19 import ( 20 "bytes" 21 "encoding/json" 22 "testing" 23 24 "github.com/aws/aws-sdk-go/aws" 25 "github.com/aws/aws-sdk-go/aws/awserr" 26 "github.com/aws/aws-sdk-go/service/sqs" 27 "github.com/golang/mock/gomock" 28 . "github.com/onsi/gomega" 29 "github.com/pkg/errors" 30 31 "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/instancestate/mock_sqsiface" 32 ) 33 34 func TestReconcileSQSQueue(t *testing.T) { 35 mockCtrl := gomock.NewController(t) 36 defer mockCtrl.Finish() 37 38 testCases := []struct { 39 name string 40 expect func(m *mock_sqsiface.MockSQSAPIMockRecorder) 41 expectErr bool 42 }{ 43 { 44 name: "successfully creates an SQS queue", 45 expect: func(m *mock_sqsiface.MockSQSAPIMockRecorder) { 46 attrs := make(map[string]string) 47 attrs[sqs.QueueAttributeNameReceiveMessageWaitTimeSeconds] = "20" 48 m.CreateQueue(&sqs.CreateQueueInput{ 49 QueueName: aws.String("test-cluster-queue"), 50 Attributes: aws.StringMap(attrs), 51 }).Return(nil, nil) 52 }, 53 expectErr: false, 54 }, 55 { 56 name: "does not error if queue already exists", 57 expect: func(m *mock_sqsiface.MockSQSAPIMockRecorder) { 58 attrs := make(map[string]string) 59 attrs[sqs.QueueAttributeNameReceiveMessageWaitTimeSeconds] = "20" 60 m.CreateQueue(&sqs.CreateQueueInput{ 61 QueueName: aws.String("test-cluster-queue"), 62 Attributes: aws.StringMap(attrs), 63 }).Return(nil, awserr.New(sqs.ErrCodeQueueNameExists, "", nil)) 64 }, 65 expectErr: false, 66 }, 67 { 68 name: "errors when unexpected error occurs", 69 expect: func(m *mock_sqsiface.MockSQSAPIMockRecorder) { 70 attrs := make(map[string]string) 71 attrs[sqs.QueueAttributeNameReceiveMessageWaitTimeSeconds] = "20" 72 m.CreateQueue(&sqs.CreateQueueInput{ 73 QueueName: aws.String("test-cluster-queue"), 74 Attributes: aws.StringMap(attrs), 75 }).Return(nil, errors.New("some error")) 76 }, 77 expectErr: true, 78 }, 79 } 80 81 for _, tc := range testCases { 82 t.Run(tc.name, func(t *testing.T) { 83 g := NewWithT(t) 84 sqsMock := mock_sqsiface.NewMockSQSAPI(mockCtrl) 85 clusterScope, err := setupCluster("test-cluster") 86 g.Expect(err).To(Not(HaveOccurred())) 87 88 tc.expect(sqsMock.EXPECT()) 89 s := NewService(clusterScope) 90 s.SQSClient = sqsMock 91 92 err = s.reconcileSQSQueue() 93 94 if tc.expectErr { 95 g.Expect(err).NotTo(BeNil()) 96 } else { 97 g.Expect(err).To(BeNil()) 98 } 99 }) 100 } 101 } 102 103 func TestDeleteSQSQueue(t *testing.T) { 104 mockCtrl := gomock.NewController(t) 105 defer mockCtrl.Finish() 106 107 testCases := []struct { 108 name string 109 expect func(m *mock_sqsiface.MockSQSAPIMockRecorder) 110 expectErr bool 111 }{ 112 { 113 name: "deletes queue successfully", 114 expect: func(m *mock_sqsiface.MockSQSAPIMockRecorder) { 115 m.GetQueueUrl(&sqs.GetQueueUrlInput{ 116 QueueName: aws.String("test-cluster-queue"), 117 }).Return(&sqs.GetQueueUrlOutput{QueueUrl: aws.String("test-cluster-queue-url")}, nil) 118 m.DeleteQueue(&sqs.DeleteQueueInput{ 119 QueueUrl: aws.String("test-cluster-queue-url"), 120 }).Return(nil, nil) 121 }, 122 expectErr: false, 123 }, 124 { 125 name: "doesn't return error if queue not found when calling GetQueueUrl", 126 expect: func(m *mock_sqsiface.MockSQSAPIMockRecorder) { 127 m.GetQueueUrl(&sqs.GetQueueUrlInput{ 128 QueueName: aws.String("test-cluster-queue"), 129 }).Return(nil, awserr.New(sqs.ErrCodeQueueDoesNotExist, "", nil)) 130 }, 131 expectErr: false, 132 }, 133 { 134 name: "returns error if Describe Queue failed for unexpected reason", 135 expect: func(m *mock_sqsiface.MockSQSAPIMockRecorder) { 136 m.GetQueueUrl(&sqs.GetQueueUrlInput{ 137 QueueName: aws.String("test-cluster-queue"), 138 }).Return(nil, errors.New("some error")) 139 }, 140 expectErr: true, 141 }, 142 { 143 name: "doesn't return error if queue not found when attempting delete", 144 expect: func(m *mock_sqsiface.MockSQSAPIMockRecorder) { 145 m.GetQueueUrl(&sqs.GetQueueUrlInput{ 146 QueueName: aws.String("test-cluster-queue"), 147 }).Return(&sqs.GetQueueUrlOutput{QueueUrl: aws.String("test-cluster-queue-url")}, nil) 148 m.DeleteQueue(&sqs.DeleteQueueInput{ 149 QueueUrl: aws.String("test-cluster-queue-url"), 150 }).Return(nil, awserr.New(sqs.ErrCodeQueueDoesNotExist, "", nil)) 151 }, 152 expectErr: false, 153 }, 154 { 155 name: "returns error if delete queue failed for unexpected reason", 156 expect: func(m *mock_sqsiface.MockSQSAPIMockRecorder) { 157 m.GetQueueUrl(&sqs.GetQueueUrlInput{ 158 QueueName: aws.String("test-cluster-queue"), 159 }).Return(&sqs.GetQueueUrlOutput{QueueUrl: aws.String("test-cluster-queue-url")}, nil) 160 m.DeleteQueue(&sqs.DeleteQueueInput{ 161 QueueUrl: aws.String("test-cluster-queue-url"), 162 }).Return(nil, errors.New("some error")) 163 }, 164 expectErr: true, 165 }, 166 } 167 168 for _, tc := range testCases { 169 t.Run(tc.name, func(t *testing.T) { 170 g := NewWithT(t) 171 sqsMock := mock_sqsiface.NewMockSQSAPI(mockCtrl) 172 clusterScope, err := setupCluster("test-cluster") 173 g.Expect(err).To(Not(HaveOccurred())) 174 175 tc.expect(sqsMock.EXPECT()) 176 s := NewService(clusterScope) 177 s.SQSClient = sqsMock 178 179 err = s.deleteSQSQueue() 180 181 if tc.expectErr { 182 g.Expect(err).NotTo(BeNil()) 183 } else { 184 g.Expect(err).To(BeNil()) 185 } 186 }) 187 } 188 } 189 190 func TestCreatePolicyForRule(t *testing.T) { 191 mockCtrl := gomock.NewController(t) 192 defer mockCtrl.Finish() 193 194 testCases := []struct { 195 name string 196 input *createPolicyForRuleInput 197 expect func(m *mock_sqsiface.MockSQSAPIMockRecorder) 198 expectErr bool 199 }{ 200 { 201 name: "creates a policy for a given rule", 202 input: &createPolicyForRuleInput{ 203 QueueArn: "test-cluster-queue-arn", 204 QueueURL: "test-cluster-queue-url", 205 RuleArn: "test-cluster-rule-arn", 206 }, 207 expect: func(m *mock_sqsiface.MockSQSAPIMockRecorder) { 208 buffer := new(bytes.Buffer) 209 _ = json.Compact(buffer, []byte(expectedPolicyJSON)) 210 attrs := make(map[string]string) 211 attrs[sqs.QueueAttributeNamePolicy] = buffer.String() 212 m.SetQueueAttributes(&sqs.SetQueueAttributesInput{ 213 QueueUrl: aws.String("test-cluster-queue-url"), 214 Attributes: aws.StringMap(attrs), 215 }).Return(nil, nil) 216 }, 217 expectErr: false, 218 }, 219 } 220 221 for _, tc := range testCases { 222 t.Run(tc.name, func(t *testing.T) { 223 g := NewWithT(t) 224 sqsMock := mock_sqsiface.NewMockSQSAPI(mockCtrl) 225 clusterScope, err := setupCluster("test-cluster") 226 g.Expect(err).To(Not(HaveOccurred())) 227 228 tc.expect(sqsMock.EXPECT()) 229 s := NewService(clusterScope) 230 s.SQSClient = sqsMock 231 232 err = s.createPolicyForRule(tc.input) 233 234 if tc.expectErr { 235 g.Expect(err).NotTo(BeNil()) 236 } else { 237 g.Expect(err).To(BeNil()) 238 } 239 }) 240 } 241 } 242 243 func TestGenerateQueueName(t *testing.T) { 244 testCases := []struct { 245 name string 246 clusterName string 247 expectedQueueName string 248 }{ 249 { 250 name: "unchanged when cluster name doesn't include a .", 251 clusterName: "test-cluster", 252 expectedQueueName: "test-cluster-queue", 253 }, 254 { 255 name: "replaces . with - in cluster name", 256 clusterName: "some.cluster.name", 257 expectedQueueName: "some-cluster-name-queue", 258 }, 259 } 260 261 for _, tc := range testCases { 262 g := NewWithT(t) 263 g.Expect(GenerateQueueName(tc.clusterName)).To(Equal(tc.expectedQueueName)) 264 } 265 } 266 267 const expectedPolicyJSON = `{ 268 "Version": "2012-10-17", 269 "Statement": [ 270 { 271 "Sid": "CAPAEvents_test-cluster-ec2-rule_test-cluster-queue", 272 "Principal": { 273 "Service": [ 274 "events.amazonaws.com" 275 ] 276 }, 277 "Effect": "Allow", 278 "Action": [ 279 "sqs:SendMessage" 280 ], 281 "Resource": [ 282 "test-cluster-queue-arn" 283 ], 284 "Condition": { 285 "ArnEquals": { 286 "aws:SourceArn": "test-cluster-rule-arn" 287 } 288 } 289 } 290 ], 291 "Id": "test-cluster-queue-arn" 292 }`