How to use Dynamoose combined with AWS SAM? - amazon-web-services

Let's say I have the following AWS SAM resource that creates a DynamoDB table:
EmployeeTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: Employee
AttributeDefinitions:
- AttributeName: EmployeeId
AttributeType: S
- AttributeName: LocationId
AttributeType: S
- AttributeName: DepartmentId
AttributeType: S
KeySchema:
- AttributeName: EmployeeId
KeyType: HASH
GlobalSecondaryIndexes:
- IndexName: Location-index
KeySchema:
- AttributeName: LocationId
KeyType: HASH
Projection:
ProjectionType: ALL
BillingMode: PAY_PER_REQUEST
And I want to interact with DynamoDB through Dynamoose.
In Dynamoose, we have the Model and Schema resources that help us define the shape of our table.
Because I already created the table and the schema (attributes, indexes, etc) within the AWS SAM template, how should I use Dynamoose Schema? How should I use indexes?
Thanks!

Here is how we can implement the dynamodb table using dynamoose.
Where schema can be written like:
const schema = new dynamoose.Schema({
EmployeeId: {
type: String,
required: true,
hashKey: true,
},
LocationId: {
type: String,
required: true,
index: [
{
global: true,
name: 'Location-index',
throughput: { read: 1, write: 1 },
project: true,
},
],
},
DepartmentId: {
type: String,
required: true,
},
});
And for model, we just need to pass the schema like:
const Employee = dynamoose.model("Employee", schema);

Related

Create a local secondary index using Cloud CloudFormation

My apologies I'm starting with AWS and Cloudformation
I got this cloud formation template, I got Id and topic as a primary index and I would like to add a local secondary index that consists of the id and position columns to this template.
Id
topic
position
detaills
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
Env:
Type: String
CommitHash:
Type: String
Resources:
RecipeRecommendationDynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: "id"
AttributeType: "S"
- AttributeName: "topic"
AttributeType: "S"
KeySchema:
- AttributeName: "id"
KeyType: "HASH"
- AttributeName: "topic"
KeyType: "RANGE"
TimeToLiveSpecification:
AttributeName: ttl
Enabled: true
TableName: topics_dumps
BillingMode: PAY_PER_REQUEST
Tags:
- Key: "Env"
Value: !Ref Env
You have to add LocalSecondaryIndexes:
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
Env:
Type: String
CommitHash:
Type: String
Resources:
RecipeRecommendationDynamoDBTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: "id"
AttributeType: "S"
- AttributeName: "topic"
AttributeType: "S"
- AttributeName: "position"
AttributeType: "S"
KeySchema:
- AttributeName: "id"
KeyType: "HASH"
- AttributeName: "topic"
KeyType: "RANGE"
TimeToLiveSpecification:
AttributeName: ttl
Enabled: true
LocalSecondaryIndexes:
- IndexName: position
KeySchema:
- AttributeName: "id"
KeyType: "HASH"
- AttributeName: "position"
KeyType: "RANGE"
Projection:
ProjectionType: ALL
TableName: topics_dumps
BillingMode: PAY_PER_REQUEST
Tags:
- Key: "Env"
Value: !Ref Env

Create the DynamoDB global Table if doesn't exist using Cloudformation

I am sharing the DynamoDB cft below. I want to add a condition, so that while adding the another table the existing tables will not impact. Below template is used for creating 2 global table with name as sample1 and sample12 configuring in parameter section:
AWSTemplateFormatVersion: "2010-09-09"
Description: 'AWS CloudFormation Template for DynamoDB tables For sample Service'
Parameters:
sample1:
Type: String
Description: Select existing dynamodb table name from Parameter Store
Default: sample1
sample12:
Type: String
Description: Select existing dynamodb table name from Parameter Store
Default: sample12
Resources:
sample1:
Type: AWS::DynamoDB::GlobalTable
Properties:
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
-
AttributeName: "msgId"
AttributeType: "S"
KeySchema:
-
AttributeName: "msgId"
KeyType: "HASH"
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
SSESpecification:
SSEEnabled: true
SSEType: "KMS"
Replicas:
- Region: us-east-1
TableName: !Ref sample1
sample12:
Type: AWS::DynamoDB::GlobalTable
Properties:
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
-
AttributeName: "msgId"
AttributeType: "S"
-
AttributeName: "flightNbr"
AttributeType: "S"
-
AttributeName: "recordUpdateTS"
AttributeType: "S"
-
AttributeName: "msgTypeCd"
AttributeType: "S"
-
AttributeName: "recordCreationEpochTime"
AttributeType: "S"
KeySchema:
-
AttributeName: "msgId"
KeyType: "HASH"
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
SSESpecification:
SSEEnabled: true
SSEType: "KMS"
Replicas:
- Region: us-east-1
TableName: !Ref sample12
GlobalSecondaryIndexes:
-
IndexName: "FLIGHTNBR_UPDATETS_INDEX"
KeySchema:
-
AttributeName: "flightNbr"
KeyType: "HASH"
-
AttributeName: "recordUpdateTS"
KeyType: "RANGE"
Projection:
ProjectionType: "ALL"
-
IndexName: "MSGTYPE_CREATETS_INDEX"
KeySchema:
-
AttributeName: "msgTypeCd"
KeyType: "HASH"
-
AttributeName: "recordCreationEpochTime"
KeyType: "RANGE"
Projection:
ProjectionType: "ALL"
How can I add a condition or any other methods to check if table exists or not?
The only way to do this is through custom resource in the form of a lambda function. The function would use AWS SDK to perform conditional checks and create aws resources based on the outcome of these checks.

