I am trying to test locally a lambda function that is listing buckets on a S3 bucket.
To have a local S3 bucket for my test, I use localstack:
docker run --rm -it -p 4566:4566 -p 4510-4559:4510-4559 localstack/localstack
I can then create a bucket (it works):
aws s3api --endpoint-url=http://localhost:4566 --region us-east-1 create-bucket --bucket images
Then I have a lambda that tries to connect to S3 and list the buckets:
package s3
import (
"context"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
awsS3 "github.com/aws/aws-sdk-go-v2/service/s3"
"fmt"
"log"
)
type S3ListBucketsAPI interface {
ListBuckets(ctx context.Context,
params *awsS3.ListBucketsInput,
optFns ...func(*awsS3.Options)) (*awsS3.ListBucketsOutput, error)
}
func GetAllBuckets(c context.Context, api S3ListBucketsAPI, input *awsS3.ListBucketsInput) (*awsS3.ListBucketsOutput, error) {
return api.ListBuckets(c, input)
}
func New(bucketName string) () {
awsEndpoint := "http://localhost:4566"
awsRegion := "us-east-1"
customResolver := aws.EndpointResolverFunc(func(service, region string) (aws.Endpoint, error) {
if awsEndpoint != "" {
return aws.Endpoint{
PartitionID: "aws",
URL: awsEndpoint,
SigningRegion: awsRegion,
HostnameImmutable: true,
}, nil
}
return aws.Endpoint{}, &aws.EndpointNotFoundError{}
})
cfg, err := config.LoadDefaultConfig(context.TODO(),
config.WithRegion(awsRegion),
config.WithEndpointResolver(customResolver),
)
if err != nil {
log.Fatalf("Cannot load the AWS configs: %s", err)
}
client := awsS3.NewFromConfig(cfg)
input := &awsS3.ListBucketsInput{}
result, err := GetAllBuckets(context.TODO(), client, input)
if err != nil {
fmt.Println(err)
}
for _, bucket := range result.Buckets {
fmt.Println(*bucket.Name + ": " + bucket.CreationDate.Format("2006-01-02 15:04:05 Monday"))
}
}
To test my lambda locally I use SAM. Here is the template:
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: AdBannerLambda
Resources:
BucketListLambda:
Type: AWS::Serverless::Function
Properties:
Handler: bin/bucket-list-lambda
Runtime: go1.x
Timeout: 100
Policies:
- S3FullAccessPolicy
When I execute the lambda:
sam local invoke AdBannerLambda -e test_data/payload.json
I have this error:
START RequestId: 7c9da60f-9a68-476b-bcd8-c24da422e80c Version: $LATEST
Got an error retrieving buckets:
operation error S3: ListBuckets, exceeded maximum number of attempts, 3, https response error StatusCode: 0, RequestID: , HostID: , request send failed, Get "http://localhost:4566/": dial tcp 127.0.0.1:4566: connect: connection refused
2022/07/28 14:54:10 <nil>
28 Jul 2022 14:54:10,979 [ERROR] (rapid) Init failed error=Runtime exited with error: exit status 1 InvokeID=
END RequestId: 5319d88f-ea30-4a61-adb6-e9ab4a83c17e
My lambda cannot reach the S3 bucket in my localstack docker even though the same code in a simple go file (not a lambda) can perform actions on S3. Any idea where the problem comes from?