diff --git a/API.md b/API.md index c7360c5c..60c0bb0e 100644 --- a/API.md +++ b/API.md @@ -3260,6 +3260,7 @@ const controlPlaneProps: ControlPlaneProps = { ... } | billing | IBilling | The billing provider configuration. | | disableAPILogging | boolean | If true, the API Gateway will not log requests to the CloudWatch Logs. | | eventManager | IEventManager | The event manager instance. | +| metering | IMetering | The metering provider configuration. | | systemAdminName | string | The name of the system admin user. | | systemAdminRoleName | string | The name of the system admin role. | @@ -3342,6 +3343,18 @@ If not provided, a new instance will be created. --- +##### `metering`Optional + +```typescript +public readonly metering: IMetering; +``` + +- *Type:* IMetering + +The metering provider configuration. + +--- + ##### `systemAdminName`Optional ```typescript @@ -4803,10 +4816,10 @@ Encapsulates the list of properties for an IBilling construct. | **Name** | **Type** | **Description** | | --- | --- | --- | -| createCustomerFunction | aws-cdk-lib.aws_lambda.IFunction \| IFunctionTrigger | The function to trigger to create a new customer. | -| deleteCustomerFunction | aws-cdk-lib.aws_lambda.IFunction \| IFunctionTrigger | The function to trigger to delete a customer. | -| createUserFunction | aws-cdk-lib.aws_lambda.IFunction \| IFunctionTrigger | The function to trigger to create a new user. | -| deleteUserFunction | aws-cdk-lib.aws_lambda.IFunction \| IFunctionTrigger | The function to trigger to delete a user. | +| createCustomerFunction | IFunctionTrigger \| aws-cdk-lib.aws_lambda.IFunction | The function to trigger to create a new customer. | +| deleteCustomerFunction | IFunctionTrigger \| aws-cdk-lib.aws_lambda.IFunction | The function to trigger to delete a customer. | +| createUserFunction | IFunctionTrigger \| aws-cdk-lib.aws_lambda.IFunction | The function to trigger to create a new user. | +| deleteUserFunction | IFunctionTrigger \| aws-cdk-lib.aws_lambda.IFunction | The function to trigger to delete a user. | | ingestor | IDataIngestorAggregator | The IDataIngestorAggregator responsible for accepting and aggregating the raw billing data. | | putUsageFunction | aws-cdk-lib.aws_lambda.IFunction \| IFunctionSchedule | The function responsible for taking the aggregated data and pushing that to the billing provider. | | webhookFunction | aws-cdk-lib.aws_lambda.IFunction | The function to trigger when a webhook request is received. | @@ -4817,10 +4830,10 @@ Encapsulates the list of properties for an IBilling construct. ##### `createCustomerFunction`Required ```typescript -public readonly createCustomerFunction: IFunction | IFunctionTrigger; +public readonly createCustomerFunction: IFunctionTrigger | IFunction; ``` -- *Type:* aws-cdk-lib.aws_lambda.IFunction | IFunctionTrigger +- *Type:* IFunctionTrigger | aws-cdk-lib.aws_lambda.IFunction The function to trigger to create a new customer. @@ -4831,10 +4844,10 @@ The function to trigger to create a new customer. ##### `deleteCustomerFunction`Required ```typescript -public readonly deleteCustomerFunction: IFunction | IFunctionTrigger; +public readonly deleteCustomerFunction: IFunctionTrigger | IFunction; ``` -- *Type:* aws-cdk-lib.aws_lambda.IFunction | IFunctionTrigger +- *Type:* IFunctionTrigger | aws-cdk-lib.aws_lambda.IFunction The function to trigger to delete a customer. @@ -4845,10 +4858,10 @@ The function to trigger to delete a customer. ##### `createUserFunction`Optional ```typescript -public readonly createUserFunction: IFunction | IFunctionTrigger; +public readonly createUserFunction: IFunctionTrigger | IFunction; ``` -- *Type:* aws-cdk-lib.aws_lambda.IFunction | IFunctionTrigger +- *Type:* IFunctionTrigger | aws-cdk-lib.aws_lambda.IFunction The function to trigger to create a new user. @@ -4859,10 +4872,10 @@ The function to trigger to create a new user. ##### `deleteUserFunction`Optional ```typescript -public readonly deleteUserFunction: IFunction | IFunctionTrigger; +public readonly deleteUserFunction: IFunctionTrigger | IFunction; ``` -- *Type:* aws-cdk-lib.aws_lambda.IFunction | IFunctionTrigger +- *Type:* IFunctionTrigger | aws-cdk-lib.aws_lambda.IFunction The function to trigger to delete a user. @@ -5182,6 +5195,176 @@ The detail-type that will trigger the handler function. --- +### IMetering + +- *Implemented By:* IMetering + +Encapsulates the list of properties for an IMetering construct. + + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| createMeterFunction | aws-cdk-lib.aws_lambda.IFunction | The function to trigger to create a meter -- POST /meters Once created, the meter can be used to track and analyze the specific usage metrics for tenants. | +| fetchUsageFunction | aws-cdk-lib.aws_lambda.IFunction | The function to trigger to get the usage data that has been recorded for a specific meter. | +| ingestUsageEventFunction | IFunctionTrigger \| aws-cdk-lib.aws_lambda.IFunction | The function to trigger to ingest a usage event. | +| cancelUsageEventsFunction | aws-cdk-lib.aws_lambda.IFunction | The function to trigger to exclude specific events from being recorded or included in the usage data. | +| cancelUsageEventsScope | string | The scope required to authorize requests for cancelling usage events. | +| createCustomerFunction | IFunctionTrigger \| aws-cdk-lib.aws_lambda.IFunction | The function to trigger to create a new customer. (Customer in this context is a tenant.). | +| createMeterScope | string | The scope required to authorize requests for creating a new meter. | +| deleteCustomerFunction | IFunctionTrigger \| aws-cdk-lib.aws_lambda.IFunction | The function to trigger to delete a customer. (Customer in this context is a tenant.). | +| fetchUsageScope | string | The scope required to authorize requests for fetching metering usage. | +| updateMeterFunction | aws-cdk-lib.aws_lambda.IFunction | The function to trigger to update a meter -- PUT /meters/meterId. | +| updateMeterScope | string | The scope required to authorize requests for updating a meter. | + +--- + +##### `createMeterFunction`Required + +```typescript +public readonly createMeterFunction: IFunction; +``` + +- *Type:* aws-cdk-lib.aws_lambda.IFunction + +The function to trigger to create a meter -- POST /meters Once created, the meter can be used to track and analyze the specific usage metrics for tenants. + +--- + +##### `fetchUsageFunction`Required + +```typescript +public readonly fetchUsageFunction: IFunction; +``` + +- *Type:* aws-cdk-lib.aws_lambda.IFunction + +The function to trigger to get the usage data that has been recorded for a specific meter. + +- GET /usage/meterId + +--- + +##### `ingestUsageEventFunction`Required + +```typescript +public readonly ingestUsageEventFunction: IFunctionTrigger | IFunction; +``` + +- *Type:* IFunctionTrigger | aws-cdk-lib.aws_lambda.IFunction + +The function to trigger to ingest a usage event. + +Usage events are used to measure and track the usage metrics associated with the meter. + +Default event trigger: INGEST_USAGE + +--- + +##### `cancelUsageEventsFunction`Optional + +```typescript +public readonly cancelUsageEventsFunction: IFunction; +``` + +- *Type:* aws-cdk-lib.aws_lambda.IFunction + +The function to trigger to exclude specific events from being recorded or included in the usage data. + +Used for canceling events that were incorrectly ingested. +-- DELETE /usage + +--- + +##### `cancelUsageEventsScope`Optional + +```typescript +public readonly cancelUsageEventsScope: string; +``` + +- *Type:* string + +The scope required to authorize requests for cancelling usage events. + +--- + +##### `createCustomerFunction`Optional + +```typescript +public readonly createCustomerFunction: IFunctionTrigger | IFunction; +``` + +- *Type:* IFunctionTrigger | aws-cdk-lib.aws_lambda.IFunction + +The function to trigger to create a new customer. (Customer in this context is a tenant.). + +Default event trigger: ONBOARDING_REQUEST + +--- + +##### `createMeterScope`Optional + +```typescript +public readonly createMeterScope: string; +``` + +- *Type:* string + +The scope required to authorize requests for creating a new meter. + +--- + +##### `deleteCustomerFunction`Optional + +```typescript +public readonly deleteCustomerFunction: IFunctionTrigger | IFunction; +``` + +- *Type:* IFunctionTrigger | aws-cdk-lib.aws_lambda.IFunction + +The function to trigger to delete a customer. (Customer in this context is a tenant.). + +Default event trigger: OFFBOARDING_REQUEST + +--- + +##### `fetchUsageScope`Optional + +```typescript +public readonly fetchUsageScope: string; +``` + +- *Type:* string + +The scope required to authorize requests for fetching metering usage. + +--- + +##### `updateMeterFunction`Optional + +```typescript +public readonly updateMeterFunction: IFunction; +``` + +- *Type:* aws-cdk-lib.aws_lambda.IFunction + +The function to trigger to update a meter -- PUT /meters/meterId. + +--- + +##### `updateMeterScope`Optional + +```typescript +public readonly updateMeterScope: string; +``` + +- *Type:* string + +The scope required to authorize requests for updating a meter. + +--- + ### IRoute - *Implemented By:* IRoute @@ -5306,6 +5489,7 @@ events sent across the EventBus. | DEACTIVATE_FAILURE | Event detail type for failed deactivation. | | TENANT_USER_CREATED | Event detail type for user creation on the app-plane side. | | TENANT_USER_DELETED | Event detail type for user deletion on the app-plane side. | +| INGEST_USAGE | Event detail type for ingesting a usage event. | --- @@ -5454,3 +5638,10 @@ should be emitted by the application plane. --- + +##### `INGEST_USAGE` + +Event detail type for ingesting a usage event. + +--- + diff --git a/src/control-plane/billing/billing-interface.ts b/src/control-plane/billing/billing-interface.ts index de16705f..97362471 100644 --- a/src/control-plane/billing/billing-interface.ts +++ b/src/control-plane/billing/billing-interface.ts @@ -3,25 +3,9 @@ import { Schedule } from 'aws-cdk-lib/aws-events'; import { IFunction } from 'aws-cdk-lib/aws-lambda'; -import { DetailType } from '../../utils'; +import { IFunctionTrigger } from '../../utils'; import { IDataIngestorAggregator } from '../ingestor-aggregator/ingestor-aggregator-interface'; -/** - * Optional interface that allows specifying both - * the function to trigger and the event that will trigger it. - */ -export interface IFunctionTrigger { - /** - * The function definition. - */ - readonly handler: IFunction; - - /** - * The detail-type that will trigger the handler function. - */ - readonly trigger: DetailType; -} - /** * Optional interface that allows specifying both * the function to trigger and the schedule by which to trigger it. diff --git a/src/control-plane/billing/billing-provider.ts b/src/control-plane/billing/billing-provider.ts index 9fb137ee..34af9f3f 100644 --- a/src/control-plane/billing/billing-provider.ts +++ b/src/control-plane/billing/billing-provider.ts @@ -6,11 +6,10 @@ import * as apigatewayV2 from 'aws-cdk-lib/aws-apigatewayv2'; import * as apigatewayV2Integrations from 'aws-cdk-lib/aws-apigatewayv2-integrations'; import * as events from 'aws-cdk-lib/aws-events'; import * as targets from 'aws-cdk-lib/aws-events-targets'; -import { IFunction } from 'aws-cdk-lib/aws-lambda'; import { NagSuppressions } from 'cdk-nag'; import { Construct } from 'constructs'; -import { IBilling, IFunctionTrigger } from './billing-interface'; -import { DetailType, IEventManager, addTemplateTag } from '../../utils'; +import { IBilling } from './billing-interface'; +import { DetailType, IEventManager, addTemplateTag, createEventTarget } from '../../utils'; /** * Encapsulates the list of properties for a BillingProvider. @@ -57,29 +56,31 @@ export class BillingProvider extends Construct { super(scope, id); addTemplateTag(this, 'BillingProvider'); - this.createEventTarget( - props.eventManager, - DetailType.ONBOARDING_REQUEST, - props.billing.createCustomerFunction - ); - - this.createEventTarget( - props.eventManager, - DetailType.OFFBOARDING_REQUEST, - props.billing.deleteCustomerFunction - ); - - this.createEventTarget( - props.eventManager, - DetailType.TENANT_USER_CREATED, - props.billing.createUserFunction - ); - - this.createEventTarget( - props.eventManager, - DetailType.TENANT_USER_DELETED, - props.billing.deleteUserFunction - ); + [ + { + defaultFunctionTrigger: DetailType.ONBOARDING_REQUEST, + functionDefinition: props.billing.createCustomerFunction, + }, + { + defaultFunctionTrigger: DetailType.OFFBOARDING_REQUEST, + functionDefinition: props.billing.deleteCustomerFunction, + }, + { + defaultFunctionTrigger: DetailType.TENANT_USER_CREATED, + functionDefinition: props.billing.createUserFunction, + }, + { + defaultFunctionTrigger: DetailType.TENANT_USER_DELETED, + functionDefinition: props.billing.deleteUserFunction, + }, + ].forEach((target) => { + createEventTarget( + this, + props.eventManager, + target.defaultFunctionTrigger, + target.functionDefinition + ); + }); if (props.billing.putUsageFunction) { const schedule = @@ -130,26 +131,4 @@ export class BillingProvider extends Construct { ); } } - - private getFunctionProps( - fn: IFunction | IFunctionTrigger, - defaultTrigger: DetailType - ): IFunctionTrigger { - return 'handler' in fn - ? { handler: fn.handler, trigger: fn.trigger } - : { handler: fn, trigger: defaultTrigger }; - } - - private createEventTarget( - eventManager: IEventManager, - defaultEvent: DetailType, - fn?: IFunction | IFunctionTrigger - ) { - if (!fn) { - return; - } - - const { handler, trigger } = this.getFunctionProps(fn, defaultEvent); - eventManager.addTargetToEvent(this, trigger, new targets.LambdaFunction(handler)); - } } diff --git a/src/control-plane/control-plane.ts b/src/control-plane/control-plane.ts index 495d1947..31a9146b 100644 --- a/src/control-plane/control-plane.ts +++ b/src/control-plane/control-plane.ts @@ -9,6 +9,8 @@ import { IAuth } from './auth/auth-interface'; import { CognitoAuth } from './auth/cognito-auth'; import { BillingProvider, IBilling } from './billing'; import { ControlPlaneAPI } from './control-plane-api'; +import { IMetering } from './metering'; +import { MeteringProvider } from './metering/metering-provider'; import { TenantConfigService } from './tenant-config'; import { TenantManagementService } from './tenant-management/tenant-management.service'; import { UserManagementService } from './user-management/user-management.service'; @@ -44,6 +46,11 @@ export interface ControlPlaneProps { */ readonly billing?: IBilling; + /** + * The metering provider configuration. + */ + readonly metering?: IMetering; + /** * The event manager instance. If not provided, a new instance will be created. */ @@ -140,6 +147,15 @@ export class ControlPlane extends Construct { }); } } + + if (props.metering) { + new MeteringProvider(this, 'Metering', { + metering: props.metering, + api: api, + eventManager: eventManager, + }); + } + this.eventManager = eventManager; // defined suppression here to suppress EventsRole Default policy diff --git a/src/control-plane/index.ts b/src/control-plane/index.ts index f0510a54..630c63d1 100644 --- a/src/control-plane/index.ts +++ b/src/control-plane/index.ts @@ -11,3 +11,4 @@ export * from './ingestor-aggregator/index'; export * from './tenant-config'; export * from './tenant-management'; export * from './user-management'; +export * from './metering'; diff --git a/src/control-plane/metering/index.ts b/src/control-plane/metering/index.ts new file mode 100644 index 00000000..b062d0c4 --- /dev/null +++ b/src/control-plane/metering/index.ts @@ -0,0 +1,4 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +export * from './metering-interface'; diff --git a/src/control-plane/metering/metering-interface.ts b/src/control-plane/metering/metering-interface.ts index 2d36203b..04a19ed7 100644 --- a/src/control-plane/metering/metering-interface.ts +++ b/src/control-plane/metering/metering-interface.ts @@ -2,65 +2,77 @@ // SPDX-License-Identifier: Apache-2.0 import { IFunction } from 'aws-cdk-lib/aws-lambda'; -import { DetailType } from '../../utils'; +import { IFunctionTrigger } from '../../utils'; /** - * Optional interface that allows specifying both - * the function to trigger and the event that will trigger it. + * Encapsulates the list of properties for an IMetering construct. */ -export interface IFunctionTrigger { +export interface IMetering { /** - * The function definition. + * The function to trigger to create a meter -- POST /meters + * Once created, the meter can be used to track and analyze the specific usage metrics for tenants. */ - readonly handler: IFunction; + createMeterFunction: IFunction; /** - * The detail-type that will trigger the handler function. + * The scope required to authorize requests for creating a new meter. */ - readonly trigger: DetailType; -} + createMeterScope?: string; -/** - * Encapsulates the list of properties for an IMetering construct. - */ -export interface IMetering { /** - * The function to trigger to create a meter. - * Once created, the meter can be used to track and analyze the specific usage metrics for tenants. + * The function to trigger to update a meter -- PUT /meters/meterId */ - createMeterFunction: IFunction | IFunctionTrigger; + updateMeterFunction?: IFunction; /** - * The function to trigger to update a meter. + * The scope required to authorize requests for updating a meter. */ - updateMeterFunction?: IFunction | IFunctionTrigger; + updateMeterScope?: string; /** * The function to trigger to ingest a usage event. * Usage events are used to measure and track the usage metrics associated with the meter. + * + * Default event trigger: INGEST_USAGE */ - ingestFunction: IFunction | IFunctionTrigger; + ingestUsageEventFunction: IFunction | IFunctionTrigger; /** * The function to trigger to get the usage data that has been recorded for a specific meter. + * -- GET /usage/meterId + */ + fetchUsageFunction: IFunction; // use 'fetch*' instead of 'get*' to avoid error JSII5000 + + /** + * The scope required to authorize requests for fetching metering usage. */ - getUsageFunction: IFunction | IFunctionTrigger; + fetchUsageScope?: string; /** * The function to trigger to exclude specific events from being recorded or included in the usage data. * Used for canceling events that were incorrectly ingested. + * -- DELETE /usage + */ + cancelUsageEventsFunction?: IFunction; + + /** + * The scope required to authorize requests for cancelling usage events. */ - cancelUsageEventsFunction?: IFunction | IFunctionTrigger; + cancelUsageEventsScope?: string; /** * The function to trigger to create a new customer. * (Customer in this context is a tenant.) + * + * Default event trigger: ONBOARDING_REQUEST */ createCustomerFunction?: IFunction | IFunctionTrigger; /** * The function to trigger to delete a customer. * (Customer in this context is a tenant.) + * + * Default event trigger: OFFBOARDING_REQUEST */ deleteCustomerFunction?: IFunction | IFunctionTrigger; } diff --git a/src/control-plane/metering/metering-provider.ts b/src/control-plane/metering/metering-provider.ts new file mode 100644 index 00000000..cf463eb3 --- /dev/null +++ b/src/control-plane/metering/metering-provider.ts @@ -0,0 +1,121 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import * as apigatewayV2 from 'aws-cdk-lib/aws-apigatewayv2'; +import * as apigatewayV2Integrations from 'aws-cdk-lib/aws-apigatewayv2-integrations'; +import { IFunction } from 'aws-cdk-lib/aws-lambda'; +import { Construct } from 'constructs'; +import { IMetering } from './metering-interface'; +import * as utils from '../../utils'; +import { ControlPlaneAPI } from '../control-plane-api'; + +/** + * Encapsulates the list of properties for a MeteringProvider. + */ +export interface MeteringProviderProps { + /** + * An implementation of the IMetering interface. + */ + readonly metering: IMetering; + + /** + * An IEventManager object to help coordinate events. + */ + readonly eventManager: utils.IEventManager; + + /** + * An API resource to use when setting up API endpoints. + */ + readonly api: ControlPlaneAPI; +} + +/** + * Represents a Metering Provider that handles metering-related operations and + * connects the concrete IMetering implementation (provided via props.metering) + * to the control plane. + * + * This construct sets up event targets for various metering-related events + * and adds API routes for 'usage' and 'meters'. + */ +export class MeteringProvider extends Construct { + constructor(scope: Construct, id: string, props: MeteringProviderProps) { + super(scope, id); + utils.addTemplateTag(this, 'MeteringProvider'); + + const usagePath = '/usage'; + const metersPath = '/meters'; + const functionTriggerMappings: { + defaultFunctionTrigger: utils.DetailType; + functionDefinition?: IFunction | utils.IFunctionTrigger; + }[] = [ + { + defaultFunctionTrigger: utils.DetailType.ONBOARDING_REQUEST, + functionDefinition: props.metering.createCustomerFunction, + }, + { + defaultFunctionTrigger: utils.DetailType.OFFBOARDING_REQUEST, + functionDefinition: props.metering.deleteCustomerFunction, + }, + { + defaultFunctionTrigger: utils.DetailType.INGEST_USAGE, + functionDefinition: props.metering.ingestUsageEventFunction, + }, + ]; + + functionTriggerMappings.forEach((target) => { + utils.createEventTarget( + this, + props.eventManager, + target.defaultFunctionTrigger, + target.functionDefinition + ); + }); + + const routes: utils.IRoute[] = [ + { + path: `${usagePath}/meterId`, + method: apigatewayV2.HttpMethod.GET, + integration: new apigatewayV2Integrations.HttpLambdaIntegration( + 'fetchUsageHttpLambdaIntegration', + props.metering.fetchUsageFunction + ), + scope: props.metering.fetchUsageScope, + }, + { + path: metersPath, + method: apigatewayV2.HttpMethod.POST, + integration: new apigatewayV2Integrations.HttpLambdaIntegration( + 'createMeterHttpLambdaIntegration', + props.metering.createMeterFunction + ), + scope: props.metering.createMeterScope, + }, + ]; + + if (props.metering.cancelUsageEventsFunction) { + routes.push({ + path: usagePath, + method: apigatewayV2.HttpMethod.DELETE, + integration: new apigatewayV2Integrations.HttpLambdaIntegration( + 'deleteUsageHttpLambdaIntegration', + props.metering.cancelUsageEventsFunction + ), + scope: props.metering.cancelUsageEventsScope, + }); + } + + if (props.metering.updateMeterFunction) { + routes.push({ + path: `${metersPath}/meterId`, + method: apigatewayV2.HttpMethod.PUT, + integration: new apigatewayV2Integrations.HttpLambdaIntegration( + 'updateMeterHttpLambdaIntegration', + props.metering.updateMeterFunction + ), + scope: props.metering.updateMeterScope, + }); + } + + utils.generateRoutes(props.api.api, routes, props.api.jwtAuthorizer); + } +} diff --git a/src/utils/event-manager.ts b/src/utils/event-manager.ts index 19fcee5c..e7433a1d 100644 --- a/src/utils/event-manager.ts +++ b/src/utils/event-manager.ts @@ -103,6 +103,11 @@ export enum DetailType { * should be emitted by the application plane. */ TENANT_USER_DELETED = 'tenantUserDeleted', + + /** + * Event detail type for ingesting a usage event. + */ + INGEST_USAGE = 'ingestUsage', } /** @@ -252,6 +257,7 @@ export class EventManager extends Construct implements IEventManager { deactivateFailure: this.applicationPlaneEventSource, tenantUserCreated: this.controlPlaneEventSource, tenantUserDeleted: this.controlPlaneEventSource, + ingestUsage: this.applicationPlaneEventSource, }; for (const key in this.supportedEvents) { diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 413656ea..86a4887a 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -3,7 +3,10 @@ import { Stack } from 'aws-cdk-lib'; import * as apigatewayV2 from 'aws-cdk-lib/aws-apigatewayv2'; +import * as targets from 'aws-cdk-lib/aws-events-targets'; +import { IFunction } from 'aws-cdk-lib/aws-lambda'; import { Construct } from 'constructs'; +import { DetailType, IEventManager } from './event-manager'; export const addTemplateTag = (construct: Construct, tag: string) => { const stackDesc = Stack.of(construct).templateOptions.description; @@ -101,3 +104,51 @@ export const generateRoutes = ( }); return allRoutes; }; + +/** + * Optional interface that allows specifying both + * the function to trigger and the event that will trigger it. + */ +export interface IFunctionTrigger { + /** + * The function definition. + */ + readonly handler: IFunction; + + /** + * The detail-type that will trigger the handler function. + */ + readonly trigger: DetailType; +} + +/** + * Helper function for attaching functions to events. + * If an IFunction is passed in as the argument for functionOrFunctionTrigger, then + * the defaultEvent is used as the trigger for the IFunction. + * + * If an IFunctionTrigger is passed in as the argument for functionOrFunctionTrigger, then + * the trigger property of the IFunctionTrigger is used as the trigger for the IFunction. + * + * If the functionOrFunctionTrigger is not passed in, no event is created. + */ +export const createEventTarget = ( + scope: Construct, + eventManager: IEventManager, + defaultEvent: DetailType, + functionOrFunctionTrigger?: IFunction | IFunctionTrigger +) => { + if (!functionOrFunctionTrigger) { + return; + } + + let handler: IFunction, trigger: DetailType; + if ('handler' in functionOrFunctionTrigger) { + handler = functionOrFunctionTrigger.handler; + trigger = functionOrFunctionTrigger.trigger; + } else { + handler = functionOrFunctionTrigger; + trigger = defaultEvent; + } + + eventManager.addTargetToEvent(scope, trigger, new targets.LambdaFunction(handler)); +};