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  }`