Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(integ-tests): Can't make two awsApiCall for the same service and api in a given context #22043

Closed
dontirun opened this issue Sep 14, 2022 · 3 comments · Fixed by #27380
Closed
Labels
@aws-cdk/assertions Related to the @aws-cdk/assertv2 package bug This issue is a bug. effort/small Small work item – less than a day of effort p2

Comments

@dontirun
Copy link
Contributor

dontirun commented Sep 14, 2022

Describe the bug

While fumbling around with integration tests I received the following error

Error: There is already a Construct with name 'AwsApiCallRedshiftdescribeClusters' in Stack [DeployAssert]

I believe this is because I had two calls for the same service and api

Expected Behavior

I can make two calls to the same service API combo

Current Behavior

I can't make two calls to the same service API combo

Reproduction Steps

import * as integ from '@aws-cdk/integ-tests';
import * as cdk from '@aws-cdk/core';

const app = new cdk.App();
const stack = new cdk.Stack(app, 'aws-cdk-redshift-cluster-database');


const test = new integ.IntegTest(app, 'aws-cdk-redshift-reboot-test', {
  testCases: [stack],
  stackUpdateWorkflow: true,
  diffAssets: true,
});


const describe = test.assertions.awsApiCall('Redshift', 'describeClusters', {
  ClusterIdentifier: cluster.clusterName,
});

const describe2 = test.assertions.awsApiCall('Redshift', 'describeClusters', {
  ClusterIdentifier: cluster.clusterName,
});

Possible Solution

return new AwsApiCall(this.scope, `AwsApiCall${service}${api}`, {

Maybe something like this?

  private static serviceAPICounter = new Map<string, number>();

...

  public awsApiCall(service: string, api: string, parameters?: any): IAwsApiCall {
    let combo = `AwsApiCall${service}${api}`
    const count = (DeployAssert.serviceAPICounter.get(combo) ?? 0) + 1
    DeployAssert.serviceAPICounter.set(combo, count)
    return new AwsApiCall(this.scope, `${combo}${count}`, {
      api,
      service,
      parameters,
    });
  }

Additional Information/Context

No response

CDK CLI Version

2.41.0

Framework Version

No response

Node.js Version

v16.16.0

OS

OsX

Language

Typescript

Language Version

No response

Other information

No response

@dontirun dontirun added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Sep 14, 2022
@github-actions github-actions bot added the @aws-cdk/assertions Related to the @aws-cdk/assertv2 package label Sep 14, 2022
@peterwoodworth peterwoodworth added p2 effort/small Small work item – less than a day of effort and removed needs-triage This issue or PR still needs to be triaged. labels Sep 15, 2022
@peterwoodworth
Copy link
Contributor

Thanks for the report @dontirun,

We could either change how the logical id is built altogether (which would change the logical id for existing instances so we'd likely need a feature flag), or what's more preferable is to somehow detect if the same API call has already been used, and then adjusting the logical ID from there if that's the case. However I'm not sure how feasible the latter is without looking more into it

@misterjoshua
Copy link
Contributor

misterjoshua commented Oct 2, 2023

While not generally advisable, I'm working around this right now by importing from DeployAssert:

import { AwsApiCall, IntegTest } from '@aws-cdk/integ-tests-alpha';
import { DeployAssert } from '@aws-cdk/integ-tests-alpha/lib/assertions/private/deploy-assert';

// ...

declare const integTest: IntegTest;

const deployAssert = integTest.assertions;
if (!DeployAssert.isDeployAssert(deployAssert)) {
  throw new Error('Expected DeployAssert');
}

// Extract the assertion scope from the DeployAssert because upstream
// implementation fails to allow multiples of the same aws api call
// due to insufficient uniqueness in the logical ids.
const assertionScope = deployAssert.scope;

const assertion1 = new AwsApiCall(assertionScope, 'First', {
  service: 'TheService',
  api: 'theApi',
  parameters: { /* ... */ },
});

const assertion2 = new AwsApiCall(assertionScope, 'Second', {
  service: 'TheService',
  api: 'theApi',
  parameters: { /* ... */ },
});

Edit: I've proposed a backward-compatible PR, hoping to fix the issue at its root. You can find it below.

@mergify mergify bot closed this as completed in #27380 Oct 10, 2023
mergify bot pushed a commit that referenced this issue Oct 10, 2023
This PR resolves errors in the integration test library when users run identical assertions multiple times.

This change ensures that each use of `awsApiCall`, `httpApiCall`, and `invokeFunction` has a unique identifier, even when multiple identical assertions are used in the same context. We introduced a `uniqueAssertionId` function in the `DeployAssert` construct that maintains backward compatibility with the old id rendering scheme, but prevents the use of conflicting construct ids by tracking the usage of ids and differentiating them where there's a conflict.

Closes #22043, #23049

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
@github-actions
Copy link

⚠️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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/assertions Related to the @aws-cdk/assertv2 package bug This issue is a bug. effort/small Small work item – less than a day of effort p2
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants