web-dev-qa-db-fra.com

connexion d'AWS SAM Local à dynamodb dans le menu fixe

J'ai configuré une paire passerelle/aws lambda d'api avec AWS sam local et j'ai confirmé que je pouvais l'appeler avec succès après l'exécution.

sam local start-api

J'ai ensuite ajouté une instance locale de dynamodb dans un conteneur de menu fixe et créé une table à l'aide de la clé aws

Mais, après avoir ajouté le code au lambda pour écrire dans l’instance dynamodb, je reçois:

2018-02-22T11: 13: 16.172Z erreur ed9ab38e-fb54-18a4-0852-db7e5b56c8cd: n'a pas pu écrire dans la table: {"message": "connect ECONNREFUSED 0.0.0.0:8000","code":"NetworkingError","errno":"ECONNREFUSED","syscall":"connect", adresse ":" 0.0.0.0 "," port ": 8000," region ":" eu-west-2 "," nom ordinateur ":" 0.0.0.0 "," réessayable ": true," heure ":" 2018-02 -22T11: 13: 16.165Z "} écriture de l'événement à partir de la commande: {"name": "test", "géolocalisation": "xyz", "type": "createDestination"} END ID requête: ed9ab38e-fb54-18a4-0852-db7e5b56c8cd

J'ai constaté en ligne que vous deviez peut-être vous connecter au même réseau de dockers. J'ai donc créé un docker network create lambda-local réseau et modifié mes commandes de démarrage en:

sam local start-api --docker-network lambda-local

et

docker run -v "$PWD":/dynamodb_local_db -p 8000:8000 --network=lambda-local cnadiminti/dynamodb-local:latest

mais toujours recevoir la même erreur

sam local est en train d'imprimer 2018/02/22 11:12:51 Connecting container 98b19370ab92f3378ce380e9c840177905a49fc986597fef9ef589e624b4eac3 to network lambda-local

Je crée le dynamodbclient en utilisant:

const AWS = require('aws-sdk')
const dynamodbURL = process.env.dynamodbURL || 'http://0.0.0.0:8000'
const awsAccessKeyId = process.env.AWS_ACCESS_KEY_ID || '1234567'
const awsAccessKey = process.env.AWS_SECRET_ACCESS_KEY || '7654321'
const awsRegion = process.env.AWS_REGION || 'eu-west-2'

console.log(awsRegion, 'initialising dynamodb in region: ')

let dynamoDbClient
const makeClient = () => {
  dynamoDbClient = new AWS.DynamoDB.DocumentClient({
    endpoint: dynamodbURL,
    accessKeyId: awsAccessKeyId,
    secretAccessKey: awsAccessKey,
    region: awsRegion
  })
  return dynamoDbClient
}

module.exports = {
  connect: () => dynamoDbClient || makeClient()
}

et inspecter le dynamodbclient mon code crée des spectacles

DocumentClient {
  options:
   { endpoint: 'http://0.0.0.0:8000',
     accessKeyId: 'my-key',
     secretAccessKey: 'my-secret',
     region: 'eu-west-2',
     attrValue: 'S8' },
  service:
   Service {
     config:
      Config {
        credentials: [Object],
        credentialProvider: [Object],
        region: 'eu-west-2',
        logger: null,
        apiVersions: {},
        apiVersion: null,
        endpoint: 'http://0.0.0.0:8000',
        httpOptions: [Object],
        maxRetries: undefined,
        maxRedirects: 10,
        paramValidation: true,
        sslEnabled: true,
        s3ForcePathStyle: false,
        s3BucketEndpoint: false,
        s3DisableBodySigning: true,
        computeChecksums: true,
        convertResponseTypes: true,
        correctClockSkew: false,
        customUserAgent: null,
        dynamoDbCrc32: true,
        systemClockOffset: 0,
        signatureVersion: null,
        signatureCache: true,
        retryDelayOptions: {},
        useAccelerateEndpoint: false,
        accessKeyId: 'my-key',
        secretAccessKey: 'my-secret' },
     endpoint:
      Endpoint {
        protocol: 'http:',
        Host: '0.0.0.0:8000',
        port: 8000,
        hostname: '0.0.0.0',
        pathname: '/',
        path: '/',
        href: 'http://0.0.0.0:8000/' },
     _clientId: 1 },
  attrValue: 'S8' }

