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

4

8

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.

Korman answered 8/2, 2021 at 15:37 Comment(2)
aws.github.io/aws-sdk-go-v2/docs/configuring-sdk/endpointsTwelvemonth
Check your region. All the answers here were bizarre workarounds for the fact that my region was eu-west-1.Futch
M
0

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})
Mcsweeney answered 8/2, 2021 at 16:13 Comment(1)
At what point do you specify "local" here?Underrate
U
3

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...

Underrate answered 27/8, 2021 at 14:43 Comment(4)
Is this really still the best option?Futch
No idea mate. Haven't used it since posting thisUnderrate
So I found that if aws cli is accidentally configured then I needed to do this, but otherwise it was completely unnecessarily. Further, I could alter my program to use the correct region, then it just worked, without overriding the HTTPClient.Futch
Good to know! ThanksUnderrate
G
2

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.

Gifu answered 13/9, 2022 at 15:43 Comment(0)
M
0

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})
Mcsweeney answered 8/2, 2021 at 16:13 Comment(1)
At what point do you specify "local" here?Underrate
L
0

Here is an example for s3.

cfg, err := config.LoadDefaultConfig(context.Background())
if err != nil {
    return nil, err
}
localStackEndpoint := "http://localstack:4566"
s3Client := s3.NewFromConfig(
    cfg,
    func(o *s3.Options) {
        o.UsePathStyle = true
        o.BaseEndpoint = &localStackEndpoint
    },
)

Reference : LocalStack Docs

Lorant answered 10/8, 2024 at 21:6 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.