не удалось выполнить API-запрос Query, ResourceNotFoundException: невозможно выполнить операции с несуществующей таблицей - PullRequest
1 голос
/ 13 января 2020

Сводка

Я выполняю функцию aws lambda с помощью AWS SAM.
Для этой функции требуется база данных, поэтому я выбираю DynamoDB.
Теперь я устанавливаю локальную среду для AWS SAM и DynamoDB.
Кажется, что мне удается установить локальный DynamoDB, но он не может подключиться при запуске локальной функции aws sam.

failed to make Query API call, ResourceNotFoundException: Cannot do operations on a non-existent table

Я хочу знать, как решить эту проблему.

пробовал

Я создал локальную таблицу и вставил проверенные тестовые данные.

❯ 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

Но когда я запускаю aws sam в локальной сети, кажется, что он не подключается к этой локальной DynamoDB, хотя эта таблица завершается локально.

❯ 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"}

Я хочу знать, как на самом деле подключиться к локальной таблице DynamoDB.

некоторый код

Вот код функции в 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)
}

Здесь env.json
Я пытаюсь изменить docker .for.ma c. host.internal к моему локальному IP-адресу. Но это не решает.

{
  "PositiveLineBotFunction": {
    "DYNAMODB_ENDPOINT": "http://docker.for.mac.host.internal:8000",
    "DYNAMODB_TABLE_NAME": "PositiveLineBotTable"
  }
}

Вот 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

Вот полный исходный код. https://github.com/jpskgc/line-positive-bot

1 Ответ

0 голосов
/ 22 января 2020

См. этот ответ

Решения состоят из 2 частей:

  • Создайте docker -сетевую сеть и запустите контейнер dicodb-local и API используя эту сеть
  • Настройте конечную точку соответствующим образом.

Для меня я сделал:

docker network create dynamodb-network
docker run -d -v "$PWD":/dynamodb_local_db -p 8000:8000 --network dynamodb-network --name dynamodb cnadiminti/dynamodb-local
sam local start-api --docker-network dynamodb-network -n env.json

и в своем коде я назвал имя docker как DNS-адрес:

const awsRegion = process.env.AWS_REGION || "us-east-2";
const options = {
  region: awsRegion,
};
if (process.env.AWS_SAM_LOCAL) {
  options.endpoint = "http://dynamodb:8000";
}
const docClient = new dynamodb.DocumentClient(options);
...