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

(aws-sns): Tests fail with: Only root constructs may have an empty name #13121

Closed
jpSimkins opened this issue Feb 17, 2021 · 3 comments
Closed
Assignees
Labels
@aws-cdk/aws-sns Related to Amazon Simple Notification Service guidance Question that needs advice or information. needs-triage This issue or PR still needs to be triaged.

Comments

@jpSimkins
Copy link

❓ General Issue

I have built a library to use and it works great. I am updating the tests and I am running into an issue that I am not sure if it's a bug or if perhaps there is something I am doing wrong.

When running my tests I am getting this error:

FAIL tests/project.with-base.test.ts
  ● Test suite failed to run

    Only root constructs may have an empty name

      134 |       // Loop over and add the emails
      135 |       for (const email of olypipeline.notifications.emails.manualApproval) {
    > 136 |         this.manualApproval.addSubscription(new EmailSubscription(email));
          |                             ^
      137 |       }
      138 |     }
      139 |   }

      at new Node (../../node_modules/constructs/src/construct.ts:71:15)
      at new ConstructNode (../../node_modules/@aws-cdk/core/lib/construct-compat.ts:277:24)
      at Object.createNode (../../node_modules/@aws-cdk/core/lib/construct-compat.ts:71:11)
      at new Construct (../../node_modules/constructs/src/construct.ts:575:26)
      at new Construct (../../node_modules/@aws-cdk/core/lib/construct-compat.ts:68:5)
      at new Resource (../../node_modules/@aws-cdk/core/lib/resource.ts:115:5)
      at new Subscription (../../node_modules/@aws-cdk/aws-sns/lib/subscription.ts:82:5)
      at Topic.addSubscription (../../node_modules/@aws-cdk/aws-sns/lib/topic-base.ts:84:5)
      at PipelineSnsTopics._applyNotifications_ManualApproval (src/lib/PipelineSnsTopics.ts:136:29)
      at new PipelineSnsTopics (src/lib/PipelineSnsTopics.ts:41:10)
      at new OlyPipeline (src/index.ts:226:22)
      at Object.<anonymous> (tests/project.with-base.test.ts:62:26)

The code in question is:

this.manualApproval = new Topic(olypipeline.scope, 'ManualApproval-' + olypipeline.id);
...
// Loop over and add the emails
for (const email of olypipeline.notifications.emails.manualApproval) {
  this.manualApproval.addSubscription(new EmailSubscription(email));
}

Basically, I have a string[] that I am using to allow for emails to be subscribed to an SNS Topic. This works fine but for some reason, the tests fail with the error above.

The Question

What is causing this to happen? There is no name to fill for a subscription so I am not sure of how to resolve this failure.

The code works and I am able to deploy with everything working as expected. For some reason, just the tests fail.

Environment

  • CDK CLI Version : 1.89.0 (build df7253c)
  • Module Version : 1.89.0
  • Node.js Version : v14.15.5
  • OS : Linux Zeus 5.8.0-43-generic Cross-region/account references #49~20.04.1-Ubuntu SMP Fri Feb 5 09:57:56 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
  • Language (Version): Typescript (6.14.11)

Other information

It needs to be noted, that I am doing the same thing in the code 2 other times and there are no errors thrown for those, just the last one.

The entire file is:

import { Code, Function, Runtime } from '@aws-cdk/aws-lambda';
import { Topic } from '@aws-cdk/aws-sns';
import { EmailSubscription, LambdaSubscription } from '@aws-cdk/aws-sns-subscriptions';

// Local files
import {
  OlyPipeline,
  lambdaCodeBuildStatusChange,
  lambdaCodeEventBridgePipeline,
  lambdaManualApproval,
} from '../index';

/**
 * Defines SNS Topic for the pipeline.
 */
export class PipelineSnsTopics {
  readonly eventBridgePipeline: Topic;
  readonly codeBuild: Topic;
  readonly manualApproval: Topic;

