Summary
I'm making aws lambda
function by AWS SAM
.
This function needs database, so I choose DynamoDB
.
Now I'm setting local environment for AWS SAM
and DynamoDB
.
It seems that I success to set local DynamoDB
, but it fails to connect when running local aws sam
function.
failed to make Query API call, ResourceNotFoundException: Cannot do operations on a non-existent table
I want to know how to solve this issue.
tried
I created local table and checked test data is inserted.
❯ aws dynamodb create-table --cli-input-json file://test/positive-line-bot_table.json --endpoint-url http://localhost:8000
TABLEDESCRIPTION 1578904757.61 0 arn:aws:dynamodb:ddblocal:000000000000:table/PositiveLineBotTable PositiveLineBotTable 0 ACTIVE
ATTRIBUTEDEFINITIONS Id N
BILLINGMODESUMMARY PROVISIONED 0.0
KEYSCHEMA Id HASH
PROVISIONEDTHROUGHPUT 0.0 0.0 0 5 5
❯ aws dynamodb batch-write-item --request-items file://test/positive-line-bot_table_data.json --endpoint-url http://localhost:8000
❯ aws dynamodb list-tables --endpoint-url http://localhost:8000
TABLENAMES PositiveLineBotTable
❯ aws dynamodb get-item --table-name PositiveLineBotTable --key '{"Id":{"N":"1"}}' --endpoint-url http://localhost:8000
ID 1
NAME test
But when I run aws sam
in local, it seems that it does no connect to this local DynamoDB
although this table does exit in local.
❯ sam local start-api --env-vars test/env.json
Fetching lambci/lambda:go1.x Docker container image......
Mounting /Users/jpskgc/go/src/line-positive-bot/positive-line-bot as /var/task:ro,delegated inside runtime container
START RequestId: c9f19371-4fea-1e25-09ec-5f628f7fcb7a Version: $LATEST
failed to make Query API call, ResourceNotFoundException: Cannot do operations on a non-existent table
Function 'PositiveLineBotFunction' timed out after 5 seconds
Function returned an invalid response (must include one of: body, headers, multiValueHeaders or statusCode in the response object). Response received:
2020-01-13 18:46:10 127.0.0.1 - - [13/Jan/2020 18:46:10] "GET /positive HTTP/1.1" 502 -
❯ curl http://127.0.0.1:3000/positive
{"message":"Internal server error"}
I want to know how to actually connect to local DynamoDB
table.
some code
Here is the function code in Go.
package main
//import
func exitWithError(err error) {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
type Item struct {
Key int
Desc string
Data map[string]interface{}
}
type Event struct {
Type string `json:"type"`
ReplyToken string `json:"replyToken"`
Source Source `json:"source"`
Timestamp int64 `json:"timestamp"`
Message Message `json:"message"`
}
type Message struct {
Type string `json:"type"`
ID string `json:"id"`
Text string `json:"text"`
}
type Source struct {
UserID string `json:"userId"`
Type string `json:"type"`
}
func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
endpoint := os.Getenv("DYNAMODB_ENDPOINT")
tableName := os.Getenv("DYNAMODB_TABLE_NAME")
sess := session.Must(session.NewSession())
config := aws.NewConfig().WithRegion("ap-northeast-1")
if len(endpoint) > 0 {
config = config.WithEndpoint(endpoint)
}
svc := dynamodb.New(sess, config)
params := &dynamodb.ScanInput{
TableName: aws.String(tableName),
}
result, err := svc.Scan(params)
if err != nil {
exitWithError(fmt.Errorf("failed to make Query API call, %v", err))
}
items := []Item{}
err = dynamodbattribute.UnmarshalListOfMaps(result.Items, &items)
if err != nil {
exitWithError(fmt.Errorf("failed to unmarshal Query result items, %v", err))
}
var words []string
for i, item := range items {
for k, v := range item.Data {
words = append(words, v.(string))
}
}
rand.Seed(time.Now().UnixNano())
i := rand.Intn(len(words))
word := words[i]
return events.APIGatewayProxyResponse{
Body: word,
StatusCode: 200,
}, nil
}
func main() {
lambda.Start(handler)
}
Here is env.json
I try changed docker.for.mac.host.internal to my local ip address. But it does not solve.
{
"PositiveLineBotFunction": {
"DYNAMODB_ENDPOINT": "http://docker.for.mac.host.internal:8000",
"DYNAMODB_TABLE_NAME": "PositiveLineBotTable"
}
}
Here is template.yml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
positive-line-bot
Globals:
Function:
Timeout: 5
Resources:
PositiveLineBotFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: positive-line-bot/
Handler: positive-line-bot
Runtime: go1.x
Policies:
- DynamoDBReadPolicy:
TableName: !Ref PositiveLineBotTable
Tracing: Active
Events:
CatchAll:
Type: Api
Properties:
Path: /positive
Method: GET
Environment:
Variables:
DYNAMODB_ENDPOINT: ''
DYNAMODB_TABLE_NAME: ''
PositiveLineBotTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: 'PositiveLineBotTable'
AttributeDefinitions:
- AttributeName: 'Id'
AttributeType: 'N'
KeySchema:
- AttributeName: 'Id'
KeyType: 'HASH'
ProvisionedThroughput:
ReadCapacityUnits: '5'
WriteCapacityUnits: '5'
BillingMode: PAY_PER_REQUEST
Outputs:
PositiveLineBotAPI:
Description: 'API Gateway endpoint URL for Prod environment for PositiveLineBot'
Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/positive/'
PositiveLineBotFunction:
Description: 'PositiveLineBot Lambda Function ARN'
Value: !GetAtt PositiveLineBotFunction.Arn
PositiveLineBotFunctionIamRole:
Description: 'Implicit IAM Role created for PositiveLineBot'
Value: !GetAtt PositiveLineBotFunction.Arn
Here is the full source code. https://github.com/jpskgc/line-positive-bot