英文:
How to create else reference resources in AWS CDK in CI/CD?
问题
Here is the translated code part without the translation of the code itself:
const existingTable = dynamodb.Table.fromTableName(stack, 'ExistingTable', 'existing-table-name');
const table = new dynamodb.Table(stack, 'MyTable', {
tableName: 'my-table',
partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
// Define other table attributes
});
if (!existingTable.tableArn) {
// Create the table if it doesn't exist
table.create();
}
英文:
I’m curious about how to use CI/CD in conjunction with AWS CDK; specifically, I want need a pattern where if a given resource does not yet exist, it is created else the (therefore existing) resource is referenced.
Here is an attempt to create a DynamoDb table if it does not exist else reference it. I’m curious, is this the correct/canonical way to do this?
const existingTable = dynamodb.Table.fromTableName(stack, 'ExistingTable', 'existing-table-name');
const table = new dynamodb.Table(stack, 'MyTable', {
tableName: 'my-table',
partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
// Define other table attributes
});
if (!existingTable.tableArn) {
// Create the table if it doesn't exist
table.create();
}
答案1
得分: 3
这不是仅仅使用CDK就能完成的事情。CDK默认情况下不是一个与AWS资源API交互的库(有一些例外情况,比如通常以lookup*
开头的函数)。它是一个生成CloudFormation模板的库。这些模板没有能力具有"如果不存在则创建资源"的语义。
你有几个选项:
- 你可以使用AWS SDK库自己进行查找。虽然这通常会起作用,但要记住它不是绝对可靠的。它容易受到时序检查和使用(TOCTOU)错误的影响,其中资源在合成模板时存在/不存在,但稍后由其他操作创建/删除。
- 你可以使用自定义资源,它会使用库进行检查和创建。这同样有点棘手(自定义资源通常难以正确使用)。
- 你可以在上下文中添加一个配置选项,指定表的名称和/或ARN。然后,你可以有条件地创建资源或使用
fromTableName
/fromTableArn
方法。这是我的个人偏好,也是在适当的情况下我使用的模式。
请记住,一般来说,这是一种反模式。你应该在部署时知道是使用现有资源还是创建新资源。动态检测和更改部署内容会导致错误/意外行为,甚至包括数据丢失:
- 如果其他资源意外删除了现有表会发生什么?在更新时将创建一个新表。该表将由新堆栈拥有,并且不包含预期的数据。类似地,如果在帐户中多次部署此堆栈,表的下一个所有者将取决于下一个部署的人(这可能是意外的情况)。
- 你没有对表的内在依赖性。与#1相关,更好的模式是使用
Fn::ImportValue
来确保两个堆栈之间存在依赖关系,其中一个提供表,另一个使用它。
英文:
This is not something you can do only using CDK. CDK is not a library that interacts with AWS resource APIs by default (there are some exceptions, such as the functions that generally start with lookup*
). It is a library that generates CloudFormation templates. Those templates do not have the ability to "create a resource if it doesn't exist" semantic.
You have a few options here:
- You can use the AWS SDK libraries to do the lookup yourself. While this will often work, keep in mind it isn't fool-proof. It is susceptible to Time-of-check-time-of-use (TOCTOU) errors, where the resource did/didn't exist at the time the template was synthesized, but was later created/removed by something else.
- You can use a Custom Resource, which would do the check and create using the libraries. This is similarly finicky (and custom resources are notoriously difficult to get right).
- You can add a configuration option to your context, where you specify the table name and/or ARN of the table. Then you would conditionally create the resource or use the
fromTableName
/fromTableArn
methods. This is my personal preference, and where appropriate I use this pattern.
Keep in mind that, generally speaking, this is an anti-pattern. You should know at deploy-time whether you are are using an existing resource or creating a new one. Having it dynamically detect and change what is deployed opens you up to errors/unexpected behavior, up to and including data loss:
- What happens if the existing table happens to be deleted by some other resource? A new table will be created when you update. That table will be owned by some new stack, and not contain the data that is expected. Similarly, if this stack is being deployed more than once in an account, the next owner of the table will depend on whoever deploys next (which is likely unexpected).
- You have no inherent dependency on the table. Related to #1, a better pattern would be to use an
Fn::ImportValue
to ensure there is a dependency between two stacks, where one provides the table and the other uses it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论