From 3bad98f9cafa88c4c8a26502798afea3c3f0e146 Mon Sep 17 00:00:00 2001 From: Massimo Prencipe Date: Fri, 4 Jun 2021 20:04:12 +0300 Subject: [PATCH] fix(events): AwsApi warns if service does not exist (#13352) Check against AWS SDK that the given service and action exist. If a service acronym is supplied check if it needs to be uppercased, e.g. rds to RDS. Fixes #13090. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- package.json | 2 + .../aws-events-targets/lib/aws-api.ts | 15 ++++++++ .../test/aws-api/aws-api.test.ts | 38 ++++++++++++++++--- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index a465b3f433d86..ddd49a146f393 100644 --- a/package.json +++ b/package.json @@ -97,6 +97,8 @@ "@aws-cdk/core/minimatch/**", "@aws-cdk/cx-api/semver", "@aws-cdk/cx-api/semver/**", + "@aws-cdk/aws-events-targets/aws-sdk", + "@aws-cdk/aws-events-targets/aws-sdk/**", "@aws-cdk/yaml-cfn/yaml", "@aws-cdk/yaml-cfn/yaml/**", "aws-cdk-lib/@balena/dockerignore", diff --git a/packages/@aws-cdk/aws-events-targets/lib/aws-api.ts b/packages/@aws-cdk/aws-events-targets/lib/aws-api.ts index 90f8059afebfb..c5b524b3003d4 100644 --- a/packages/@aws-cdk/aws-events-targets/lib/aws-api.ts +++ b/packages/@aws-cdk/aws-events-targets/lib/aws-api.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import * as events from '@aws-cdk/aws-events'; import * as iam from '@aws-cdk/aws-iam'; import * as lambda from '@aws-cdk/aws-lambda'; +import { Annotations } from '@aws-cdk/core'; import { metadata } from './sdk-api-metadata.generated'; import { addLambdaPermission } from './util'; @@ -89,6 +90,8 @@ export class AwsApi implements events.IRuleTarget { lambdaPurpose: 'AWS', }); + checkServiceExists(this.props.service, handler); + if (this.props.policyStatement) { handler.addToRolePolicy(this.props.policyStatement); } else { @@ -117,6 +120,18 @@ export class AwsApi implements events.IRuleTarget { } } +/** + * Check if the given service exists in the AWS SDK. If not, a warning will be raised. + * @param service Service name + */ +function checkServiceExists(service: string, handler: lambda.SingletonFunction) { + const sdkService = awsSdkMetadata[service.toLowerCase()]; + if (!sdkService) { + Annotations.of(handler).addWarning(`Service ${service} does not exist in the AWS SDK. Check the list of available \ +services and actions from https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/index.html`); + } +} + /** * Transform SDK service/action to IAM action using metadata from aws-sdk module. */ diff --git a/packages/@aws-cdk/aws-events-targets/test/aws-api/aws-api.test.ts b/packages/@aws-cdk/aws-events-targets/test/aws-api/aws-api.test.ts index e43c9708574fc..c605dfa64e992 100644 --- a/packages/@aws-cdk/aws-events-targets/test/aws-api/aws-api.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/aws-api/aws-api.test.ts @@ -1,4 +1,4 @@ -import { countResources, expect, haveResource } from '@aws-cdk/assert-internal'; +import { countResources, expect as cdkExpect, haveResource, SynthUtils } from '@aws-cdk/assert-internal'; import * as events from '@aws-cdk/aws-events'; import * as iam from '@aws-cdk/aws-iam'; import { Stack } from '@aws-cdk/core'; @@ -32,7 +32,7 @@ test('use AwsApi as an event rule target', () => { })); // THEN - expect(stack).to(haveResource('AWS::Events::Rule', { + cdkExpect(stack).to(haveResource('AWS::Events::Rule', { Targets: [ { Arn: { @@ -73,9 +73,9 @@ test('use AwsApi as an event rule target', () => { })); // Uses a singleton function - expect(stack).to(countResources('AWS::Lambda::Function', 1)); + cdkExpect(stack).to(countResources('AWS::Lambda::Function', 1)); - expect(stack).to(haveResource('AWS::IAM::Policy', { + cdkExpect(stack).to(haveResource('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -112,7 +112,7 @@ test('with policy statement', () => { })); // THEN - expect(stack).to(haveResource('AWS::Events::Rule', { + cdkExpect(stack).to(haveResource('AWS::Events::Rule', { Targets: [ { Arn: { @@ -130,7 +130,7 @@ test('with policy statement', () => { ], })); - expect(stack).to(haveResource('AWS::IAM::Policy', { + cdkExpect(stack).to(haveResource('AWS::IAM::Policy', { PolicyDocument: { Statement: [ { @@ -143,3 +143,29 @@ test('with policy statement', () => { }, })); }); + +test('with service not in AWS SDK', () => { + // GIVEN + const stack = new Stack(); + const rule = new events.Rule(stack, 'Rule', { + schedule: events.Schedule.expression('rate(15 minutes)'), + }); + const awsApi = new targets.AwsApi({ + service: 'no-such-service', + action: 'no-such-action', + policyStatement: new iam.PolicyStatement({ + actions: ['s3:GetObject'], + resources: ['resource'], + }), + }); + + // WHEN + rule.addTarget(awsApi); + + // THEN + const assembly = SynthUtils.synthesize(stack); + expect(assembly.messages.length).toBe(1); + const message = assembly.messages[0]; + expect(message.entry.type).toBe('aws:cdk:warning'); + expect(message.entry.data).toBe('Service no-such-service does not exist in the AWS SDK. Check the list of available services and actions from https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/index.html'); +});