如何用CDK获取资源的逻辑ID?

问题描述 投票:1回答:1

我试图写一些 测试 的 CDK 构造,以验证作为该构造一部分定义的安全组规则。

这个构造看起来像下面的东西。

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,你需要的是 逻辑ID 的安全组,该安全组是作为构造的一部分创建的。

您可以在此处生成的 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 Logical ID。


请注意,CDK 是否 提供 少数识别器 为您提供。

  • Unique ID 提供了非常接近的东西,但它与 CloudFormation 堆栈中使用的标识符不同。例如 securityGroup.uniqueId 返回 TestStackTestConstructSecurityGroup10D493A7 而CloudFormation模板则显示 TestConstructSecurityGroup95EF3F0F. 你可以注意到的区别是 uniqueId 将Construct ID预先添加到逻辑标识符上,并且每个附加的哈希值都不同。
  • 构造ID只是你在实例化一个构造时提供的标识符,它也不是逻辑ID,尽管它被用作逻辑ID的一部分。它也不是逻辑ID,虽然它被用作逻辑ID的一部分。我也没有看到一种方法可以直接从构造体中以编程方式检索这个ID。当然,你可以在某个地方定义这个ID,然后重用它就可以了,但这仍然不能解决它与逻辑ID不完全匹配的问题。在这种情况下,这就是一个不同的 SecurityGroup 作为构造ID和 TestConstructSecurityGroup95EF3F0F 作为合成模板中的逻辑ID。

有没有一种直接的方法来获取CDK资源的逻辑ID?

amazon-web-services amazon-cloudformation aws-cdk
1个回答
2
投票

在写完这整篇帖子并翻阅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);
热门问题
推荐问题
最新问题