mirror of
https://github.com/nikoksr/notify.git
synced 2025-01-22 03:09:35 +02:00
feat(service): Add AWS SNS (#110)
Co-authored-by: Niko Köser <koeserniko@gmail.com>
This commit is contained in:
parent
7d85160b7a
commit
80bc1fa47d
3
go.mod
3
go.mod
@ -6,11 +6,13 @@ require (
|
||||
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f
|
||||
github.com/Rhymen/go-whatsapp v0.1.1
|
||||
github.com/RocketChat/Rocket.Chat.Go.SDK v0.0.0-20210506200512-3b3352a919f0
|
||||
github.com/antihax/optional v1.0.0 // indirect
|
||||
github.com/atc0005/go-teams-notify/v2 v2.6.0
|
||||
github.com/aws/aws-sdk-go-v2 v1.13.0
|
||||
github.com/aws/aws-sdk-go-v2/config v1.13.1
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.8.0
|
||||
github.com/aws/aws-sdk-go-v2/service/ses v1.12.0
|
||||
github.com/aws/aws-sdk-go-v2/service/sns v1.4.1
|
||||
github.com/blinkbean/dingtalk v0.0.0-20210905093040-7d935c0f7e19
|
||||
github.com/bwmarrin/discordgo v0.23.2
|
||||
github.com/cschomburg/go-pushbullet v0.0.0-20171206132031-67759df45fbb
|
||||
@ -32,7 +34,6 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/antihax/optional v1.0.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.10.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.2.0 // indirect
|
||||
|
4
go.sum
4
go.sum
@ -50,6 +50,7 @@ github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwc
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/atc0005/go-teams-notify/v2 v2.6.0 h1:YegKDWbjlatR0fP2yHsQYXzTcUGNJXhm1/OiCgbyysc=
|
||||
github.com/atc0005/go-teams-notify/v2 v2.6.0/go.mod h1:xo6GejLDHn3tWBA181F8LrllIL0xC1uRsRxq7YNXaaY=
|
||||
github.com/aws/aws-sdk-go-v2 v1.6.0/go.mod h1:tI4KhsR5VkzlUa2DZAdwx7wCAYGwkZZ1H31PYrBFx1w=
|
||||
github.com/aws/aws-sdk-go-v2 v1.13.0 h1:1XIXAfxsEmbhbj5ry3D3vX+6ZcUYvIqSm4CWWEuGZCA=
|
||||
github.com/aws/aws-sdk-go-v2 v1.13.0/go.mod h1:L6+ZpqHaLbAaxsqV0L4cvxZY7QupWJB4fhkf8LXvC7w=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.13.1 h1:yLv8bfNoT4r+UvUKQKqRtdnvuWGMK5a82l4ru9Jvnuo=
|
||||
@ -68,10 +69,13 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.7.0 h1:4QAOB3KrvI
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.7.0/go.mod h1:K/qPe6AP2TGYv4l6n7c88zh9jWBDf6nHhvg1fx/EWfU=
|
||||
github.com/aws/aws-sdk-go-v2/service/ses v1.12.0 h1:AsIuaTDMsg0bX5cfGNfU8uxUA1tAhBrojswetpD6PcY=
|
||||
github.com/aws/aws-sdk-go-v2/service/ses v1.12.0/go.mod h1:061vZ/X66UM49xth/ZZGvtJdHGgLh8FwgRvt+1YyhJI=
|
||||
github.com/aws/aws-sdk-go-v2/service/sns v1.4.1 h1:uc9t63SToTT6v/NG2UT3m+8DNpZF1noCSFbHk8dh9RE=
|
||||
github.com/aws/aws-sdk-go-v2/service/sns v1.4.1/go.mod h1:SyRNX444n2Vk3NAEEM0ewyS8qsTeAjig3HPjvlBuhlM=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.9.0 h1:1qLJeQGBmNQW3mBNzK2CFmrQNmoXWrscPqsrAaU1aTA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.9.0/go.mod h1:vCV4glupK3tR7pw7ks7Y4jYRL86VvxS+g5qk04YeWrU=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.14.0 h1:ksiDXhvNYg0D2/UFkLejsaz3LqpW5yjNQ8Nx9Sn2c0E=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.14.0/go.mod h1:u0xMJKDvvfocRjiozsoZglVNXRG19043xzp3r2ivLIk=
|
||||
github.com/aws/smithy-go v1.4.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
||||
github.com/aws/smithy-go v1.10.0 h1:gsoZQMNHnX+PaghNw4ynPsyGP7aUCqx5sY2dlPQsZ0w=
|
||||
github.com/aws/smithy-go v1.10.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
||||
github.com/blinkbean/dingtalk v0.0.0-20210905093040-7d935c0f7e19 h1:pamuM2sgLJLoMWfchc6y071z8ifalajU7btZmZNhoH4=
|
||||
|
79
service/amazonsns/amazon_sns.go
Normal file
79
service/amazonsns/amazon_sns.go
Normal file
@ -0,0 +1,79 @@
|
||||
package amazonsns
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/aws/aws-sdk-go-v2/credentials"
|
||||
"github.com/aws/aws-sdk-go-v2/service/sns"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// SNSSendMessageAPI Basic interface to send messages through SNS.
|
||||
type SNSSendMessageAPI interface {
|
||||
SendMessage(ctx context.Context,
|
||||
params *sns.PublishInput,
|
||||
optFns ...func(*sns.Options)) (*sns.PublishOutput, error)
|
||||
}
|
||||
|
||||
// SNSSendMessageClient Client specific for SNS using aws sdk v2.
|
||||
type SNSSendMessageClient struct {
|
||||
client *sns.Client
|
||||
}
|
||||
|
||||
// SendMessage Client specific for SNS using aws sdk v2.
|
||||
func (s SNSSendMessageClient) SendMessage(ctx context.Context,
|
||||
params *sns.PublishInput,
|
||||
optFns ...func(*sns.Options)) (*sns.PublishOutput, error) {
|
||||
return s.client.Publish(ctx, params, optFns...)
|
||||
}
|
||||
|
||||
// AmazonSNS Basic structure with SNS information
|
||||
type AmazonSNS struct {
|
||||
sendMessageClient SNSSendMessageAPI
|
||||
queueTopics []string
|
||||
}
|
||||
|
||||
// New creates a new AmazonSNS
|
||||
func New(accessKeyID, secretKey, region string) (*AmazonSNS, error) {
|
||||
credProvider := credentials.NewStaticCredentialsProvider(accessKeyID, secretKey, "")
|
||||
cfg, err := config.LoadDefaultConfig(
|
||||
context.Background(),
|
||||
config.WithCredentialsProvider(credProvider),
|
||||
config.WithRegion(region),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client := sns.NewFromConfig(cfg)
|
||||
return &AmazonSNS{
|
||||
sendMessageClient: SNSSendMessageClient{client: client},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// AddReceivers takes queue urls and adds them to the internal topics
|
||||
// list. The Send method will send a given message to all those
|
||||
// Topics.
|
||||
func (s *AmazonSNS) AddReceivers(queues ...string) {
|
||||
s.queueTopics = append(s.queueTopics, queues...)
|
||||
}
|
||||
|
||||
// Send message to everyone on all topics
|
||||
func (s AmazonSNS) Send(ctx context.Context, subject, message string) error {
|
||||
// For each topic
|
||||
for _, topic := range s.queueTopics {
|
||||
// Create new input with subject, message and the specific topic
|
||||
input := &sns.PublishInput{
|
||||
Subject: aws.String(subject),
|
||||
Message: aws.String(message),
|
||||
TopicArn: aws.String(topic),
|
||||
}
|
||||
// Send the message
|
||||
_, err := s.sendMessageClient.SendMessage(ctx, input)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to send message using Amazon SNS to ARN TOPIC '%s'", topic)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
117
service/amazonsns/amazon_sns_test.go
Normal file
117
service/amazonsns/amazon_sns_test.go
Normal file
@ -0,0 +1,117 @@
|
||||
package amazonsns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/sns"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
type SNSSendMessageMock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (m *SNSSendMessageMock) SendMessage(ctx context.Context,
|
||||
params *sns.PublishInput,
|
||||
optFns ...func(*sns.Options)) (*sns.PublishOutput, error) {
|
||||
args := m.Called(ctx, params, optFns)
|
||||
return args.Get(0).(*sns.PublishOutput), args.Error(1)
|
||||
}
|
||||
|
||||
func TestAddReceivers(t *testing.T) {
|
||||
amazonSNS, err := New("", "", "")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
amazonSNS.AddReceivers("One topic")
|
||||
}
|
||||
|
||||
func TestSendMessageWithNoTopicsConfigured(t *testing.T) {
|
||||
mockSns := new(SNSSendMessageMock)
|
||||
amazonSNS := AmazonSNS{
|
||||
sendMessageClient: mockSns,
|
||||
}
|
||||
|
||||
err := amazonSNS.Send(context.Background(), "Subject", "Message")
|
||||
assert.Nil(t, err)
|
||||
mockSns.AssertNotCalled(t, "SendMessage", mock.Anything, mock.Anything, mock.Anything)
|
||||
}
|
||||
|
||||
func TestSendMessageWithSucessAndOneTopicCOnfigured(t *testing.T) {
|
||||
mockSns := new(SNSSendMessageMock)
|
||||
output := sns.PublishOutput{}
|
||||
mockSns.On("SendMessage", mock.Anything, mock.Anything, mock.Anything).
|
||||
Return(&output, nil)
|
||||
|
||||
amazonSNS := AmazonSNS{
|
||||
sendMessageClient: mockSns,
|
||||
}
|
||||
amazonSNS.AddReceivers("arn:aws:sns:region:number:topicname")
|
||||
err := amazonSNS.Send(context.Background(), "Subject", "Message")
|
||||
assert.Nil(t, err)
|
||||
|
||||
mockSns.AssertExpectations(t)
|
||||
assert.Equal(t, 1, len(mockSns.Calls))
|
||||
}
|
||||
|
||||
func TestSendMessageWithSucessAndTwoTopicCOnfigured(t *testing.T) {
|
||||
mockSns := new(SNSSendMessageMock)
|
||||
output := sns.PublishOutput{}
|
||||
mockSns.On("SendMessage", mock.Anything, mock.Anything, mock.Anything).
|
||||
Return(&output, nil)
|
||||
|
||||
amazonSNS := AmazonSNS{
|
||||
sendMessageClient: mockSns,
|
||||
}
|
||||
|
||||
amazonSNS.AddReceivers("arn:aws:sns:region:number:topicname1",
|
||||
"arn:aws:sns:region:number:topicname1")
|
||||
|
||||
err := amazonSNS.Send(context.Background(), "Subject", "Message")
|
||||
assert.Nil(t, err)
|
||||
|
||||
mockSns.AssertExpectations(t)
|
||||
assert.Equal(t, 2, len(mockSns.Calls))
|
||||
}
|
||||
|
||||
func TestSendMessageWithErrorAndOneQueueConfiguredShouldReturnError(t *testing.T) {
|
||||
mockSns := new(SNSSendMessageMock)
|
||||
output := sns.PublishOutput{}
|
||||
mockSns.On("SendMessage", mock.Anything, mock.Anything, mock.Anything).
|
||||
Return(&output, errors.New("Error on SNS"))
|
||||
|
||||
amazonSNS := AmazonSNS{
|
||||
sendMessageClient: mockSns,
|
||||
}
|
||||
|
||||
amazonSNS.AddReceivers("arn:aws:sns:region:number:topicname")
|
||||
err := amazonSNS.Send(context.Background(), "Subject", "Message")
|
||||
|
||||
assert.NotNil(t, err)
|
||||
|
||||
mockSns.AssertExpectations(t)
|
||||
assert.Equal(t, 1, len(mockSns.Calls))
|
||||
}
|
||||
|
||||
func TestSendMessageWithErrorAndTwoQueueConfiguredShouldReturnErrorOnFirst(t *testing.T) {
|
||||
mockSns := new(SNSSendMessageMock)
|
||||
output := sns.PublishOutput{}
|
||||
mockSns.On("SendMessage", mock.Anything, mock.Anything, mock.Anything).
|
||||
Return(&output, errors.New("Error on SNS"))
|
||||
|
||||
amazonSNS := AmazonSNS{
|
||||
sendMessageClient: mockSns,
|
||||
}
|
||||
|
||||
amazonSNS.AddReceivers(
|
||||
"arn:aws:sns:region:number:topicname1",
|
||||
"arn:aws:sns:region:number:topicname1")
|
||||
|
||||
err := amazonSNS.Send(context.Background(), "Subject", "Message")
|
||||
assert.NotNil(t, err)
|
||||
mockSns.AssertExpectations(t)
|
||||
assert.Equal(t, 1, len(mockSns.Calls))
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user