SAM invoke won't take local env vars

1

I have a sample SAM application with basic endpoints. I just want to run it locally by:

sam local invoke -e events/event-post-item.json putItemFunction --profile myprofile -n local.json

local.json is as follows:

{
    "Parameters": {
        "TABLE_CUSTOMERS": "MyDynamoDBTable" // MyDynamoDBTable is the DynamoDB resource name from `template.yml`
    }
}

And following is the code for putItemFunction

const dynamodb = require('aws-sdk/clients/dynamodb');
const docClient = new dynamodb.DocumentClient(); 
const tableName = process.env.TABLE_CUSTOMERS; 

exports.putItemHandler = async (event) => {
    const { body, httpMethod, path } = event;
    if (httpMethod !== 'POST') {
        throw new Error(`postMethod only accepts POST method, you tried: ${httpMethod} method.`);
    } 
    console.log('received:', JSON.stringify(event));  
    const { id, name } = JSON.parse(body); 
    const params = {
        TableName: tableName,
        Item: { id, name },
    };
    await docClient.put(params).promise();

    const response = {
        statusCode: 200,
        body,
    };

    console.log(`response from: ${path} statusCode: ${response.statusCode} body: ${response.body}`);
    return response;
};

I run this, and I get a "resource not found" error. I have made sure that the profile details are correct. I do understand that I am invoking it locally, and my local machine has a runtime docker only. Not the DynamoDB table, 'cause that's created over the cloud. Shouldn't SAM figure out the generated database name as defined in the Stack's template.yml file? When I hardcode the generated database name in the env file, it works. But that's not pragmatic approach. I want SAM to just use the table name that was just generated when I deployed the stack.

asked 2 years ago3311 views
3 Answers
1

It's not well documented but any env vars that you want to override via --env-vars must be defined in the SAM template. I too had this problem until I finally ran across https://stackoverflow.com/questions/48104665/aws-sam-local-environment-variables/48139216#48139216.

jimmbo
answered 5 months ago
0

If you want to use the generated table name in the stack you can use a cloudformation construct called !Ref and set an environment variable for the lambda function that can be used. As indicated here, dynamo outputs the name of the table that you can then reference in your lambda function as an env variable. Here is an example.

  MyLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
       ....     
      Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object
        Variables:
          DYNAMODB_TABLE_NAME: !Ref DynamoDBTable

DynamoDBTable:
    Type: AWS::DynamoDB::Table
    Properties: 
      AttributeDefinitions: 
        - AttributeName: id
          AttributeType: S
sagar
answered 2 years ago
  • That's already done. The problem is, if I skip --env-vars env.json part from the sam local invoke command then process.env.DYNAMODB_TABLE_NAME value I get is just DynamoDBTable. Not the correct name of database that was generated with the stack, ex: DynamoDBTable-T69PQM8X9UBJ...

  • I guess I understand what's going on. I can't get the generated DB name to be sent to the process.env automatically when invoking locally. I have to get the generated names from the deploy output and pipe it to some script to be injected it into env.json for my local invokes to be automatic.

0

Try putting the function name at the end of the invoke line:

sam local invoke -e events/event-post-item.json --profile myprofile -n local.json putItemFunction
profile pictureAWS
EXPERT
Uri
answered 2 years ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions