aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.59k stars 3.89k forks source link

(assertions): Cannot run tests with VpcEndpointServiceDomainName #18739

Closed fitzchak closed 2 years ago

fitzchak commented 2 years ago

What is the problem?

I cannot run tests with VpcEndpointServiceDomainName as in case I have two tests it will throw the following:

Cannot create a VpcEndpointServiceDomainName for service testuseast1ClientEndpointServiceDBD8CB6F, another VpcEndpointServiceDomainName (subdoamin.test.com) is already associated with it

Reproduction Steps

In order to reproduce please create the following 2 files and run one of the tests:

client-stack.ts:

import { Stack, StackProps } from "aws-cdk-lib";
import { Vpc, VpcEndpointService } from "aws-cdk-lib/aws-ec2";
import { NetworkLoadBalancer } from "aws-cdk-lib/aws-elasticloadbalancingv2";
import { PublicHostedZone, VpcEndpointServiceDomainName } from "aws-cdk-lib/aws-route53";
import { Construct } from "constructs";

export interface ClientStackProps extends StackProps {
  readonly stageName: string;
}

export class ClientStack extends Stack {
  constructor(scope: Construct, id: string, props: ClientStackProps) {
    super(scope, id, props);

    const vpc = new Vpc(this, "Vpc", {
    });

    const domain = "test.com";
    const subdomain = `subdoamin.${domain}`;

    const zone = new PublicHostedZone(this, "DevopsHostedZone", {
      zoneName: domain,
    });

    const networkLoadBalancer = new NetworkLoadBalancer(this, "NetworkLoadBalancer", {
      vpc,
      internetFacing: false,
      crossZoneEnabled: true,
    });

    const endpointService = new VpcEndpointService(this, "EndpointService", {
      vpcEndpointServiceLoadBalancers: [networkLoadBalancer],
    });

    new VpcEndpointServiceDomainName(this, "EndpointServiceDomain", {
      endpointService,
      domainName: subdomain,
      publicHostedZone: zone,
    });
  }
}

client-stack.test.ts

import { App } from "aws-cdk-lib";
import { Template } from "aws-cdk-lib/assertions";
import { ClientStack } from "../lib/client-stack";
import { Constants } from "../lib/constants";

describe("client stack", () => {
  const app = new App();
  const stack = new ClientStack(app, `test-${Constants.defaultRegion}-Client`, {
    stageName: "DEV",
  });

  it("matches to snapshot", () => {
    const template = Template.fromStack(stack);
    expect(template).toMatchSnapshot();
  });
});

describe("client stack - PROD", () => {
  const app = new App();
  const stack = new ClientStack(app, `test-${Constants.defaultRegion}-Client`, {
    stageName: "PROD",
  });

  it("matches to snapshot", () => {
    const template = Template.fromStack(stack);
    expect(template).toMatchSnapshot();
  });
});

What did you expect to happen?

I expect the test to pass

What actually happened?

The test is failing with Cannot create a VpcEndpointServiceDomainName for service testuseast1ClientEndpointServiceDBD8CB6F, another VpcEndpointServiceDomainName (subdoamin.test.com) is already associated with it error.

Looks like the validation is not correct as it picking the duplication from the other test.

CDK CLI Version

2.0.8

Framework Version

No response

Node.js Version

14.16.1

OS

Mac

Language

Typescript

Language Version

No response

Other information

No response

njlynch commented 2 years ago

Thanks for filing this bug.

The VpcEndpointServiceDomainName keeps global list of domains to prevent accidental association of two domains with a single service. The uniqueness of the service is determined by the service's uniqueId, which is determined by the types and IDs of all of the nodes in the tree leading up to, and including, the service.

In the case of your tests, a simple workaround is simply to give the Stacks a different ID:

  const stack = new ClientStack(app, `test-${Constants.defaultRegion}-Client-PROD`, {
    stageName: "PROD",
  });

This will cause the IDs of the VpcEndpointService to be different, which will allow the test to pass.

Give that a shot, and let us know if that solves the issue for you.

github-actions[bot] commented 2 years ago

This issue has not received a response in a while. If you want to keep this issue open, please leave a comment below and auto-close will be canceled.

fitzchak commented 2 years ago

Thanks @njlynch, this indeed solved the issue. I suggest to add this info to the error message as this will mostly fail from tests.

github-actions[bot] commented 2 years ago

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.