Lypheus
Lypheus

Reputation: 474

AWS Serverless - Auto Create DynamoDB

In my serverless.yml file, I have specified a DynamoDB resource, something to this effect (see below). I'd like to know two things:

  1. Why is it that I'm not seeing these tables get created when they don't exist, forcing me to manually enter AWS console and do so myself?

  2. In my source code (nodejs), i'm not sure how I'd reference a table specified in the yml file instead of hardcoding it.

The two questions above roll up into a singular problem, which is that I'd like to be able to specify the tables in the yml and then when doing a "deploy", have a different table set created per environment.

i.e. If I deploy to "--stage Prod", then table would be "MyTable_Prod". If I deploy to "--stage Dev", then table would be "MyTable_Dev", etc...

Figuring this out would go a long way to making deployments much smoother :).

The serverless.yml section of interest is as follows:

  resources:  
  Resources:
    DynamoDbTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: MyHappyFunTable
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 5
          WriteCapacityUnits: 5
    DynamoDBIamPolicy:
      Type: AWS::IAM::Policy
      DependsOn: DynamoDbTable
      Properties:
        PolicyName: lambda-dynamodb
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Action:
                - dynamodb:Query
                - dynamodb:Scan
                - dynamodb:GetItem
                - dynamodb:PutItem
                - dynamodb:UpdateItem
                - dynamodb:DeleteItem
              Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"
        Roles:
          - Ref: IamRoleLambdaExecution

A sample of my horrid 'hardcoded' table names is as follows:

dbParms = {
    TableName : "MyTable_Dev",
    FilterExpression: "#tid = :tid and #owner = :owner",
    ProjectionExpression: "#id, #name",
    ExpressionAttributeNames: {
        "#tid" : "tenantid",
        "#id" : "id",
        "#name" : "name",
        "#owner" : "owner"
    },
    ExpressionAttributeValues: {
        ":tid": tenantId,
        ":owner": owner
    }
};

Note the "MyTable_Dev" ... ideally i'd like that to be something like "MyTable_" + {$opt.stage} ... or something to that effect.

Upvotes: 3

Views: 666

Answers (1)

Noel Llevares
Noel Llevares

Reputation: 16087

In my source code (nodejs), i'm not sure how I'd reference a table specified in the yml file instead of hardcoding it.

I would put your stage in an environment variable that your Lambda function has access to.

In your serverless.yml,

provider:
  ...
  environment:
    STAGE: {$opt:stage}

Then, in your code you can access it through process.env.STAGE.

const tableName = 'MyTable_' + process.env.STAGE

Upvotes: 1

Related Questions