Can we create multiple Amazon DynamoDB tables at a time using AWS CloudFormation Template?

I'm trying to create Amazon DynamoDB tables using Cloud Formation Template. So my question is can I have multiple tables created in single go ?
If yes, what would the approach be, to have multiple "Properties" or to have multiple "Resources" ?
Can you please clarify on this.
Each DynamoDB table is a resource of type AWS::DynamoDB::Table.
Add multiple resources, each with a different table name. For example:
Resources:
Users:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: UserID
AttributeType: S
KeySchema:
- AttributeName: UserID
KeyType: HASH
Jobs:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: UserID
AttributeType: S
- AttributeName: JobID
AttributeType: S
KeySchema:
- AttributeName: UserID
KeyType: HASH
- AttributeName: JobID
KeyType: RANGE

Serverless deploy fails

Iam trying to deploy my lambda function to AWS using serverless. When executing
serverless deploy --verbose
Iam getting the following error every time:
Serverless Error ---------------------------------------
An error occurred: mainTable - Invalid KeySchema: The first > KeySchemaElement is not a HASH key type (Service: AmazonDynamoDBv2;Status Code: 400; Error Code: ValidationException; Request ID: EACEH0RDMBR36TR0DDBGODTRT3VV4KQNSO5AEMVJF66Q9ASUAAJG).
My serverless.yml looks as following:
service: backend-1 # NOTE: update this with your service name
provider:
name: aws
runtime: nodejs10.x
stage: dev
region: eu-central-1
functions:
graphql:
handler: src/handler.graphql
events:
- http:
path: graphql
method: post
cors: true
plugins:
- serverless-webpack
- serverless-offline
custom:
webpack:
webpackCOnfig: 'webpack.config.js'
includeModules: true
packager: 'npm'
stage: ${opt:stage, self:provider.stage}
resources:
Resources:
mainTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: main_${self:custom.stage}
AttributeDefinitions:
- AttributeName: id
AttributeType: S
- AttributeName: sort
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
- AttributeName: sort
KeyType: RANGE
BillingMode: PAY_PER_REQUEST
GlobalSecondaryIndexes:
- IndexName: spinned-primary
KeySchema:
- AttributeName: id
KeyType: RANGE
- AttributeName: sort
KeyType: HASH
Projection:
ProjectionType: ALL
labelTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: labels_${self:custom.stage}
AttributeDefinitions:
- AttributeName: sort
AttributeType: S
- AttributeName: label
AttributeType: S
KeySchema:
- AttributeName: sort
KeyType: HASH
- AttributeName: label
KeyType: RANGE
BillingMode: PAY_PER_REQUEST
GlobalSecondaryIndexes:
- IndexName: spinned-primary
KeySchema:
- AttributeName: sort
KeyType: RANGE
- AttributeName: label
KeyType: HASH
Projection:
ProjectionType: ALL
logTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: logs_${self:custom.stage}
AttributeDefinitions:
- AttributeName: id
AttributeType: S
- AttributeName: sort
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
- AttributeName: sort
KeyType: RANGE
BillingMode: PAY_PER_REQUEST
Can someone of you help?
Cheers!
When using KeySchemaElements, the HASH keytype must come before the RANGE keytype.
In your YAML, on you GSI for spinned-primary, you have to put the HASH keytype before the RANGE keytype; switch them around so that the HASH is the first keytype in that element.

How to set DynamoDB Read/write capacity mode to On-demand on CloudFormation

I've seen this site about DynamoDB On-demand and I updated my tables, created by CloudFormation, to On-demand. Now, when I try to update my Stack, I get this error:
One or more parameter values were invalid: Neither ReadCapacityUnits nor WriteCapacityUnits can be specified when BillingMode is PAY_PER_REQUEST
Is there a way to set DynamoDB Read/write capacity mode to On-demand on CloudFormation?
EDIT:
I've updated to On-demand on AWS Console.
EDIT 2:
My template:
DynamoDBUsersTable:
Type: AWS::DynamoDB::Table
Description: Users table
Properties:
TableName: !Sub ${StackName}-users-table
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH
ProvisionedThroughput:
ReadCapacityUnits: 10
WriteCapacityUnits: 10
Thank you.
You need to add BillingMode: PAY_PER_REQUEST to properties and remove ProvisionedThroughput both from table properties and from all GlobalSecondaryIndexes if they specified. So finally your template have to look like:
DynamoDBUsersTable:
Type: AWS::DynamoDB::Table
Description: Users table
Properties:
TableName: !Sub ${StackName}-users-table
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: userId
AttributeType: S
KeySchema:
- AttributeName: userId
KeyType: HASH