New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dynamodb: add GSI to existing Dynamodb table via CDK deploy #12343
Comments
That's not something we can accommodate @mattiLeBlanc . We can't modify resources in the CDK that are not managed in the CDK. If you want to do different things in test / prod, you need to vary it in code: const app = new cdk.App();
// test
new MyStack(app, 'TestStack');
// prod
new MyStack(app, 'ProdStack', {
table: 'my-table-arn',
});
interface MyStackProps extends cdk.StackProps {
readonly table?: string;
}
class MyStack extends cdk.Stack {
readonly table: dynamodb.ITable;
constructor(scope: Construct, id: string, props?: MyStackProps) {
super(scope, id, props);
if (props.table) {
this.table = dynamodb.Table.fromTableArn(this, 'Table', props.table);
} else {
this.table = new dynamodb.Table(this, 'Table', {
// do whatever you need here...
});
}
}
} Thanks, |
@skinny85 I am using a stack to create my table, it is just when I want to update a deployed table by adding an index, I want to do it through the CDK and not manually for each env and developer that might have the stack deployed.
|
Yes. If you want a GSI added to a Table using the CDK, that Table also needs to be created by the CDK. |
Generally, those things are done in CDK by code changes. You change the code to add the GSI to your CDK-managed Table, and then everyone who updates their code will get the GSI the next time they deploy their Stacks. |
@skinny85 I think we are misunderstanding each other. My table is created by CDK. The problem is that in the docs or typescript definition I do not see a way to add a GSI to an existing table. When I already have a table with production data and I we decide to add an index later, I can't remove the table and recreate because I don't want to lose data. Using the Do you understand my issue now? |
No, sorry 😕. If you have a Table managed by the CDK, then you have a |
@skinny85 So before the CDK starts generating Cloudformation stuff I run a SDK I have a However, if I add an index to my schema (to an existing Type which has the @model annotation), and deploy again, the table already exists and I would get a CDK error saying table X can't be created, right? So I use the list of tables I fetched before to decide if I use: Just to be clear, it is my understanding that I can't use However: both functions return an ITable which doesn't support the function
those 2 fromTable or fromArn return ITable don't have it: So my issue is a Typescript related issue perhaps. So in your original example I have no clue how to to add a GSI with the current Typescript:
I can't make my issue anymore clear then this. Maybe I am looking at it from the wrong angle and I am not seeing the obvious so I hope at least now you understand what issue I am running into from my perspective. Thanks for your time and patience. |
No. The existing Table would be updated with the GSI. |
But I am getting a Table already exist error when I try to update my table which already exists:
using I am don't know how to further explain it, I have exhausted my story telling. :( edit I will try to force the type of when I fetch a table via Arn or Name to the interface of update 2
I don't know how to resolve this. |
Here's how the CDK works. Point in time #1This is the code: const app = new App();
const stack = new Stack(app, 'Stack');
const table = new dynamodb.Table(stack, 'Table', {
partitionKey: {
name: 'Id',
type: dynamodb.AttributeType.STRING,
},
removalPolicy: RemovalPolicy.DESTROY,
}); You run Point in time #2You want to add a GSI. You change the code to be: const app = new App();
const stack = new Stack(app, 'Stack');
const table = new dynamodb.Table(stack, 'Table', {
partitionKey: {
name: 'Id',
type: dynamodb.AttributeType.STRING,
},
removalPolicy: RemovalPolicy.DESTROY,
});
table.addGlobalSecondaryIndex({
partitionKey: {
name: 'Id',
type: dynamodb.AttributeType.STRING,
},
indexName: 'some-index',
}); You run I also don't know how to explain this better 😕. |
@skinny85 Yeah I think I see why we dont understand each other. What I think is happening is that when you use DESTROY, it is fine to run the Does that make sense? I can't imagine you every want to destroy your table in production when you want to add an index later, that would be very unhelpful and force me to manually add the index via the AWS console. But I want everything to stay managed via the CDK. |
No. Feel free to remove it from the code I posted above, and try it yourself. Just remember to manually delete the Table after you're done testing. |
Okay, I did some more testing an initially it didn't work, I would get :
So I did start to test some variations like not adding a tableName to the TableProps since you don't have that, for that I had to remove my tables and recreate them and of course everything works now that I have recreated them with or without tableName in props. So I think what is going on that for some reason my tables where not part of the stack anymore, it's delta lost sync or something and that is why it tried to create another table with the same name, hence the name collision error. I will have to check in Staging and production if the tables are also not in the stack anymore. I believe I can see that in Resource list and I know how to import resources back into a stack. Adam, thanks for your patience man, this was just a difficult issue because it was not clear to me my tables have fallen outside of the stack (they where created by the stack initially, never separately). |
I think I might guess what's happening. You said you set a specific name for a Table; perhaps you're doing an update that causes a replacement of the Table (Meaning, the given change cannot be applied to the existing Table; a new Table must be created instead)? In that case, CloudFormation will first try to create a new resource, and if you're setting a specific name for the Table, then it will fail with the "Table with name 'xyz' already exists" error. You can see which changes cause a replacement by running A few pointers:
Hope this helps! Thanks, |
Hi Adam, Strangely, when I removed my stack and tables and recreated the tables, with a tablename, and then added the GSI and deployed again, no error. I am redeploying it now to verify if the table is listed, and then I will manually reimport the resources in my stacks and test if I can do the update. update |
That's great to hear @mattiLeBlanc ! Anything else we can help you with on this issue? |
Hi Adam, |
|
A way to use Table.addGlobalSecondaryIndex for existing tables so we can Add an inde to a existing table using the CDK.
Use Case
I create my DynamoDB tables via the CDK.
Now I have to add an index, so I want to ideally update the existing table and not recreate the table (no delete policy is enabled).
So, in my CDK script I check (using the SDK) if the table already exists. If it doesn't exist I use :
to create table and GSI.
However, if the table does already exist (in staging or prod), I am using
to get a table reference ( so I can use that to get the datasource for Appsync resolvers and such).
The problem I have is that
fromTableName
returns an interface ofITable
and notTable
.ITable
doesn't have theaddGlobalSecondaryIndex
function, onlyTable
does.So there is no way for me (as far as I know) to add an index to an existing table, either then removing the table first (bad) or adding it manually.
I have add a hacky workaround in my CDK deploy script using the SDK where I use the
updateTable
command from@aws-sdk/client-dynamodb
however that is not ideal.Proposed Solution
If the
Table.fromTableName
function would return aTable
interface, that could allow us to calladdGlobalSecondaryIndex
orremoveGlobalSecondaryIndex
and update our tables via the CDK.Other
This is a 🚀 Feature Request
The text was updated successfully, but these errors were encountered: