Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AWS SDK clients for CFN Custom Resource support #1805

Merged
merged 1 commit into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions provider/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,19 @@ go 1.21

require (
github.com/apparentlymart/go-cidr v1.1.0
github.com/aws/aws-lambda-go v1.47.0
github.com/aws/aws-sdk-go v1.50.36
github.com/aws/aws-sdk-go-v2 v1.26.1
github.com/aws/aws-sdk-go-v2 v1.32.3
github.com/aws/aws-sdk-go-v2/config v1.27.11
github.com/aws/aws-sdk-go-v2/credentials v1.17.11
github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.15.7
github.com/aws/aws-sdk-go-v2/service/cloudformation v1.43.0
github.com/aws/aws-sdk-go-v2/service/ec2 v1.146.0
github.com/aws/aws-sdk-go-v2/service/lambda v1.64.1
github.com/aws/aws-sdk-go-v2/service/s3 v1.66.2
github.com/aws/aws-sdk-go-v2/service/ssm v1.49.2
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6
github.com/aws/smithy-go v1.20.2
github.com/aws/smithy-go v1.22.0
github.com/blang/semver v3.5.1+incompatible
github.com/goccy/go-yaml v1.9.5
github.com/golang/glog v1.2.0
Expand Down Expand Up @@ -58,12 +61,16 @@ require (
github.com/agext/levenshtein v1.2.3 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.6 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.22 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.3 // indirect
github.com/aws/aws-sdk-go-v2/service/kms v1.30.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 // indirect
Expand Down
48 changes: 26 additions & 22 deletions provider/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,14 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aws/aws-lambda-go v1.47.0 h1:0H8s0vumYx/YKs4sE7YM0ktwL2eWse+kfopsRI1sXVI=
github.com/aws/aws-lambda-go v1.47.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A=
github.com/aws/aws-sdk-go v1.50.36 h1:PjWXHwZPuTLMR1NIb8nEjLucZBMzmf84TLoLbD8BZqk=
github.com/aws/aws-sdk-go v1.50.36/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA=
github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg=
github.com/aws/aws-sdk-go-v2 v1.32.3 h1:T0dRlFBKcdaUPGNtkBSwHZxrtis8CQU17UpNBZYd0wk=
github.com/aws/aws-sdk-go-v2 v1.32.3/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.6 h1:pT3hpW0cOHRJx8Y0DfJUEQuqPild8jRGmSFmBgvydr0=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.6/go.mod h1:j/I2++U0xX+cr44QjHay4Cvxj6FUbnxrgmqN3H1jTZA=
github.com/aws/aws-sdk-go-v2/config v1.27.11 h1:f47rANd2LQEYHda2ddSCKYId18/8BhSRM4BULGmfgNA=
github.com/aws/aws-sdk-go-v2/config v1.27.11/go.mod h1:SMsV78RIOYdve1vf36z8LmnszlRWkwMQtomCAI0/mIE=
github.com/aws/aws-sdk-go-v2/credentials v1.17.11 h1:YuIB1dJNf1Re822rriUOTxopaHHvIq0l/pX3fwO+Tzs=
Expand All @@ -105,14 +107,14 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYh
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.15 h1:7Zwtt/lP3KNRkeZre7soMELMGNoBrutx8nobg1jKWmo=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.15/go.mod h1:436h2adoHb57yd+8W+gYPrrA9U/R/SuAuOO42Ushzhw=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 h1:Jw50LwEkVjuVzE1NzkhNKkBf9cRN7MtE1F/b2cOKTUM=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22/go.mod h1:Y/SmAyPcOTmpeVaWSzSKiILfXTVJwrGmYZhcRbhWuEY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 h1:981MHwBaRZM7+9QSR6XamDzF/o7ouUGxFzr+nVSIhrs=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22/go.mod h1:1RA1+aBEfn+CAB/Mh0MB6LsdCYCnjZm7tKXtnk499ZQ=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5 h1:81KE7vaZzrl7yHBYHVEzYB8sypz11NMOZ40YlWvPxsU=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5/go.mod h1:LIt2rg7Mcgn09Ygbdh/RdIm0rQ+3BNkbP1gyVMFtRK0=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.22 h1:yV+hCAHZZYJQcwAaszoBNwLbPItHvApxT0kVIw6jRgs=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.22/go.mod h1:kbR1TL8llqB1eGnVbybcA4/wgScxdylOdyAd51yxPdw=
github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.15.7 h1:8sBfx7QkDZ6dgfUNXWHWRc6Eax7WOI3Slgj6OKDHKTI=
github.com/aws/aws-sdk-go-v2/service/cloudcontrol v1.15.7/go.mod h1:P1EMD13hrBE2KUw030w482Eyk2NmOFIvGqmgNi4XRDc=
github.com/aws/aws-sdk-go-v2/service/cloudformation v1.43.0 h1:fusTelL7ZIvR51E+xwc/HVUlWGhkWFlS+dtYrynVBq4=
Expand All @@ -121,18 +123,20 @@ github.com/aws/aws-sdk-go-v2/service/ec2 v1.146.0 h1:d6pYx/CKADORpxqBINY7DuD4V1f
github.com/aws/aws-sdk-go-v2/service/ec2 v1.146.0/go.mod h1:hIsHE0PaWAQakLCshKS7VKWMGXaqrAFp4m95s2W9E6c=
github.com/aws/aws-sdk-go-v2/service/iam v1.31.4 h1:eVm30ZIDv//r6Aogat9I88b5YX1xASSLcEDqHYRPVl0=
github.com/aws/aws-sdk-go-v2/service/iam v1.31.4/go.mod h1:aXWImQV0uTW35LM0A/T4wEg6R1/ReXUu4SM6/lUHYK0=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7 h1:ZMeFZ5yk+Ek+jNr1+uwCd2tG89t6oTS5yVWpa6yy2es=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7/go.mod h1:mxV05U+4JiHqIpGqqYXOHLPKUC6bDXC44bsUhNjOEwY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5 h1:f9RyWNtS8oH7cZlbn+/JNPpjUk5+5fLd5lM9M0i49Ys=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5/go.mod h1:h5CoMZV2VF297/VLhRhO1WF+XYWOzXo+4HsObA4HjBQ=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 h1:TToQNkvGguu209puTojY/ozlqy2d/SFNcoLIqTFi42g=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0/go.mod h1:0jp+ltwkf+SwG2fm/PKo8t4y8pJSgOCO4D8Lz3k0aHQ=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.3 h1:kT6BcZsmMtNkP/iYMcRG+mIEA/IbeiUimXtGmqF39y0=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.3/go.mod h1:Z8uGua2k4PPaGOYn66pK02rhMrot3Xk3tpBuUFPomZU=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3 h1:qcxX0JYlgWH3hpPUnd6U0ikcl6LLA9sLkXE2w1fpMvY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3/go.mod h1:cLSNEmI45soc+Ef8K/L+8sEA3A3pYFEYf5B5UI+6bH4=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.3 h1:ZC7Y/XgKUxwqcdhO5LE8P6oGP1eh6xlQReWNKfhvJno=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.3/go.mod h1:WqfO7M9l9yUAw0HcHaikwRd/H6gzYdz7vjejCA5e2oY=
github.com/aws/aws-sdk-go-v2/service/kms v1.30.1 h1:SBn4I0fJXF9FYOVRSVMWuhvEKoAHDikjGpS3wlmw5DE=
github.com/aws/aws-sdk-go-v2/service/kms v1.30.1/go.mod h1:2snWQJQUKsbN66vAawJuOGX7dr37pfOq9hb0tZDGIqQ=
github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1 h1:6cnno47Me9bRykw9AEv9zkXE+5or7jz8TsskTTccbgc=
github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1/go.mod h1:qmdkIIAC+GCLASF7R2whgNrJADz0QZPX+Seiw/i4S3o=
github.com/aws/aws-sdk-go-v2/service/lambda v1.64.1 h1:0njE+T0N80Kl2bPfK85Lnz1+dD/xskJduTqfRyREpvY=
github.com/aws/aws-sdk-go-v2/service/lambda v1.64.1/go.mod h1:hr+VpAzvznKumy8q8TFEJfx3Xx+zfK2gDrrWjBqLLPw=
github.com/aws/aws-sdk-go-v2/service/s3 v1.66.2 h1:p9TNFL8bFUMd+38YIpTAXpoxyz0MxC7FlbFEH4P4E1U=
github.com/aws/aws-sdk-go-v2/service/s3 v1.66.2/go.mod h1:fNjyo0Coen9QTwQLWeV6WO2Nytwiu+cCcWaTdKCAqqE=
github.com/aws/aws-sdk-go-v2/service/ssm v1.49.2 h1:JcvYXGYiu7ME17irbW6kvWno2LG5i29Ci0UZyWX0IOs=
github.com/aws/aws-sdk-go-v2/service/ssm v1.49.2/go.mod h1:loBAHYxz7JyucJvq4xuW9vunu8iCzjNYfSrQg2QEczA=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.5 h1:vN8hEbpRnL7+Hopy9dzmRle1xmDc7o8tmY0klsr175w=
Expand All @@ -141,8 +145,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 h1:Jux+gDDyi1Lruk+KHF91tK2K
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 h1:cwIxeBttqPN3qkaAjcEcsh8NYr8n2HZPkcKgPAi1phU=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw=
github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=
github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM=
github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
Expand Down
93 changes: 93 additions & 0 deletions provider/pkg/client/lambda.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright 2016-2024, Pulumi Corporation.

package client

import (
"context"
"fmt"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/lambda"
lambdaTypes "github.com/aws/aws-sdk-go-v2/service/lambda/types"
"github.com/pkg/errors"
)

const DefaultFunctionActivationTimeout = 5 * time.Minute

//go:generate mockgen -package client -source lambda.go -destination mock_lambda.go LambdaClient,LambdaApi
type LambdaClient interface {
// InvokeAsync invokes the given Lambda function with the 'Event' invocation type. This means that the function
// will be invoked asynchronously and no response will be returned. If the function is not ready to be invoked yet,
// this method will wait for the function to become active before invoking it.
InvokeAsync(ctx context.Context, functionName string, payload []byte) error
}

type LambdaApi interface {
Invoke(ctx context.Context, params *lambda.InvokeInput, optFns ...func(*lambda.Options)) (*lambda.InvokeOutput, error)
GetFunction(context.Context, *lambda.GetFunctionInput, ...func(*lambda.Options)) (*lambda.GetFunctionOutput, error)
}

type lambdaClientImpl struct {
api LambdaApi
functionActivationTimeout time.Duration
}

func NewLambdaClient(api LambdaApi) LambdaClient {
return &lambdaClientImpl{
api: api,
functionActivationTimeout: DefaultFunctionActivationTimeout,
}
}

func (c *lambdaClientImpl) InvokeAsync(ctx context.Context, functionName string, payload []byte) error {
input := lambda.InvokeInput{
FunctionName: aws.String(functionName),
Payload: payload,
// async invocation
InvocationType: lambdaTypes.InvocationTypeEvent,
}

// fire off an initial invoke. If the function is not ready, we need to wait for it to become ready.
// this initial invoke will trigger the AWS Lambda service to start the function transition process.
invokeResp, err := c.api.Invoke(ctx, &input)

if err != nil {
// Lambda functions can be in a state where they are not ready to be invoked yet.
// If we get this error, we need to wait for the function to become active
var notReadyErr *lambdaTypes.ResourceNotReadyException
if errors.As(err, &notReadyErr) {
err := c.waitForFunctionActive(ctx, functionName)
if err != nil {
return fmt.Errorf("failed to wait for function to become active: %w", err)
}
invokeResp, err = c.api.Invoke(ctx, &input)
if err != nil {
return err
}
} else {
return err
}
}

if invokeResp.StatusCode != 202 {
return fmt.Errorf("lambda invocation failed with status code %d", invokeResp.StatusCode)
}

return nil
}

// waitForFunctionActive waits for the function to be in the active state. If the function is not ready
// after 5 minutes, it will return an error.
func (c *lambdaClientImpl) waitForFunctionActive(ctx context.Context, functionName string) error {
err := lambda.NewFunctionActiveV2Waiter(c.api, func(o *lambda.FunctionActiveV2WaiterOptions) {
// We already aggressively retry SDK errors with plenty retry attempts and
// throttling exceptions will be taken care of by the SDK
o.MinDelay = time.Second
o.MaxDelay = 5 * time.Second
}).Wait(ctx, &lambda.GetFunctionInput{
FunctionName: aws.String(functionName),
}, c.functionActivationTimeout)

return err
}
150 changes: 150 additions & 0 deletions provider/pkg/client/lambda_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package client

import (
"context"
"testing"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/lambda"
lambdaTypes "github.com/aws/aws-sdk-go-v2/service/lambda/types"
"github.com/stretchr/testify/assert"
gomock "go.uber.org/mock/gomock"
)

func lambdaSetup(t *testing.T) (*gomock.Controller, *lambdaClientImpl, *MockLambdaApi) {
ctrl := gomock.NewController(t)
mockLambdaApi := NewMockLambdaApi(ctrl)
client := &lambdaClientImpl{
api: mockLambdaApi,
functionActivationTimeout: 2 * time.Second,
}
return ctrl, client, mockLambdaApi
}

func TestInvokeAsync_SuccessfulInvocation(t *testing.T) {
t.Parallel()
ctrl, client, mockLambdaApi := lambdaSetup(t)
defer ctrl.Finish()

ctx := context.Background()
functionName := "test-function"
payload := []byte(`{"key": "value"}`)

mockLambdaApi.EXPECT().Invoke(ctx, gomock.Any()).Return(&lambda.InvokeOutput{
StatusCode: 202,
}, nil)

err := client.InvokeAsync(ctx, functionName, payload)
assert.NoError(t, err)
}

func TestInvokeAsync_FunctionNotReadyInitiallyButBecomesReady(t *testing.T) {
t.Parallel()
ctrl, client, mockLambdaApi := lambdaSetup(t)
defer ctrl.Finish()

ctx := context.Background()
functionName := "test-function"
payload := []byte(`{"key": "value"}`)

mockLambdaApi.EXPECT().Invoke(ctx, gomock.Any()).Return(nil, &lambdaTypes.ResourceNotReadyException{})

mockLambdaApi.EXPECT().GetFunction(gomock.Any(), &lambda.GetFunctionInput{
FunctionName: aws.String(functionName),
}, gomock.Any()).Return(&lambda.GetFunctionOutput{
Configuration: &lambdaTypes.FunctionConfiguration{
State: lambdaTypes.StateInactive,
},
}, nil)
mockLambdaApi.EXPECT().GetFunction(gomock.Any(), &lambda.GetFunctionInput{
FunctionName: aws.String(functionName),
}, gomock.Any()).Return(&lambda.GetFunctionOutput{
Configuration: &lambdaTypes.FunctionConfiguration{
State: lambdaTypes.StateActive,
},
}, nil)

mockLambdaApi.EXPECT().Invoke(ctx, gomock.Any()).Return(&lambda.InvokeOutput{
StatusCode: 202,
}, nil)

err := client.InvokeAsync(ctx, functionName, payload)
assert.NoError(t, err)
}

func TestInvokeAsync_FunctionNotReadyAndFailsToBecomeReady(t *testing.T) {
t.Parallel()
ctrl, client, mockLambdaApi := lambdaSetup(t)
defer ctrl.Finish()

ctx := context.Background()
functionName := "test-function"
payload := []byte(`{"key": "value"}`)

mockLambdaApi.EXPECT().Invoke(ctx, gomock.Any()).Return(nil, &lambdaTypes.ResourceNotReadyException{})

mockLambdaApi.EXPECT().GetFunction(gomock.Any(), &lambda.GetFunctionInput{
FunctionName: aws.String(functionName),
}, gomock.Any()).Return(&lambda.GetFunctionOutput{
Configuration: &lambdaTypes.FunctionConfiguration{
State: lambdaTypes.StateInactive,
},
}, nil).AnyTimes()

err := client.InvokeAsync(ctx, functionName, payload)
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to wait for function to become active")
}

func TestInvokeAsync_InvocationFailsWithNon202StatusCode(t *testing.T) {
t.Parallel()
ctrl, client, mockLambdaApi := lambdaSetup(t)
defer ctrl.Finish()

ctx := context.Background()
functionName := "test-function"
payload := []byte(`{"key": "value"}`)

mockLambdaApi.EXPECT().Invoke(ctx, gomock.Any()).Return(&lambda.InvokeOutput{
StatusCode: 400,
}, nil)

err := client.InvokeAsync(ctx, functionName, payload)
assert.Error(t, err)
assert.Contains(t, err.Error(), "lambda invocation failed with status code 400")
}

func TestInvokeAsync_FunctionNotReadyInitiallyButBecomesReadyAndThenFails(t *testing.T) {
t.Parallel()
ctrl, client, mockLambdaApi := lambdaSetup(t)
defer ctrl.Finish()

ctx := context.Background()
functionName := "test-function"
payload := []byte(`{"key": "value"}`)

mockLambdaApi.EXPECT().Invoke(ctx, gomock.Any()).Return(nil, &lambdaTypes.ResourceNotReadyException{})
mockLambdaApi.EXPECT().Invoke(ctx, gomock.Any()).Return(&lambda.InvokeOutput{
StatusCode: 400,
}, nil)

mockLambdaApi.EXPECT().GetFunction(gomock.Any(), &lambda.GetFunctionInput{
FunctionName: aws.String(functionName),
}, gomock.Any()).Return(&lambda.GetFunctionOutput{
Configuration: &lambdaTypes.FunctionConfiguration{
State: lambdaTypes.StateInactive,
},
}, nil)
mockLambdaApi.EXPECT().GetFunction(gomock.Any(), &lambda.GetFunctionInput{
FunctionName: aws.String(functionName),
}, gomock.Any()).Return(&lambda.GetFunctionOutput{
Configuration: &lambdaTypes.FunctionConfiguration{
State: lambdaTypes.StateActive,
},
}, nil)

err := client.InvokeAsync(ctx, functionName, payload)
assert.Error(t, err)
assert.Contains(t, err.Error(), "lambda invocation failed with status code 400")
}
Loading
Loading