Cette configuration doit-elle fonctionner? Comment puis-je les amener à se parler?

---- modifier ----

D'après une conversation sur Twitter, il est utile de mentionner (peut-être) que je peux interagir avec dynamodb au niveau de la CLI et du Web Shell

 dynamo db at the CLI

 dynamodb web Shell

7
Paul D'Ambra

Merci beaucoup à Heitor Lessa qui m'a répondu sur Twitter avec un exemple de repo

Ce qui m'a dirigé vers la réponse ...

  • le conteneur de menu fixe de dynamodb est sur 127.0.0.1 dans le contexte de ma machine .__ (c'est pourquoi je pourrais interagir avec lui)

  • Le conteneur de menu fixe de SAM local est sur 127.0.0.1 dans le contexte de ma machine

  • Mais ils ne sont pas sur 127.0.0.1 du contexte de l'autre 

Donc: https://github.com/heitorlessa/sam-local-python-hot-reloading/blob/master/users/users.py#L14

M'a indiqué de changer mon code de connexion pour:

const AWS = require('aws-sdk')
const awsRegion = process.env.AWS_REGION || 'eu-west-2'

let dynamoDbClient
const makeClient = () => {
  const options = {
    region: awsRegion
  }
  if(process.env.AWS_SAM_LOCAL) {
    options.endpoint = 'http://dynamodb:8000'
  }
  dynamoDbClient = new AWS.DynamoDB.DocumentClient(options)
  return dynamoDbClient
}

module.exports = {
  connect: () => dynamoDbClient || makeClient()
}

avec les lignes importantes étant: 

if(process.env.AWS_SAM_LOCAL) {
  options.endpoint = 'http://dynamodb:8000'
}

du contexte du conteneur du docker local SAM, le conteneur dynamodb est exposé via son nom

Mes deux commandes de démarrage ont fini comme:

docker run -d -v "$PWD":/dynamodb_local_db -p 8000:8000 --network lambda-local --name dynamodb cnadiminti/dynamodb-local

et

AWS_REGION=eu-west-2 sam local start-api --docker-network lambda-local

avec le seul changement ici étant de donner un nom au conteneur dynamodb

7
Paul D'Ambra

Si vous utilisez sam-local sur un mac comme beaucoup de devs, vous devriez pouvoir utiliser 

options.endpoint = "http://docker.for.mac.localhost:8000"

Ou sur les nouvelles installations de docker https://docs.docker.com/docker-for-mac/release-notes/#docker-community-edition-18030-ce-mac59-2018-03-26

options.endpoint = "http://Host.docker.internal:8000"

Au lieu d'avoir à faire plusieurs commandes comme Paul a montré ci-dessus (mais cela pourrait être plus agnostique de plate-forme?).

7
Ellery

Comme @Paul l’a mentionné, il s’agit de configurer votre réseau entre les conteneurs de menu fixe - lambda et base de données.

Une autre approche qui a fonctionné pour moi (en utilisant docker-compose).

docker-compose:

version: '2.1'

services:
  db:
    image: ...
    ports:
      - "3306:3306"
    networks:
      - my_network
    environment:
      ...
    volumes:
      ...

networks:
  my_network:

Ensuite, après docker-compose up, exécuter docker network ls affichera:

NETWORK ID          NAME                        DRIVER              SCOPE
7eb440d5c0e6        dev_my_network              bridge              local

Mon nom de conteneur de menu fixe est dev_db_1.

Mon code js est:

const connection = mysql.createConnection({
    Host: "dev_db_1",
    port: 3306,
    ...
});

Ensuite, en exécutant la commande sam:

sam local invoke --docker-network dev_my_network -e my.json

Empiler:

  • Docker: 18.03.1-ce
  • Docker-compose: 1.21.1
  • MacOS HighSierra 10.13.6
1
Yair Segal