  /**
   * Builds the Topics and defines the notifications
   * @param pipeline
   * @param environment
   */
  constructor(olypipeline: OlyPipeline) {
    // Add Pipeline EventBridge Topic
    this.eventBridgePipeline = new Topic(
      olypipeline.scope,
      'EventBridgePipeline-' + olypipeline.id,
    );
    this._applyNotifications_EventBridgePipeline(olypipeline);

    // Add Build Topic
    this.codeBuild = new Topic(olypipeline.scope, 'CodeBuild-' + olypipeline.id);
    this._applyNotifications_CodeBuild(olypipeline);

    // Add Manual approval topic
    // TODO: currently, this topic is defined even when a pipeline has no manual approval. Would like to resolve that.
    this.manualApproval = new Topic(olypipeline.scope, 'ManualApproval-' + olypipeline.id);
    this._applyNotifications_ManualApproval(olypipeline);
  }

  /**
   * Apply notifications to event bridge pipeline topic
   * @param olypipeline
   */
  private _applyNotifications_EventBridgePipeline(olypipeline: OlyPipeline): void {
    // If we have a webhook, add the lambda to parse it
    if (olypipeline.notifications?.webhooks && olypipeline.notifications.webhooks.pipelineEvents) {
      // Event Bridge for Pipeline
      const _fnLambdaEventBridgePipeline = new Function(
        olypipeline.scope,
        'lambdaCodeEventBridgePipeline',
        {
          runtime: Runtime.PYTHON_3_6,
          handler: 'index.lambda_handler',
          code: Code.fromInline(lambdaCodeEventBridgePipeline()),
          environment: {
            WEBHOOK: olypipeline.notifications.webhooks.pipelineEvents.toString(), // converts array to string, this is intentional
            PIPELINE_NAME: olypipeline.id,
          },
        },
      );
      // Subscribe lambda to topic
      this.eventBridgePipeline.addSubscription(
        new LambdaSubscription(_fnLambdaEventBridgePipeline),
      );
    }
    // Check if we have notification emails
    if (olypipeline.notifications?.emails && olypipeline.notifications.emails.pipelineEvents) {
      // Loop over and add the emails
      for (const email of olypipeline.notifications.emails.pipelineEvents) {
        this.eventBridgePipeline.addSubscription(new EmailSubscription(email));
      }
    }
  }

  /**
   * Apply notifications to codebuild topic
   * @param pipeline
   */
  private _applyNotifications_CodeBuild(olypipeline: OlyPipeline): void {
    // If we have a webhook, add the lambda to parse it
    if (olypipeline.notifications?.webhooks && olypipeline.notifications.webhooks.codebuildEvents) {
      // Manual Approval Lambda
      const _fnLambdaCodeBuildStatusChange = new Function(
        olypipeline.scope,
        'lambdaCodeBuildStatusChange',
        {
          runtime: Runtime.PYTHON_3_6,
          handler: 'index.lambda_handler',
          code: Code.fromInline(lambdaCodeBuildStatusChange()),
          environment: {
            WEBHOOK: olypipeline.notifications.webhooks.codebuildEvents.toString(), // converts array to string, this is intentional
            PIPELINE_NAME: olypipeline.id,
          },
        },
      );
      // Subscribe lambda to topic
      this.codeBuild.addSubscription(new LambdaSubscription(_fnLambdaCodeBuildStatusChange));
    }
    // Check if we have notification emails
    if (olypipeline.notifications?.emails && olypipeline.notifications.emails.codebuildEvents) {
      // Loop over and add the emails
      for (const email of olypipeline.notifications.emails.codebuildEvents) {
        this.codeBuild.addSubscription(new EmailSubscription(email));
      }
    }
  }

