From 8c1aa7fedc3e01dd71a537f7e149d3052b2ce107 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Tue, 22 Aug 2023 20:31:40 -0400 Subject: [PATCH] [sqs] Initial boilerplate --- main.go | 13 ++++++ services/kms/itest/kms_test.go | 2 +- services/sqs/errors.go | 17 ++++++++ services/sqs/http.go | 13 ++++++ services/sqs/sqs.go | 72 ++++++++++++++++++++++++++++++++++ services/sqs/types.go | 11 ++++++ 6 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 services/sqs/errors.go create mode 100755 services/sqs/http.go create mode 100755 services/sqs/sqs.go create mode 100755 services/sqs/types.go diff --git a/main.go b/main.go index d6dc4da..a563172 100755 --- a/main.go +++ b/main.go @@ -17,6 +17,7 @@ import ( "aws-in-a-box/services/kinesis" "aws-in-a-box/services/kms" "aws-in-a-box/services/s3" + "aws-in-a-box/services/sqs" ) func versionString() string { @@ -63,6 +64,8 @@ func main() { enableS3 := flag.Bool("experimental_enableS3", true, "Enable S3 service") s3InitialBuckets := flag.String("s3InitialBuckets", "", "Buckets to create at startup. Example: bucket1,bucket2,bucket3") + enableSQS := flag.Bool("enableSQS", true, "Enable SQS service") + flag.Parse() var level slog.Level @@ -132,6 +135,16 @@ func main() { logger.Info("Enabled DynamoDB (EXPERIMENTAL!!!)") } + if *enableSQS { + logger := logger.With("service", "dynamodb") + s := sqs.New(sqs.Options{ + Logger: logger, + ArnGenerator: arnGenerator, + }) + s.RegisterHTTPHandlers(logger, methodRegistry) + logger.Info("Enabled SQS") + } + handlerChain := []server.HandlerFunc{server.HandlerFuncFromRegistry(logger, methodRegistry)} if *enableS3 { diff --git a/services/kms/itest/kms_test.go b/services/kms/itest/kms_test.go index 31f3b5a..4a431c0 100644 --- a/services/kms/itest/kms_test.go +++ b/services/kms/itest/kms_test.go @@ -1,4 +1,4 @@ -package kms +package itest import ( "context" diff --git a/services/sqs/errors.go b/services/sqs/errors.go new file mode 100644 index 0000000..5e79712 --- /dev/null +++ b/services/sqs/errors.go @@ -0,0 +1,17 @@ +package sqs + +import "aws-in-a-box/awserrors" + +func XXXTodoException(message string) *awserrors.Error { + return &awserrors.Error{ + Code: 400, + Body: awserrors.ErrorBody{ + Type: "XXXTodoException", + Message: message, + }, + } +} + +func QueueNameExists(message string) *awserrors.Error { + return awserrors.Generate400Exception("QueueNameExists", message) +} diff --git a/services/sqs/http.go b/services/sqs/http.go new file mode 100755 index 0000000..5d9814f --- /dev/null +++ b/services/sqs/http.go @@ -0,0 +1,13 @@ +package sqs + +import ( + "golang.org/x/exp/slog" + + "aws-in-a-box/http" +) + +const service = "TODO" + +func (s *SQS) RegisterHTTPHandlers(logger *slog.Logger, methodRegistry http.Registry) { + http.Register(logger, methodRegistry, service, "CreateQueue", s.CreateQueue) +} diff --git a/services/sqs/sqs.go b/services/sqs/sqs.go new file mode 100755 index 0000000..207a1f3 --- /dev/null +++ b/services/sqs/sqs.go @@ -0,0 +1,72 @@ +package sqs + +import ( + "sync" + + "golang.org/x/exp/maps" + "golang.org/x/exp/slog" + + "aws-in-a-box/arn" + "aws-in-a-box/awserrors" +) + +type Queue struct { + // Immutable + CreationTimestamp int64 + Attributes map[string]string + URL string + + // Mutable + Messages []byte + Tags map[string]string +} + +type SQS struct { + logger *slog.Logger + arnGenerator arn.Generator + + mu sync.Mutex + queues map[string]Queue + tags map[string]string +} + +type Options struct { + Logger *slog.Logger + ArnGenerator arn.Generator +} + +func New(options Options) *SQS { + if options.Logger == nil { + options.Logger = slog.Default() + } + + s := &SQS{ + logger: options.Logger, + arnGenerator: options.ArnGenerator, + } + + return s +} + +// https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_CreateQueue.html +func (s *SQS) CreateQueue(input CreateQueueInput) (*CreateQueueOutput, *awserrors.Error) { + s.mu.Lock() + defer s.mu.Unlock() + + if queue, ok := s.queues[input.QueueName]; ok { + if maps.Equal(queue.Attributes, input.Attributes) { + return &CreateQueueOutput{ + QueueUrl: queue.URL, + }, nil + } + return nil, QueueNameExists("") + } + + s.queues[input.QueueName] = Queue{ + Attributes: input.Attributes, + Tags: input.Tags, + URL: "TODO", + } + + return nil, nil +} diff --git a/services/sqs/types.go b/services/sqs/types.go new file mode 100755 index 0000000..d0223d9 --- /dev/null +++ b/services/sqs/types.go @@ -0,0 +1,11 @@ +package sqs + +type CreateQueueInput struct { + Attributes map[string]string + QueueName string + Tags map[string]string `json:"tags"` +} + +type CreateQueueOutput struct { + QueueUrl string +}