web-dev-qa-db-fra.com

Comment obtenir un identifiant logique de la ressource avec CDK?

J'essaie d'écrire un peu tests pour une construction CDK valide les règles du groupe de sécurité définies dans le cadre de la construction.

La construction ressemble à quelque chose comme ce qui suit.

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));
  }
}

Et je veux écrire un test qui ressemble à quelque chose comme ce qui suit.

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
    )
  );
});

Le problème ici est que le test est validé par rapport au modèle de cloudformation synthétisé, de sorte que si vous souhaitez vérifier que le groupe de sécurité créé par cette construction a une règle permettant l'accès de srcSecurityGroup, vous avez besoin du logique ID du groupe de sécurité créé dans le cadre de la construction.

Vous pouvez voir cela dans le modèle de cloudformation généré ici.

{
  "Type": "AWS::EC2::SecurityGroupIngress",
  "Properties": {
    "IpProtocol": "tcp",
    "FromPort": 22,
    "GroupId": {
      "Fn::GetAtt": [
        "TestConstructSecurityGroup95EF3F0F", <-- This
        "GroupId"
      ]
    },
    "SourceSecurityGroupId": "id-123",
    "ToPort": 22
  }
}

Ce Fn::GetAtt est le creux de ce problème. Puisque ces tests font vraiment une comparaison d'objet, vous devez être capable de reproduire le Fn::Get Invocation, ce qui nécessite l'identifiant logique de la cloudalisation.


Notez que le CDK fait fournit une poignée d'identificateurs pour vous.

  • ID unique fournit quelque chose de très proche, mais ce n'est pas le même identifiant utilisé dans la pile de cloudations. Par exemple, securityGroup.uniqueId Retour TestStackTestConstructSecurityGroup10D493A7 Alors que le modèle de formation cloud affiche TestConstructSecurityGroup95EF3F0F. Vous pouvez noter que les différences sont le uniqueId _ compensa l'ID de construction à l'identifiant logique et le hachage annexe est différent dans chaque.
  • Construire ID n'est que l'identifiant que vous fournissez lors de l'instancitation d'une construction. Ce n'est pas l'identifiant logique non plus, bien qu'il soit utilisé dans le cadre de l'ID logique. Je n'ai pas non plus vu de manière à récupérer de manière programmable cet identifiant de la construction directement. Vous pouvez bien sûr définir l'identifiant quelque part et simplement le réutiliser, mais cela ne résout toujours pas que le problème ne correspond pas parfaitement à l'ID logique. Dans ce cas, c'est une différence de SecurityGroup comme identifiant de construction et TestConstructSecurityGroup95EF3F0F comme identifiant logique dans le modèle synthétisé.

Y a-t-il une manière simple obtenir l'identifiant logique des ressources CDK?

7
jaredready

Après avoir écrit ce poste entier et creuser par le CDK Code, je suis tombé sur la réponse que je cherchais. Si quelqu'un a une meilleure approche pour obtenir l'identifiant logique à partir d'une construction de CDK de niveau supérieur, la contribution serait beaucoup apprécié.

Si vous devez obtenir l'ID logique d'une ressource CDK, vous pouvez procéder comme suit:

const stack = new Stack();
const construct = new SampleConstruct(stack, "SampleConstruct");
const logicalId = stack.getLogicalId(construct.securityGroup.node.defaultChild as CfnSecurityGroup);

Notez que vous avez déjà une ressource de cloudation (par exemple, quelque chose qui commence par avec Cfn) alors c'est un peu plus facile.

// Pretend construct.securityGroup is of type CfnSecurityGroup
const logicalId = stack.getLogicalId(construct.securityGroup);
2
jaredready