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.
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.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?
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);