How do I use aws-sdk-go-v2 with localstack?

Viewed 1597

I'm trying to migrate from aws-sdk-go to aws-sdk-go-v2. But, I am using localstack locally to mimic some aws services such as sqs and s3. I'm not sure how to configure the new sdk to use the localstack endpoint instead of the real one.

For example, in the v1 SDK I can point it to localstack by setting the endpoint here:

session.Must(session.NewSession(&aws.Config{
    Region:   aws.String("us-east-1"),
    Endpoint: aws.String("http://localstack:4566"), 
}))

But, how do I do this in the v2 SDK? I think I need to set some param in the config but I dont see any option to specify the endpoint.

3 Answers

So if you go trudging through the python code, principally this, you'll see:

https://github.com/localstack/localstack/blob/25ba1de8a8841af27feab54b8d55c80ac46349e2/localstack/services/edge.py#L115

I then needed to overwrite the authorization header, when using the v2 aws golang sdk in order to add the correct structure.

I picked the structure up from running the aws cli tool and trace logging the localstack docker container:

'Authorization': 'AWS4-HMAC-SHA256 Credential=AKIAR2X5NRNSRTCOJHCI/20210827/eu-west-1/sns/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=c69672d38631752ede15d90e7047a5183ebf3707a228decf6ec26e97fdbd02aa',

In go I then needed to overwrite the http client to add that header in:

type s struct {
    cl http.Client
}

func (s s) Do(r *http.Request) (*http.Response, error) {
    r.Header.Add("authorization", "AWS4-HMAC-SHA256 Credential=AKIAR2X5NRNSRTCOJHCI/20210827/eu-west-1/sns/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=33fa777a3bb1241f30742419b8fab81945aa219050da6e29b34db16053661000")
    return s.cl.Do(r)
}

func NewSNS(endpoint, topicARN string) (awsPubSub, error) {
    cfg := aws.Config{
        EndpointResolver: aws.EndpointResolverFunc(func(service, region string) (aws.Endpoint, error) {
            return aws.Endpoint{
                PartitionID:       "aws",
                URL:               "http://localhost:4566",
                SigningRegion:     "eu-west-1",
                HostnameImmutable: true,
                // Source:        aws.EndpointSourceCustom,
            }, nil
        }),
        HTTPClient: s{http.Client{}},
    }

....

It was very time consuming and painful and I'd love to know a better way, but this works for the time being...

It depends from the service that you use.

In order to initialize a Glue client:

cfg, err := config.LoadDefaultConfig(context.Background())
if err != nil {
    panic(err)
}
glueConnection := glue.New(glue.Options{Credentials: cfg.Credentials, Region: cfg.Region})

The equivalent of your code in the SDK v2 is:

    cfg, err := config.LoadDefaultConfig(
    ctx,
    config.WithRegion("us-east-1"),
    config.WithEndpointResolverWithOptions(aws.EndpointResolverWithOptionsFunc(
        func(service, region string, options ...interface{}) (aws.Endpoint, error) {
            return aws.Endpoint{URL: "http://localhost:4566"}, nil
        }),
    ),
)

Using LoadDefaultConfig you will not need to specify the region if you already set it up on the AWS config. You can read more on the AWS SDK v2 docs.

You can find the above example in the package docs.

Related