skip to Main Content

I use aws cdk to deploy a stack that contains a dynamoDB table. For each deploy of my stack, CloudFormation creates a new table and links it to my lambda function. I want to know how I can reuse an existing table, without the need to create a new one if it was already created for this stack (to avoid migrating my record to a new instance of the dynamoDB table).

Here is my code:

const table = new Table(stack, id, {
    billingMode: BillingMode.PAY_PER_REQUEST,
    partitionKey: {
        name: "id",
        type: AttributeType.STRING,
    },
    removalPolicy: RemovalPolicy.SNAPSHOT,
});

I previously tried to use Table.fromTableName, but I cloudn’t link my lambda function to the table…

Here is the code I tried:

let myTable: Table; // my table
let lambdaFunction: Function = new Function(...); // my function

// table creation
try {
    myTable = Table.fromTableName(stack, tableId, name);
} catch (_) {
    myTable = new Table(stack, id, {
        billingMode: BillingMode.PAY_PER_REQUEST,
        partitionKey: {
            name: "id",
            type: AttributeType.STRING,
        },
        removalPolicy: RemovalPolicy.SNAPSHOT,
    });
}

//referencing the table in my lambda function via env
lambdaFunction.addEnvironment("TABLE_NAME", myTable.tableName);

When the lambda tries to access the table a ResourceNotFound exception is thrown.

Any ideas?

As well I heard that if I use the same tableName in new Table(...) dynamoDB will return me the existing table without creating a new one, but I don’t know if it’s true…
Does someone knows?

3

Answers


  1. Chosen as BEST ANSWER

    I rechecked the matter, the answer actually is to use constant constructor ids along with constant resource names.

    From this blog:

    But as we discussed earlier, replacing resources is likely not the best thing to do in the first place. So to prevent it, we just don’t modify the CDK Construct IDs.

    So what I did is to give hard-coded constructor ids, along with hard-coded table name, that wouldn't be changed. This preserve the logical ID of the resource to CloudFormation would identify it and prevent deletion and re-creation of the resource.

    Note that you need to take a different approach if you are using nested constructors, as detailed in the blog:

    CDK generates the Logical IDs based on the full Construct “path”. With nested Constructs, IDs of all “higher” Constructs are used to create the unique Logical ID. [...] So even if we don’t change the Construct IDs, moving Constructs into other Constructs changes generated Logical IDs. This is what often happens during development or refactoring.

    So, as said here is the fixed code:

    myTable = new Table(stack, "MyTableConstructor", {
           tableName: "MyTable",
           billingMode: BillingMode.PAY_PER_REQUEST,
           partitionKey: {
               name: "id",
               type: AttributeType.STRING,
           },
           removalPolicy: RemovalPolicy.SNAPSHOT,
    });
    

    This will work with an existing table, no need to use Table.fromTableName to import it :)

    So, it wasn't linked to the removal policy of the table or the use of Table.fromTableName, only that the logical ID was messed up...


  2. First of all you need to change retention policy of the table, as a Snapshot will not retain your table and data in a usable manner. Explicitly defining a table name will also allow you to easily import the table again, without having to understand what CDK named the table for you.

    removalPolicy: RemovalPolicy.RETAIN,
    tableName: 'MyLovelyTable',
    

    Then Table.fromTableName will work, as long as you provide the correct table name from the Table interface.

    const importedTable = dynamodb.Table.fromTableName(
      this,
      'table-from-name-id',
      'MyLovelyTable',
    );
    

    If you create the stack often, and don’t often know what the tableName is, then every time you change the table you can store the name in Parameter Store and retrieve it when needed.

    Login or Signup to reply.
  3. To reuse a DynamoDB table in TypeScript, you can use the AWS SDK for JavaScript/TypeScript (aws-sdk package) to interact with DynamoDB. Here’s an example of how you can reuse a DynamoDB table:

    1. Install the necessary dependencies by running the following command in your project directory:

      npm install aws-sdk
      
    2. Import the necessary modules in your TypeScript file:

      import AWS from 'aws-sdk';
      
    3. Configure the AWS SDK with your AWS credentials and the appropriate region:

      AWS.config.update({
        region: 'YOUR_REGION',
        accessKeyId: 'YOUR_ACCESS_KEY',
        secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
      });
      

      Replace ‘YOUR_REGION’, ‘YOUR_ACCESS_KEY’, and ‘YOUR_SECRET_ACCESS_KEY’ with your actual AWS region and credentials.

    4. Create a DynamoDB document client using the configured AWS SDK:

      const dynamodb = new AWS.DynamoDB.DocumentClient();
      
    5. Use the DynamoDB client to perform operations on the existing table. For example, to retrieve an item from the table:

       const params = {
         TableName: 'YOUR_TABLE_NAME',
         Key: {
           // Specify the primary key attributes
           primaryKey: 'PRIMARY_KEY_VALUE',
         },
       };
      
       dynamodb.get(params, (error, data) => {
         if (error) {
           console.error('Error retrieving item:', error);
         } else {
           console.log('Retrieved item:', data.Item);
         }
                 });
      

      Replace ‘YOUR_TABLE_NAME’ with the name of your existing DynamoDB table and ‘PRIMARY_KEY_VALUE’ with the actual value of the primary key attribute you want to retrieve.

    By following these steps, you can reuse the existing DynamoDB table and perform various operations using the AWS SDK for JavaScript/TypeScript.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search