如何使用 CDK 获取资源的逻辑 ID?
Posted
技术标签:
【中文标题】如何使用 CDK 获取资源的逻辑 ID?【英文标题】:How to get logical ID of resource with CDK? 【发布时间】:2020-08-31 07:49:27 【问题描述】:我正在尝试为 CDK 构造编写一些 tests,以验证定义为构造一部分的安全组规则。
构造体如下所示。
export interface SampleConstructProps extends StackProps
srcSecurityGroupId: string;
export class SampleConstruct extends Construct
securityGroup: SecurityGroup;
constructor(scope: Construct, id: string, props: SampleConstructProps)
super(scope, id, props);
// const vpc = Vpc.fromLookup(...);
this.securityGroup = new SecurityGroup(this, "SecurityGroup",
vpc: vpc,
allowAllOutbound: true,
);
const srcSecurityGroupId = SecurityGroup.fromSecurityGroupId(stack, "SrcSecurityGroup", props.srcSecurityGroupId);
this.securityGroup.addIngressRule(srcSecurityGroup, Port.tcp(22));
我想编写一个如下所示的测试。
test("Security group config is correct", () =>
const stack = new Stack();
const srcSecurityGroupId = "id-123";
const testConstruct = new SampleConstruct(stack, "TestConstruct",
srcSecurityGroupId: srcSecurityGroupId
);
expect(stack).to(
haveResource(
"AWS::EC2::SecurityGroupIngress",
IpProtocol: "tcp",
FromPort: 22,
ToPort: 22,
SourceSecurityGroupId: srcSecurityGroupId,
GroupId:
"Fn::GetAtt": [testConstruct.securityGroup.logicalId, "GroupId"], // Can't do this
,
,
undefined,
true
)
);
);
这里的问题是测试是针对合成的 CloudFormation 模板进行验证的,因此,如果您想验证此构造创建的安全组是否具有允许从 srcSecurityGroup
访问的规则,您需要 Logical ID 的作为 Construct 的一部分创建的安全组。
您可以在此处生成的 CloudFormation 模板中看到这一点。
"Type": "AWS::EC2::SecurityGroupIngress",
"Properties":
"IpProtocol": "tcp",
"FromPort": 22,
"GroupId":
"Fn::GetAtt": [
"TestConstructSecurityGroup95EF3F0F", <-- This
"GroupId"
]
,
"SourceSecurityGroupId": "id-123",
"ToPort": 22
Fn::GetAtt
是这个问题的症结所在。由于这些测试实际上只是进行对象比较,因此您需要能够复制 Fn::Get
调用,这需要 CloudFormation 逻辑 ID。
请注意,CDK确实为您提供了handful of identifiers。
唯一 ID 提供了非常接近的东西,但它与 CloudFormation 堆栈中使用的标识符不同。例如,securityGroup.uniqueId
返回 TestStackTestConstructSecurityGroup10D493A7
,而 CloudFormation 模板显示 TestConstructSecurityGroup95EF3F0F
。您可以注意到不同之处在于 uniqueId
将构造 ID 附加到逻辑标识符中,并且附加的哈希在每个中都不同。
构造 ID 只是您在实例化构造时提供的标识符。它也不是逻辑 ID,尽管它被用作逻辑 ID 的一部分。我还没有看到直接从构造中以编程方式检索此 ID 的方法。您当然可以在某处定义 ID 并重复使用它,但这仍然不能解决它与逻辑 ID 不完全匹配的问题。在这种情况下,SecurityGroup
作为构造 ID,TestConstructSecurityGroup95EF3F0F
作为合成模板中的逻辑 ID。
有没有直接的方法获取 CDK 资源的逻辑 ID?
【问题讨论】:
【参考方案1】:写完整篇文章并深入研究 CDK 代码后,我偶然发现了我正在寻找的答案。如果有人有更好的方法从更高级别的 CDK 构造中获取逻辑 ID,我们将不胜感激。
如果您需要获取 CDK 资源的逻辑 ID,您可以执行以下操作:
const stack = new Stack();
const construct = new SampleConstruct(stack, "SampleConstruct");
const logicalId = stack.getLogicalId(construct.securityGroup.node.defaultChild as CfnSecurityGroup);
请注意,您已经有一个 CloudFormation 资源(例如以 Cfn
开头的资源),那么它会容易一些。
// Pretend construct.securityGroup is of type CfnSecurityGroup
const logicalId = stack.getLogicalId(construct.securityGroup);
【讨论】:
【参考方案2】:除了来自 jaredready 的出色回答,您还可以使用 resource.node.default_child.overrideLogicalId("AnyStringHere")
显式设置逻辑 ID
这可能会更容易,因为您可以设置一次并使用硬编码字符串,而不是为每个测试查找值。
【讨论】:
【参考方案3】:从我的测试来看,stack.getLogicalId
似乎总是会返回原来的,CDK 分配的logicalId,如果你调用overrideLogicalId
,它不会改变,所以它不会总是匹配合成的输出。
这对我有用,即使设置了 logicalId 覆盖:
stack.resolve((construct.node.defaultChild as cdk.CfnElement).logicalId)
stack.resolve
是必需的,因为.logicalId
是一个令牌。
【讨论】:
以上是关于如何使用 CDK 获取资源的逻辑 ID?的主要内容,如果未能解决你的问题,请参考以下文章
AWS CDK - 如何将 Access Key Secret 和 Secret Key Id 作为 Env Param 传递给容器