  /**
   * Apply notifications to manual approval topic
   * @param pipeline
   */
  private _applyNotifications_ManualApproval(olypipeline: OlyPipeline): void {
    // If we have a webhook, add the lambda to parse it
    if (olypipeline.notifications?.webhooks && olypipeline.notifications.webhooks.manualApproval) {
      // Manual Approval Lambda
      const _fnLambdaManualApproval = new Function(olypipeline.scope, 'lambdaManualApproval', {
        runtime: Runtime.PYTHON_3_6,
        handler: 'index.lambda_handler',
        code: Code.fromInline(lambdaManualApproval()),
        environment: {
          WEBHOOK: olypipeline.notifications.webhooks.manualApproval.toString(), // converts array to string, this is intentional
          PIPELINE_NAME: olypipeline.id,
        },
      });
      // Subscribe lambda to topic
      this.manualApproval.addSubscription(new LambdaSubscription(_fnLambdaManualApproval));
    }
    // Check if we have notification emails
    if (olypipeline.notifications?.emails && olypipeline.notifications.emails.manualApproval) {
      // Loop over and add the emails
      for (const email of olypipeline.notifications.emails.manualApproval) {
        this.manualApproval.addSubscription(new EmailSubscription(email));
      }
    }
  }
}
@jpSimkins jpSimkins added guidance Question that needs advice or information. needs-triage This issue or PR still needs to be triaged. labels Feb 17, 2021
@github-actions github-actions bot added the @aws-cdk/aws-sns Related to Amazon Simple Notification Service label Feb 17, 2021
@jpSimkins
Copy link
Author

Ok, this was something stupid on my part... my test had an empty string for the email as I forgot to fill it out. The empty string is what triggered this error. A bit misleading for the error so I would suggest to update that message to state the email is empty as this is an issue with the EmailSubscription construct. Other than that, this was just an issue on my end.

@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.

@dskiran2018
Copy link

Error: Only root constructs may have an empty name
at new Node (C:\Users\kirankumar.dangeti\Desktop\myproject\Aurora_project\DiMeldewesen\Digitalesmeldewesen_lambda\node_modules\constructs\src\construct.ts:71:15)
at new ConstructNode (C:\Users\kirankumar.dangeti\Desktop\myproject\Aurora_project\DiMeldewesen\Digitalesmeldewesen_lambda\node_modules@aws-cdk\core\lib\construct-compat.ts:277:24)
at Object.createNode (C:\Users\kirankumar.dangeti\Desktop\myproject\Aurora_project\DiMeldewesen\Digitalesmeldewesen_lambda\node_modules@aws-cdk\core\lib\construct-compat.ts:71:11)
at new Construct (C:\Users\kirankumar.dangeti\Desktop\myproject\Aurora_project\DiMeldewesen\Digitalesmeldewesen_lambda\node_modules\constructs\src\construct.ts:575:26)
at new Construct (C:\Users\kirankumar.dangeti\Desktop\myproject\Aurora_project\DiMeldewesen\Digitalesmeldewesen_lambda\node_modules@aws-cdk\core\lib\construct-compat.ts:68:5)
at new Resource (C:\Users\kirankumar.dangeti\Desktop\myproject\Aurora_project\DiMeldewesen\Digitalesmeldewesen_lambda\node_modules@aws-cdk\core\lib\resource.ts:127:5)
at new SecurityGroupBase (C:\Users\kirankumar.dangeti\Desktop\myproject\Aurora_project\DiMeldewesen\Digitalesmeldewesen_lambda\node_modules@aws-cdk\aws-ec2\lib\security-group.ts:70:5)
at new MutableImport (C:\Users\kirankumar.dangeti\Desktop\myproject\Aurora_project\DiMeldewesen\Digitalesmeldewesen_lambda\node_modules@aws-cdk\aws-ec2\lib\security-group.js:257:17)
at Function.fromSecurityGroupId (C:\Users\kirankumar.dangeti\Desktop\myproject\Aurora_project\DiMeldewesen\Digitalesmeldewesen_lambda\node_modules@aws-cdk\aws-ec2\lib\security-group.ts:359:9)
at new DigitalesmeldewesenLambdaStack (C:\Users\kirankumar.dangeti\Desktop\myproject\Aurora_project\DiMeldewesen\Digitalesmeldewesen_lambda\lib\digitalesmeldewesen_lambda-stack.ts:52:32)
Subprocess exited with error 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-sns Related to Amazon Simple Notification Service guidance Question that needs advice or information. needs-triage This issue or PR still needs to be triaged.
Projects
None yet
Development

No branches or pull requests

3 participants