From 11b6b40381935c5746ee5182db13f27de939f195 Mon Sep 17 00:00:00 2001 From: Syed Hussain Date: Mon, 29 Jul 2024 21:45:57 +0000 Subject: [PATCH 1/3] refactor(core-app-plane)!: replace BashJobRunner with ScriptJob This commit refactors the BashJobRunner construct into a more generic ScriptJob construct. It also introduces two new constructs, ProvisioningScriptJob and DeprovisioningScriptJob, which are wrappers around ScriptJob with predefined configurations for tenant provisioning and deprovisioning scenarios. The main changes include: - Rename BashJobRunner to ScriptJob and update related interfaces and properties - Add OutgoingEventDetailTypes interface to represent success and failure detail types - Introduce ProvisioningScriptJob and DeprovisioningScriptJob constructs - Update CoreApplicationPlane to use scriptJobs instead of jobRunnersList - Update integration tests and documentation accordingly This refactoring provides a more flexible and extensible approach for running arbitrary scripts in the application plane, while also simplifying the configuration for common tenant lifecycle management scenarios. --- .projen/deps.json | 1 + .projenrc.ts | 2 +- API.md | 2073 +++++++++++------ docs/public/README.md | 42 +- package-lock.json | 10 +- package.json | 2 +- scripts/sbt-aws.sh | 2 +- src/control-plane/integ.default.ts | 6 +- .../tenant-management.service.ts | 17 +- src/core-app-plane/core-app-plane.ts | 8 +- src/core-app-plane/index.ts | 3 +- src/core-app-plane/integ.default.ts | 33 +- .../{bash-job-runner.ts => script-job.ts} | 167 +- .../tenant-lifecycle-script-jobs.ts | 105 + test/core-app-plane.test.ts | 28 +- test/event-manager.test.ts | 50 +- 16 files changed, 1614 insertions(+), 935 deletions(-) rename src/core-app-plane/{bash-job-runner.ts => script-job.ts} (64%) create mode 100644 src/core-app-plane/tenant-lifecycle-script-jobs.ts diff --git a/.projen/deps.json b/.projen/deps.json index 1594f7f..1939da2 100644 --- a/.projen/deps.json +++ b/.projen/deps.json @@ -143,6 +143,7 @@ }, { "name": "@aws-cdk/aws-lambda-python-alpha", + "version": "2.140.0-alpha.0", "type": "runtime" }, { diff --git a/.projenrc.ts b/.projenrc.ts index 3792764..4d4eede 100644 --- a/.projenrc.ts +++ b/.projenrc.ts @@ -34,7 +34,7 @@ const project = new awscdk.AwsCdkConstructLibrary({ copyrightPeriod: '2024-', defaultReleaseBranch: 'main', deps: [ - '@aws-cdk/aws-lambda-python-alpha', + `@aws-cdk/aws-lambda-python-alpha@${CDK_VERSION}-alpha.0`, 'cdk-nag', `@aws-cdk/aws-kinesisfirehose-alpha@${CDK_VERSION}-alpha.0`, `@aws-cdk/aws-kinesisfirehose-destinations-alpha@${CDK_VERSION}-alpha.0`, diff --git a/API.md b/API.md index 925e204..1c69a64 100644 --- a/API.md +++ b/API.md @@ -151,172 +151,6 @@ when registering a new customer. --- -### BashJobRunner - -Provides a BashJobRunner to execute arbitrary bash code. - -#### Initializers - -```typescript -import { BashJobRunner } from '@cdklabs/sbt-aws' - -new BashJobRunner(scope: Construct, id: string, props: BashJobRunnerProps) -``` - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| scope | constructs.Construct | *No description.* | -| id | string | *No description.* | -| props | BashJobRunnerProps | *No description.* | - ---- - -##### `scope`Required - -- *Type:* constructs.Construct - ---- - -##### `id`Required - -- *Type:* string - ---- - -##### `props`Required - -- *Type:* BashJobRunnerProps - ---- - -#### Methods - -| **Name** | **Description** | -| --- | --- | -| toString | Returns a string representation of this construct. | - ---- - -##### `toString` - -```typescript -public toString(): string -``` - -Returns a string representation of this construct. - -#### Static Functions - -| **Name** | **Description** | -| --- | --- | -| isConstruct | Checks if `x` is a construct. | - ---- - -##### ~~`isConstruct`~~ - -```typescript -import { BashJobRunner } from '@cdklabs/sbt-aws' - -BashJobRunner.isConstruct(x: any) -``` - -Checks if `x` is a construct. - -###### `x`Required - -- *Type:* any - -Any object. - ---- - -#### Properties - -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| codebuildProject | aws-cdk-lib.aws_codebuild.Project | The codebuildProject used to implement this BashJobRunner. | -| eventTarget | aws-cdk-lib.aws_events.IRuleTarget | The eventTarget to use when triggering this BashJobRunner. | -| incomingEvent | DetailType | The incoming event DetailType that triggers this job. | -| provisioningStateMachine | aws-cdk-lib.aws_stepfunctions.StateMachine | The StateMachine used to implement this BashJobRunner orchestration. | -| environmentVariablesToOutgoingEvent | string[] | The environment variables to export into the outgoing event once the BashJobRunner has finished. | - ---- - -##### `node`Required - -```typescript -public readonly node: Node; -``` - -- *Type:* constructs.Node - -The tree node. - ---- - -##### `codebuildProject`Required - -```typescript -public readonly codebuildProject: Project; -``` - -- *Type:* aws-cdk-lib.aws_codebuild.Project - -The codebuildProject used to implement this BashJobRunner. - ---- - -##### `eventTarget`Required - -```typescript -public readonly eventTarget: IRuleTarget; -``` - -- *Type:* aws-cdk-lib.aws_events.IRuleTarget - -The eventTarget to use when triggering this BashJobRunner. - ---- - -##### `incomingEvent`Required - -```typescript -public readonly incomingEvent: DetailType; -``` - -- *Type:* DetailType - -The incoming event DetailType that triggers this job. - ---- - -##### `provisioningStateMachine`Required - -```typescript -public readonly provisioningStateMachine: StateMachine; -``` - -- *Type:* aws-cdk-lib.aws_stepfunctions.StateMachine - -The StateMachine used to implement this BashJobRunner orchestration. - ---- - -##### `environmentVariablesToOutgoingEvent`Optional - -```typescript -public readonly environmentVariablesToOutgoingEvent: string[]; -``` - -- *Type:* string[] - -The environment variables to export into the outgoing event once the BashJobRunner has finished. - ---- - - ### BillingProvider Represents a Billing Provider that handles billing-related operations. @@ -1379,43 +1213,44 @@ The EventManager instance that allows connecting to events flowing between the C --- -### EventManager +### DeprovisioningScriptJob -- *Implements:* IEventManager +Provides a ProvisioningScriptJob to execute arbitrary bash code. -Provides an EventManager to interact with the EventBus shared with the SBT control plane. +This is a simple wrapper around ScriptJob that reduces some of the parameters +that need to be configured. -#### Initializers +#### Initializers ```typescript -import { EventManager } from '@cdklabs/sbt-aws' +import { DeprovisioningScriptJob } from '@cdklabs/sbt-aws' -new EventManager(scope: Construct, id: string, props?: EventManagerProps) +new DeprovisioningScriptJob(scope: Construct, id: string, props: TenantLifecycleScriptJobProps) ``` | **Name** | **Type** | **Description** | | --- | --- | --- | -| scope | constructs.Construct | *No description.* | -| id | string | *No description.* | -| props | EventManagerProps | *No description.* | +| scope | constructs.Construct | *No description.* | +| id | string | *No description.* | +| props | TenantLifecycleScriptJobProps | *No description.* | --- -##### `scope`Required +##### `scope`Required - *Type:* constructs.Construct --- -##### `id`Required +##### `id`Required - *Type:* string --- -##### `props`Optional +##### `props`Required -- *Type:* EventManagerProps +- *Type:* TenantLifecycleScriptJobProps --- @@ -1423,13 +1258,11 @@ new EventManager(scope: Construct, id: string, props?: EventManagerProps) | **Name** | **Description** | | --- | --- | -| toString | Returns a string representation of this construct. | -| addTargetToEvent | Adds an IRuleTarget to an event. | -| grantPutEventsTo | Provides grantee the permissions to place events on the EventManager bus. | +| toString | Returns a string representation of this construct. | --- -##### `toString` +##### `toString` ```typescript public toString(): string @@ -1437,73 +1270,25 @@ public toString(): string Returns a string representation of this construct. -##### `addTargetToEvent` - -```typescript -public addTargetToEvent(scope: Construct, eventType: DetailType, target: IRuleTarget): void -``` - -Adds an IRuleTarget to an event. - -###### `scope`Required - -- *Type:* constructs.Construct - -The scope in which to find (or create) the Rule. - ---- - -###### `eventType`Required - -- *Type:* DetailType - -The detail type of the event to add a target to. - ---- - -###### `target`Required - -- *Type:* aws-cdk-lib.aws_events.IRuleTarget - -The target that will be added to the event. - ---- - -##### `grantPutEventsTo` - -```typescript -public grantPutEventsTo(grantee: IGrantable): void -``` - -Provides grantee the permissions to place events on the EventManager bus. - -###### `grantee`Required - -- *Type:* aws-cdk-lib.aws_iam.IGrantable - -The grantee resource that will be granted the permission(s). - ---- - #### Static Functions | **Name** | **Description** | | --- | --- | -| isConstruct | Checks if `x` is a construct. | +| isConstruct | Checks if `x` is a construct. | --- -##### ~~`isConstruct`~~ +##### ~~`isConstruct`~~ ```typescript -import { EventManager } from '@cdklabs/sbt-aws' +import { DeprovisioningScriptJob } from '@cdklabs/sbt-aws' -EventManager.isConstruct(x: any) +DeprovisioningScriptJob.isConstruct(x: any) ``` Checks if `x` is a construct. -###### `x`Required +###### `x`Required - *Type:* any @@ -1515,17 +1300,16 @@ Any object. | **Name** | **Type** | **Description** | | --- | --- | --- | -| node | constructs.Node | The tree node. | -| applicationPlaneEventSource | string | The event source used for events emitted by the application plane. | -| busArn | string | The ARN/ID of the bus that will be used to send and receive events. | -| busName | string | The name of the bus that will be used to send and receive events. | -| controlPlaneEventSource | string | The event source used for events emitted by the control plane. | -| eventBus | aws-cdk-lib.aws_events.IEventBus | The eventBus resource that will be used to send and receive events. | -| supportedEvents | {[ key: string ]: string} | List of recognized events that are available as triggers. | +| node | constructs.Node | The tree node. | +| codebuildProject | aws-cdk-lib.aws_codebuild.Project | The codebuildProject used to implement this ScriptJob. | +| eventTarget | aws-cdk-lib.aws_events.IRuleTarget | The eventTarget to use when triggering this ScriptJob. | +| incomingEvent | DetailType | The incoming event DetailType that triggers this job. | +| provisioningStateMachine | aws-cdk-lib.aws_stepfunctions.StateMachine | The StateMachine used to implement this ScriptJob orchestration. | +| environmentVariablesToOutgoingEvent | string[] | The environment variables to export into the outgoing event once the ScriptJob has finished. | --- -##### `node`Required +##### `node`Required ```typescript public readonly node: Node; @@ -1537,80 +1321,299 @@ The tree node. --- -##### `applicationPlaneEventSource`Required +##### `codebuildProject`Required ```typescript -public readonly applicationPlaneEventSource: string; +public readonly codebuildProject: Project; ``` -- *Type:* string +- *Type:* aws-cdk-lib.aws_codebuild.Project -The event source used for events emitted by the application plane. +The codebuildProject used to implement this ScriptJob. --- -##### `busArn`Required +##### `eventTarget`Required ```typescript -public readonly busArn: string; +public readonly eventTarget: IRuleTarget; ``` -- *Type:* string +- *Type:* aws-cdk-lib.aws_events.IRuleTarget -The ARN/ID of the bus that will be used to send and receive events. +The eventTarget to use when triggering this ScriptJob. --- -##### `busName`Required +##### `incomingEvent`Required ```typescript -public readonly busName: string; +public readonly incomingEvent: DetailType; ``` -- *Type:* string +- *Type:* DetailType -The name of the bus that will be used to send and receive events. +The incoming event DetailType that triggers this job. --- -##### `controlPlaneEventSource`Required +##### `provisioningStateMachine`Required ```typescript -public readonly controlPlaneEventSource: string; +public readonly provisioningStateMachine: StateMachine; ``` -- *Type:* string +- *Type:* aws-cdk-lib.aws_stepfunctions.StateMachine -The event source used for events emitted by the control plane. +The StateMachine used to implement this ScriptJob orchestration. --- -##### `eventBus`Required +##### `environmentVariablesToOutgoingEvent`Optional ```typescript -public readonly eventBus: IEventBus; +public readonly environmentVariablesToOutgoingEvent: string[]; ``` -- *Type:* aws-cdk-lib.aws_events.IEventBus +- *Type:* string[] -The eventBus resource that will be used to send and receive events. +The environment variables to export into the outgoing event once the ScriptJob has finished. --- -##### `supportedEvents`Required -```typescript -public readonly supportedEvents: {[ key: string ]: string}; -``` +### EventManager -- *Type:* {[ key: string ]: string} +- *Implements:* IEventManager -List of recognized events that are available as triggers. +Provides an EventManager to interact with the EventBus shared with the SBT control plane. ---- +#### Initializers +```typescript +import { EventManager } from '@cdklabs/sbt-aws' -### FirehoseAggregator +new EventManager(scope: Construct, id: string, props?: EventManagerProps) +``` + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| scope | constructs.Construct | *No description.* | +| id | string | *No description.* | +| props | EventManagerProps | *No description.* | + +--- + +##### `scope`Required + +- *Type:* constructs.Construct + +--- + +##### `id`Required + +- *Type:* string + +--- + +##### `props`Optional + +- *Type:* EventManagerProps + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| toString | Returns a string representation of this construct. | +| addTargetToEvent | Adds an IRuleTarget to an event. | +| grantPutEventsTo | Provides grantee the permissions to place events on the EventManager bus. | + +--- + +##### `toString` + +```typescript +public toString(): string +``` + +Returns a string representation of this construct. + +##### `addTargetToEvent` + +```typescript +public addTargetToEvent(scope: Construct, eventType: DetailType, target: IRuleTarget): void +``` + +Adds an IRuleTarget to an event. + +###### `scope`Required + +- *Type:* constructs.Construct + +The scope in which to find (or create) the Rule. + +--- + +###### `eventType`Required + +- *Type:* DetailType + +The detail type of the event to add a target to. + +--- + +###### `target`Required + +- *Type:* aws-cdk-lib.aws_events.IRuleTarget + +The target that will be added to the event. + +--- + +##### `grantPutEventsTo` + +```typescript +public grantPutEventsTo(grantee: IGrantable): void +``` + +Provides grantee the permissions to place events on the EventManager bus. + +###### `grantee`Required + +- *Type:* aws-cdk-lib.aws_iam.IGrantable + +The grantee resource that will be granted the permission(s). + +--- + +#### Static Functions + +| **Name** | **Description** | +| --- | --- | +| isConstruct | Checks if `x` is a construct. | + +--- + +##### ~~`isConstruct`~~ + +```typescript +import { EventManager } from '@cdklabs/sbt-aws' + +EventManager.isConstruct(x: any) +``` + +Checks if `x` is a construct. + +###### `x`Required + +- *Type:* any + +Any object. + +--- + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| applicationPlaneEventSource | string | The event source used for events emitted by the application plane. | +| busArn | string | The ARN/ID of the bus that will be used to send and receive events. | +| busName | string | The name of the bus that will be used to send and receive events. | +| controlPlaneEventSource | string | The event source used for events emitted by the control plane. | +| eventBus | aws-cdk-lib.aws_events.IEventBus | The eventBus resource that will be used to send and receive events. | +| supportedEvents | {[ key: string ]: string} | List of recognized events that are available as triggers. | + +--- + +##### `node`Required + +```typescript +public readonly node: Node; +``` + +- *Type:* constructs.Node + +The tree node. + +--- + +##### `applicationPlaneEventSource`Required + +```typescript +public readonly applicationPlaneEventSource: string; +``` + +- *Type:* string + +The event source used for events emitted by the application plane. + +--- + +##### `busArn`Required + +```typescript +public readonly busArn: string; +``` + +- *Type:* string + +The ARN/ID of the bus that will be used to send and receive events. + +--- + +##### `busName`Required + +```typescript +public readonly busName: string; +``` + +- *Type:* string + +The name of the bus that will be used to send and receive events. + +--- + +##### `controlPlaneEventSource`Required + +```typescript +public readonly controlPlaneEventSource: string; +``` + +- *Type:* string + +The event source used for events emitted by the control plane. + +--- + +##### `eventBus`Required + +```typescript +public readonly eventBus: IEventBus; +``` + +- *Type:* aws-cdk-lib.aws_events.IEventBus + +The eventBus resource that will be used to send and receive events. + +--- + +##### `supportedEvents`Required + +```typescript +public readonly supportedEvents: {[ key: string ]: string}; +``` + +- *Type:* {[ key: string ]: string} + +List of recognized events that are available as triggers. + +--- + + +### FirehoseAggregator - *Implements:* IDataIngestorAggregator @@ -1770,43 +1773,44 @@ The DynamoDB table containing the aggregated data. --- -### SampleRegistrationWebPage +### ProvisioningScriptJob -Constructs a sample registration web page hosted on Amazon S3 and fronted by Amazon CloudFront. +Provides a ProvisioningScriptJob to execute arbitrary bash code. -The web page includes a form for users to register for the SaaS product. +This is a simple wrapper around ScriptJob that reduces some of the parameters +that need to be configured. -#### Initializers +#### Initializers ```typescript -import { SampleRegistrationWebPage } from '@cdklabs/sbt-aws' +import { ProvisioningScriptJob } from '@cdklabs/sbt-aws' -new SampleRegistrationWebPage(scope: Construct, id: string, props: SampleRegistrationWebPageProps) +new ProvisioningScriptJob(scope: Construct, id: string, props: TenantLifecycleScriptJobProps) ``` | **Name** | **Type** | **Description** | | --- | --- | --- | -| scope | constructs.Construct | *No description.* | -| id | string | *No description.* | -| props | SampleRegistrationWebPageProps | *No description.* | +| scope | constructs.Construct | *No description.* | +| id | string | *No description.* | +| props | TenantLifecycleScriptJobProps | *No description.* | --- -##### `scope`Required +##### `scope`Required - *Type:* constructs.Construct --- -##### `id`Required +##### `id`Required - *Type:* string --- -##### `props`Required +##### `props`Required -- *Type:* SampleRegistrationWebPageProps +- *Type:* TenantLifecycleScriptJobProps --- @@ -1814,11 +1818,11 @@ new SampleRegistrationWebPage(scope: Construct, id: string, props: SampleRegistr | **Name** | **Description** | | --- | --- | -| toString | Returns a string representation of this construct. | +| toString | Returns a string representation of this construct. | --- -##### `toString` +##### `toString` ```typescript public toString(): string @@ -1830,21 +1834,21 @@ Returns a string representation of this construct. | **Name** | **Description** | | --- | --- | -| isConstruct | Checks if `x` is a construct. | +| isConstruct | Checks if `x` is a construct. | --- -##### ~~`isConstruct`~~ +##### ~~`isConstruct`~~ ```typescript -import { SampleRegistrationWebPage } from '@cdklabs/sbt-aws' +import { ProvisioningScriptJob } from '@cdklabs/sbt-aws' -SampleRegistrationWebPage.isConstruct(x: any) +ProvisioningScriptJob.isConstruct(x: any) ``` Checks if `x` is a construct. -###### `x`Required +###### `x`Required - *Type:* any @@ -1856,11 +1860,16 @@ Any object. | **Name** | **Type** | **Description** | | --- | --- | --- | -| node | constructs.Node | The tree node. | +| node | constructs.Node | The tree node. | +| codebuildProject | aws-cdk-lib.aws_codebuild.Project | The codebuildProject used to implement this ScriptJob. | +| eventTarget | aws-cdk-lib.aws_events.IRuleTarget | The eventTarget to use when triggering this ScriptJob. | +| incomingEvent | DetailType | The incoming event DetailType that triggers this job. | +| provisioningStateMachine | aws-cdk-lib.aws_stepfunctions.StateMachine | The StateMachine used to implement this ScriptJob orchestration. | +| environmentVariablesToOutgoingEvent | string[] | The environment variables to export into the outgoing event once the ScriptJob has finished. | --- -##### `node`Required +##### `node`Required ```typescript public readonly node: Node; @@ -1872,162 +1881,104 @@ The tree node. --- +##### `codebuildProject`Required -### TenantConfigLambdas +```typescript +public readonly codebuildProject: Project; +``` -Represents a set of Lambda functions for managing tenant configurations. +- *Type:* aws-cdk-lib.aws_codebuild.Project -#### Initializers +The codebuildProject used to implement this ScriptJob. -```typescript -import { TenantConfigLambdas } from '@cdklabs/sbt-aws' +--- -new TenantConfigLambdas(scope: Construct, id: string, props: TenantConfigLambdasProps) +##### `eventTarget`Required + +```typescript +public readonly eventTarget: IRuleTarget; ``` -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| scope | constructs.Construct | - The parent construct. | -| id | string | - The ID of the construct. | -| props | TenantConfigLambdasProps | - The properties required to initialize the TenantConfigLambdas. | - ---- - -##### `scope`Required - -- *Type:* constructs.Construct - -The parent construct. - ---- - -##### `id`Required - -- *Type:* string - -The ID of the construct. - ---- - -##### `props`Required - -- *Type:* TenantConfigLambdasProps - -The properties required to initialize the TenantConfigLambdas. - ---- - -#### Methods +- *Type:* aws-cdk-lib.aws_events.IRuleTarget -| **Name** | **Description** | -| --- | --- | -| toString | Returns a string representation of this construct. | +The eventTarget to use when triggering this ScriptJob. --- -##### `toString` +##### `incomingEvent`Required ```typescript -public toString(): string +public readonly incomingEvent: DetailType; ``` -Returns a string representation of this construct. - -#### Static Functions +- *Type:* DetailType -| **Name** | **Description** | -| --- | --- | -| isConstruct | Checks if `x` is a construct. | +The incoming event DetailType that triggers this job. --- -##### ~~`isConstruct`~~ +##### `provisioningStateMachine`Required ```typescript -import { TenantConfigLambdas } from '@cdklabs/sbt-aws' - -TenantConfigLambdas.isConstruct(x: any) +public readonly provisioningStateMachine: StateMachine; ``` -Checks if `x` is a construct. - -###### `x`Required - -- *Type:* any - -Any object. - ---- - -#### Properties +- *Type:* aws-cdk-lib.aws_stepfunctions.StateMachine -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| node | constructs.Node | The tree node. | -| tenantConfigFunction | aws-cdk-lib.aws_lambda.Function | The Lambda function responsible for managing tenant configurations. | +The StateMachine used to implement this ScriptJob orchestration. --- -##### `node`Required +##### `environmentVariablesToOutgoingEvent`Optional ```typescript -public readonly node: Node; +public readonly environmentVariablesToOutgoingEvent: string[]; ``` -- *Type:* constructs.Node +- *Type:* string[] -The tree node. +The environment variables to export into the outgoing event once the ScriptJob has finished. --- -##### `tenantConfigFunction`Required - -```typescript -public readonly tenantConfigFunction: Function; -``` - -- *Type:* aws-cdk-lib.aws_lambda.Function - -The Lambda function responsible for managing tenant configurations. - ---- +### SampleRegistrationWebPage -### TenantConfigService +Constructs a sample registration web page hosted on Amazon S3 and fronted by Amazon CloudFront. -Represents the Tenant Config Service construct. +The web page includes a form for users to register for the SaaS product. -#### Initializers +#### Initializers ```typescript -import { TenantConfigService } from '@cdklabs/sbt-aws' +import { SampleRegistrationWebPage } from '@cdklabs/sbt-aws' -new TenantConfigService(scope: Construct, id: string, props: TenantConfigServiceProps) +new SampleRegistrationWebPage(scope: Construct, id: string, props: SampleRegistrationWebPageProps) ``` | **Name** | **Type** | **Description** | | --- | --- | --- | -| scope | constructs.Construct | *No description.* | -| id | string | *No description.* | -| props | TenantConfigServiceProps | *No description.* | +| scope | constructs.Construct | *No description.* | +| id | string | *No description.* | +| props | SampleRegistrationWebPageProps | *No description.* | --- -##### `scope`Required +##### `scope`Required - *Type:* constructs.Construct --- -##### `id`Required +##### `id`Required - *Type:* string --- -##### `props`Required +##### `props`Required -- *Type:* TenantConfigServiceProps +- *Type:* SampleRegistrationWebPageProps --- @@ -2035,11 +1986,11 @@ new TenantConfigService(scope: Construct, id: string, props: TenantConfigService | **Name** | **Description** | | --- | --- | -| toString | Returns a string representation of this construct. | +| toString | Returns a string representation of this construct. | --- -##### `toString` +##### `toString` ```typescript public toString(): string @@ -2051,21 +2002,21 @@ Returns a string representation of this construct. | **Name** | **Description** | | --- | --- | -| isConstruct | Checks if `x` is a construct. | +| isConstruct | Checks if `x` is a construct. | --- -##### ~~`isConstruct`~~ +##### ~~`isConstruct`~~ ```typescript -import { TenantConfigService } from '@cdklabs/sbt-aws' +import { SampleRegistrationWebPage } from '@cdklabs/sbt-aws' -TenantConfigService.isConstruct(x: any) +SampleRegistrationWebPage.isConstruct(x: any) ``` Checks if `x` is a construct. -###### `x`Required +###### `x`Required - *Type:* any @@ -2077,11 +2028,11 @@ Any object. | **Name** | **Type** | **Description** | | --- | --- | --- | -| node | constructs.Node | The tree node. | +| node | constructs.Node | The tree node. | --- -##### `node`Required +##### `node`Required ```typescript public readonly node: Node; @@ -2094,41 +2045,41 @@ The tree node. --- -### TenantManagementLambda +### ScriptJob -Represents the Tenant Management Lambda construct. +Provides a ScriptJob to execute arbitrary bash code. -#### Initializers +#### Initializers ```typescript -import { TenantManagementLambda } from '@cdklabs/sbt-aws' +import { ScriptJob } from '@cdklabs/sbt-aws' -new TenantManagementLambda(scope: Construct, id: string, props: TenantManagementLambdaProps) +new ScriptJob(scope: Construct, id: string, props: ScriptJobProps) ``` | **Name** | **Type** | **Description** | | --- | --- | --- | -| scope | constructs.Construct | *No description.* | -| id | string | *No description.* | -| props | TenantManagementLambdaProps | *No description.* | +| scope | constructs.Construct | *No description.* | +| id | string | *No description.* | +| props | ScriptJobProps | *No description.* | --- -##### `scope`Required +##### `scope`Required - *Type:* constructs.Construct --- -##### `id`Required +##### `id`Required - *Type:* string --- -##### `props`Required +##### `props`Required -- *Type:* TenantManagementLambdaProps +- *Type:* ScriptJobProps --- @@ -2136,11 +2087,11 @@ new TenantManagementLambda(scope: Construct, id: string, props: TenantManagement | **Name** | **Description** | | --- | --- | -| toString | Returns a string representation of this construct. | +| toString | Returns a string representation of this construct. | --- -##### `toString` +##### `toString` ```typescript public toString(): string @@ -2152,21 +2103,21 @@ Returns a string representation of this construct. | **Name** | **Description** | | --- | --- | -| isConstruct | Checks if `x` is a construct. | +| isConstruct | Checks if `x` is a construct. | --- -##### ~~`isConstruct`~~ +##### ~~`isConstruct`~~ ```typescript -import { TenantManagementLambda } from '@cdklabs/sbt-aws' +import { ScriptJob } from '@cdklabs/sbt-aws' -TenantManagementLambda.isConstruct(x: any) +ScriptJob.isConstruct(x: any) ``` Checks if `x` is a construct. -###### `x`Required +###### `x`Required - *Type:* any @@ -2178,12 +2129,16 @@ Any object. | **Name** | **Type** | **Description** | | --- | --- | --- | -| node | constructs.Node | The tree node. | -| tenantManagementFunc | aws-cdk-lib.aws_lambda.Function | *No description.* | +| node | constructs.Node | The tree node. | +| codebuildProject | aws-cdk-lib.aws_codebuild.Project | The codebuildProject used to implement this ScriptJob. | +| eventTarget | aws-cdk-lib.aws_events.IRuleTarget | The eventTarget to use when triggering this ScriptJob. | +| incomingEvent | DetailType | The incoming event DetailType that triggers this job. | +| provisioningStateMachine | aws-cdk-lib.aws_stepfunctions.StateMachine | The StateMachine used to implement this ScriptJob orchestration. | +| environmentVariablesToOutgoingEvent | string[] | The environment variables to export into the outgoing event once the ScriptJob has finished. | --- -##### `node`Required +##### `node`Required ```typescript public readonly node: Node; @@ -2195,38 +2150,88 @@ The tree node. --- -##### `tenantManagementFunc`Required +##### `codebuildProject`Required ```typescript -public readonly tenantManagementFunc: Function; +public readonly codebuildProject: Project; ``` -- *Type:* aws-cdk-lib.aws_lambda.Function +- *Type:* aws-cdk-lib.aws_codebuild.Project + +The codebuildProject used to implement this ScriptJob. --- +##### `eventTarget`Required -### TenantManagementService +```typescript +public readonly eventTarget: IRuleTarget; +``` -Represents a service for managing tenants in the application. +- *Type:* aws-cdk-lib.aws_events.IRuleTarget -#### Initializers +The eventTarget to use when triggering this ScriptJob. + +--- + +##### `incomingEvent`Required ```typescript -import { TenantManagementService } from '@cdklabs/sbt-aws' +public readonly incomingEvent: DetailType; +``` -new TenantManagementService(scope: Construct, id: string, props: TenantManagementServiceProps) +- *Type:* DetailType + +The incoming event DetailType that triggers this job. + +--- + +##### `provisioningStateMachine`Required + +```typescript +public readonly provisioningStateMachine: StateMachine; +``` + +- *Type:* aws-cdk-lib.aws_stepfunctions.StateMachine + +The StateMachine used to implement this ScriptJob orchestration. + +--- + +##### `environmentVariablesToOutgoingEvent`Optional + +```typescript +public readonly environmentVariablesToOutgoingEvent: string[]; +``` + +- *Type:* string[] + +The environment variables to export into the outgoing event once the ScriptJob has finished. + +--- + + +### TenantConfigLambdas + +Represents a set of Lambda functions for managing tenant configurations. + +#### Initializers + +```typescript +import { TenantConfigLambdas } from '@cdklabs/sbt-aws' + +new TenantConfigLambdas(scope: Construct, id: string, props: TenantConfigLambdasProps) ``` | **Name** | **Type** | **Description** | | --- | --- | --- | -| scope | constructs.Construct | - The parent construct. | -| id | string | - The ID of the construct. | -| props | TenantManagementServiceProps | - The properties required to initialize the service. | +| scope | constructs.Construct | - The parent construct. | +| id | string | - The ID of the construct. | +| props | TenantConfigLambdasProps | - The properties required to initialize the TenantConfigLambdas. | --- -##### `scope`Required +##### `scope`Required - *Type:* constructs.Construct @@ -2234,7 +2239,7 @@ The parent construct. --- -##### `id`Required +##### `id`Required - *Type:* string @@ -2242,11 +2247,11 @@ The ID of the construct. --- -##### `props`Required +##### `props`Required -- *Type:* TenantManagementServiceProps +- *Type:* TenantConfigLambdasProps -The properties required to initialize the service. +The properties required to initialize the TenantConfigLambdas. --- @@ -2254,11 +2259,11 @@ The properties required to initialize the service. | **Name** | **Description** | | --- | --- | -| toString | Returns a string representation of this construct. | +| toString | Returns a string representation of this construct. | --- -##### `toString` +##### `toString` ```typescript public toString(): string @@ -2270,21 +2275,21 @@ Returns a string representation of this construct. | **Name** | **Description** | | --- | --- | -| isConstruct | Checks if `x` is a construct. | +| isConstruct | Checks if `x` is a construct. | --- -##### ~~`isConstruct`~~ +##### ~~`isConstruct`~~ ```typescript -import { TenantManagementService } from '@cdklabs/sbt-aws' +import { TenantConfigLambdas } from '@cdklabs/sbt-aws' -TenantManagementService.isConstruct(x: any) +TenantConfigLambdas.isConstruct(x: any) ``` Checks if `x` is a construct. -###### `x`Required +###### `x`Required - *Type:* any @@ -2296,12 +2301,12 @@ Any object. | **Name** | **Type** | **Description** | | --- | --- | --- | -| node | constructs.Node | The tree node. | -| table | TenantManagementTable | The tenant management table instance. | +| node | constructs.Node | The tree node. | +| tenantConfigFunction | aws-cdk-lib.aws_lambda.Function | The Lambda function responsible for managing tenant configurations. | --- -##### `node`Required +##### `node`Required ```typescript public readonly node: Node; @@ -2313,51 +2318,54 @@ The tree node. --- -##### `table`Required +##### `tenantConfigFunction`Required ```typescript -public readonly table: TenantManagementTable; +public readonly tenantConfigFunction: Function; ``` -- *Type:* TenantManagementTable +- *Type:* aws-cdk-lib.aws_lambda.Function -The tenant management table instance. +The Lambda function responsible for managing tenant configurations. --- -### TenantManagementTable +### TenantConfigService -Represents a table for managing tenant details in the application. +Represents the Tenant Config Service construct. -#### Initializers +#### Initializers ```typescript -import { TenantManagementTable } from '@cdklabs/sbt-aws' +import { TenantConfigService } from '@cdklabs/sbt-aws' -new TenantManagementTable(scope: Construct, id: string) +new TenantConfigService(scope: Construct, id: string, props: TenantConfigServiceProps) ``` | **Name** | **Type** | **Description** | | --- | --- | --- | -| scope | constructs.Construct | - The parent construct. | -| id | string | - The ID of the construct. | +| scope | constructs.Construct | *No description.* | +| id | string | *No description.* | +| props | TenantConfigServiceProps | *No description.* | --- -##### `scope`Required +##### `scope`Required - *Type:* constructs.Construct -The parent construct. - --- -##### `id`Required +##### `id`Required - *Type:* string -The ID of the construct. +--- + +##### `props`Required + +- *Type:* TenantConfigServiceProps --- @@ -2365,11 +2373,11 @@ The ID of the construct. | **Name** | **Description** | | --- | --- | -| toString | Returns a string representation of this construct. | +| toString | Returns a string representation of this construct. | --- -##### `toString` +##### `toString` ```typescript public toString(): string @@ -2381,21 +2389,21 @@ Returns a string representation of this construct. | **Name** | **Description** | | --- | --- | -| isConstruct | Checks if `x` is a construct. | +| isConstruct | Checks if `x` is a construct. | --- -##### ~~`isConstruct`~~ +##### ~~`isConstruct`~~ ```typescript -import { TenantManagementTable } from '@cdklabs/sbt-aws' +import { TenantConfigService } from '@cdklabs/sbt-aws' -TenantManagementTable.isConstruct(x: any) +TenantConfigService.isConstruct(x: any) ``` Checks if `x` is a construct. -###### `x`Required +###### `x`Required - *Type:* any @@ -2407,16 +2415,11 @@ Any object. | **Name** | **Type** | **Description** | | --- | --- | --- | -| node | constructs.Node | The tree node. | -| tenantConfigColumn | string | The name of the column that stores the tenant configuration. | -| tenantConfigIndexName | string | The name of the global secondary index for the tenant configuration. | -| tenantDetails | aws-cdk-lib.aws_dynamodb.Table | The table that stores the tenant details. | -| tenantIdColumn | string | The name of the column that stores the tenant ID. | -| tenantNameColumn | string | The name of the column that stores the tenant name. | +| node | constructs.Node | The tree node. | --- -##### `node`Required +##### `node`Required ```typescript public readonly node: Node; @@ -2428,88 +2431,140 @@ The tree node. --- -##### `tenantConfigColumn`Required + +### TenantManagementLambda + +Represents the Tenant Management Lambda construct. + +#### Initializers ```typescript -public readonly tenantConfigColumn: string; +import { TenantManagementLambda } from '@cdklabs/sbt-aws' + +new TenantManagementLambda(scope: Construct, id: string, props: TenantManagementLambdaProps) ``` +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| scope | constructs.Construct | *No description.* | +| id | string | *No description.* | +| props | TenantManagementLambdaProps | *No description.* | + +--- + +##### `scope`Required + +- *Type:* constructs.Construct + +--- + +##### `id`Required + - *Type:* string -The name of the column that stores the tenant configuration. +--- + +##### `props`Required + +- *Type:* TenantManagementLambdaProps --- -##### `tenantConfigIndexName`Required +#### Methods + +| **Name** | **Description** | +| --- | --- | +| toString | Returns a string representation of this construct. | + +--- + +##### `toString` ```typescript -public readonly tenantConfigIndexName: string; +public toString(): string ``` -- *Type:* string +Returns a string representation of this construct. -The name of the global secondary index for the tenant configuration. +#### Static Functions + +| **Name** | **Description** | +| --- | --- | +| isConstruct | Checks if `x` is a construct. | --- -##### `tenantDetails`Required +##### ~~`isConstruct`~~ ```typescript -public readonly tenantDetails: Table; +import { TenantManagementLambda } from '@cdklabs/sbt-aws' + +TenantManagementLambda.isConstruct(x: any) ``` -- *Type:* aws-cdk-lib.aws_dynamodb.Table +Checks if `x` is a construct. -The table that stores the tenant details. +###### `x`Required + +- *Type:* any + +Any object. --- -##### `tenantIdColumn`Required +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| tenantManagementFunc | aws-cdk-lib.aws_lambda.Function | *No description.* | + +--- + +##### `node`Required ```typescript -public readonly tenantIdColumn: string; +public readonly node: Node; ``` -- *Type:* string +- *Type:* constructs.Node -The name of the column that stores the tenant ID. +The tree node. --- -##### `tenantNameColumn`Required +##### `tenantManagementFunc`Required ```typescript -public readonly tenantNameColumn: string; +public readonly tenantManagementFunc: Function; ``` -- *Type:* string - -The name of the column that stores the tenant name. +- *Type:* aws-cdk-lib.aws_lambda.Function --- -### UserManagementService +### TenantManagementService -Represents a service for managing users in the application. +Represents a service for managing tenants in the application. -#### Initializers +#### Initializers ```typescript -import { UserManagementService } from '@cdklabs/sbt-aws' +import { TenantManagementService } from '@cdklabs/sbt-aws' -new UserManagementService(scope: Construct, id: string, props: UserManagementServiceProps) +new TenantManagementService(scope: Construct, id: string, props: TenantManagementServiceProps) ``` | **Name** | **Type** | **Description** | | --- | --- | --- | -| scope | constructs.Construct | - The parent construct. | -| id | string | - The ID of the construct. | -| props | UserManagementServiceProps | - The properties required to initialize the service. | +| scope | constructs.Construct | - The parent construct. | +| id | string | - The ID of the construct. | +| props | TenantManagementServiceProps | - The properties required to initialize the service. | --- -##### `scope`Required +##### `scope`Required - *Type:* constructs.Construct @@ -2517,7 +2572,7 @@ The parent construct. --- -##### `id`Required +##### `id`Required - *Type:* string @@ -2525,9 +2580,9 @@ The ID of the construct. --- -##### `props`Required +##### `props`Required -- *Type:* UserManagementServiceProps +- *Type:* TenantManagementServiceProps The properties required to initialize the service. @@ -2537,11 +2592,11 @@ The properties required to initialize the service. | **Name** | **Description** | | --- | --- | -| toString | Returns a string representation of this construct. | +| toString | Returns a string representation of this construct. | --- -##### `toString` +##### `toString` ```typescript public toString(): string @@ -2553,21 +2608,21 @@ Returns a string representation of this construct. | **Name** | **Description** | | --- | --- | -| isConstruct | Checks if `x` is a construct. | +| isConstruct | Checks if `x` is a construct. | --- -##### ~~`isConstruct`~~ +##### ~~`isConstruct`~~ ```typescript -import { UserManagementService } from '@cdklabs/sbt-aws' +import { TenantManagementService } from '@cdklabs/sbt-aws' -UserManagementService.isConstruct(x: any) +TenantManagementService.isConstruct(x: any) ``` Checks if `x` is a construct. -###### `x`Required +###### `x`Required - *Type:* any @@ -2579,11 +2634,12 @@ Any object. | **Name** | **Type** | **Description** | | --- | --- | --- | -| node | constructs.Node | The tree node. | +| node | constructs.Node | The tree node. | +| table | TenantManagementTable | The tenant management table instance. | --- -##### `node`Required +##### `node`Required ```typescript public readonly node: Node; @@ -2595,319 +2651,433 @@ The tree node. --- +##### `table`Required -## Structs +```typescript +public readonly table: TenantManagementTable; +``` -### AWSMarketplaceSaaSProductProps +- *Type:* TenantManagementTable -Properties for configuring an AWS Marketplace SaaS product. +The tenant management table instance. + +--- -#### Initializer + +### TenantManagementTable + +Represents a table for managing tenant details in the application. + +#### Initializers ```typescript -import { AWSMarketplaceSaaSProductProps } from '@cdklabs/sbt-aws' +import { TenantManagementTable } from '@cdklabs/sbt-aws' -const aWSMarketplaceSaaSProductProps: AWSMarketplaceSaaSProductProps = { ... } +new TenantManagementTable(scope: Construct, id: string) ``` -#### Properties - | **Name** | **Type** | **Description** | | --- | --- | --- | -| entitlementSNSTopic | string | SNS topic ARN provided from AWS Marketplace. | -| marketplaceTechAdminEmail | string | Email to be notified on changes requiring action. | -| pricingModel | AWSMarketplaceSaaSPricingModel | The pricing model for the AWS Marketplace SaaS product. | -| productCode | string | Product code provided from AWS Marketplace. | -| subscriptionSNSTopic | string | SNS topic ARN provided from AWS Marketplace. | -| disableAPILogging | boolean | Flag to disable API logging. | -| eventManager | IEventManager | The EventManager for the AWS Marketplace SaaS product. | -| marketplaceSellerEmail | string | Seller email address, verified in SES and in 'Production' mode. | -| requiredFieldsForRegistration | string[] | List of required fields for registration. | +| scope | constructs.Construct | - The parent construct. | +| id | string | - The ID of the construct. | --- -##### `entitlementSNSTopic`Required +##### `scope`Required -```typescript -public readonly entitlementSNSTopic: string; -``` +- *Type:* constructs.Construct -- *Type:* string +The parent construct. -SNS topic ARN provided from AWS Marketplace. +--- -Must exist. +##### `id`Required ---- +- *Type:* string -##### `marketplaceTechAdminEmail`Required +The ID of the construct. -```typescript -public readonly marketplaceTechAdminEmail: string; -``` +--- -- *Type:* string +#### Methods -Email to be notified on changes requiring action. +| **Name** | **Description** | +| --- | --- | +| toString | Returns a string representation of this construct. | --- -##### `pricingModel`Required +##### `toString` ```typescript -public readonly pricingModel: AWSMarketplaceSaaSPricingModel; +public toString(): string ``` -- *Type:* AWSMarketplaceSaaSPricingModel +Returns a string representation of this construct. -The pricing model for the AWS Marketplace SaaS product. +#### Static Functions + +| **Name** | **Description** | +| --- | --- | +| isConstruct | Checks if `x` is a construct. | --- -##### `productCode`Required +##### ~~`isConstruct`~~ ```typescript -public readonly productCode: string; +import { TenantManagementTable } from '@cdklabs/sbt-aws' + +TenantManagementTable.isConstruct(x: any) ``` -- *Type:* string +Checks if `x` is a construct. -Product code provided from AWS Marketplace. +###### `x`Required + +- *Type:* any + +Any object. --- -##### `subscriptionSNSTopic`Required +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| node | constructs.Node | The tree node. | +| tenantConfigColumn | string | The name of the column that stores the tenant configuration. | +| tenantConfigIndexName | string | The name of the global secondary index for the tenant configuration. | +| tenantDetails | aws-cdk-lib.aws_dynamodb.Table | The table that stores the tenant details. | +| tenantIdColumn | string | The name of the column that stores the tenant ID. | +| tenantNameColumn | string | The name of the column that stores the tenant name. | + +--- + +##### `node`Required ```typescript -public readonly subscriptionSNSTopic: string; +public readonly node: Node; ``` -- *Type:* string +- *Type:* constructs.Node -SNS topic ARN provided from AWS Marketplace. +The tree node. -Must exist. +--- + +##### `tenantConfigColumn`Required + +```typescript +public readonly tenantConfigColumn: string; +``` + +- *Type:* string + +The name of the column that stores the tenant configuration. --- -##### `disableAPILogging`Optional +##### `tenantConfigIndexName`Required ```typescript -public readonly disableAPILogging: boolean; +public readonly tenantConfigIndexName: string; ``` -- *Type:* boolean +- *Type:* string -Flag to disable API logging. +The name of the global secondary index for the tenant configuration. --- -##### `eventManager`Optional +##### `tenantDetails`Required ```typescript -public readonly eventManager: IEventManager; +public readonly tenantDetails: Table; ``` -- *Type:* IEventManager +- *Type:* aws-cdk-lib.aws_dynamodb.Table -The EventManager for the AWS Marketplace SaaS product. +The table that stores the tenant details. -This is used to enable integration with sbt-aws. +--- + +##### `tenantIdColumn`Required + +```typescript +public readonly tenantIdColumn: string; +``` + +- *Type:* string + +The name of the column that stores the tenant ID. --- -##### `marketplaceSellerEmail`Optional +##### `tenantNameColumn`Required ```typescript -public readonly marketplaceSellerEmail: string; +public readonly tenantNameColumn: string; ``` - *Type:* string -Seller email address, verified in SES and in 'Production' mode. +The name of the column that stores the tenant name. --- -##### `requiredFieldsForRegistration`Optional + +### UserManagementService + +Represents a service for managing users in the application. + +#### Initializers ```typescript -public readonly requiredFieldsForRegistration: string[]; +import { UserManagementService } from '@cdklabs/sbt-aws' + +new UserManagementService(scope: Construct, id: string, props: UserManagementServiceProps) ``` -- *Type:* string[] +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| scope | constructs.Construct | - The parent construct. | +| id | string | - The ID of the construct. | +| props | UserManagementServiceProps | - The properties required to initialize the service. | -List of required fields for registration. +--- -The existence of these -fields is checked when a new customer is registered. +##### `scope`Required + +- *Type:* constructs.Construct + +The parent construct. + +--- + +##### `id`Required + +- *Type:* string + +The ID of the construct. + +--- + +##### `props`Required + +- *Type:* UserManagementServiceProps + +The properties required to initialize the service. + +--- + +#### Methods + +| **Name** | **Description** | +| --- | --- | +| toString | Returns a string representation of this construct. | --- -### BashJobRunnerProps +##### `toString` + +```typescript +public toString(): string +``` + +Returns a string representation of this construct. + +#### Static Functions + +| **Name** | **Description** | +| --- | --- | +| isConstruct | Checks if `x` is a construct. | -Encapsulates the list of properties for a BashJobRunner. +--- -#### Initializer +##### ~~`isConstruct`~~ ```typescript -import { BashJobRunnerProps } from '@cdklabs/sbt-aws' +import { UserManagementService } from '@cdklabs/sbt-aws' -const bashJobRunnerProps: BashJobRunnerProps = { ... } +UserManagementService.isConstruct(x: any) ``` +Checks if `x` is a construct. + +###### `x`Required + +- *Type:* any + +Any object. + +--- + #### Properties | **Name** | **Type** | **Description** | | --- | --- | --- | -| eventManager | IEventManager | The EventManager instance that allows connecting to events flowing between the Control Plane and other components. | -| incomingEvent | DetailType | The incoming event DetailType that triggers this job. | -| outgoingEvent | DetailType | The outgoing event DetailType that is emitted upon job completion. | -| permissions | aws-cdk-lib.aws_iam.PolicyDocument | The IAM permission document for the BashJobRunner. | -| script | string | The bash script to run as part of the BashJobRunner. | -| environmentJSONVariablesFromIncomingEvent | string[] | The environment variables to import into the BashJobRunner from event details field. | -| environmentStringVariablesFromIncomingEvent | string[] | The environment variables to import into the BashJobRunner from event details field. | -| environmentVariablesToOutgoingEvent | string[] | The environment variables to export into the outgoing event once the BashJobRunner has finished. | -| postScript | string | The bash script to run after the main script has completed. | -| scriptEnvironmentVariables | {[ key: string ]: string} | The variables to pass into the codebuild BashJobRunner. | -| tenantIdentifierKeyInIncomingEvent | string | The key where the tenant identifier is to be extracted from in the incoming event. | +| node | constructs.Node | The tree node. | --- -##### `eventManager`Required +##### `node`Required ```typescript -public readonly eventManager: IEventManager; +public readonly node: Node; ``` -- *Type:* IEventManager +- *Type:* constructs.Node -The EventManager instance that allows connecting to events flowing between the Control Plane and other components. +The tree node. --- -##### `incomingEvent`Required + +## Structs + +### AWSMarketplaceSaaSProductProps + +Properties for configuring an AWS Marketplace SaaS product. + +#### Initializer ```typescript -public readonly incomingEvent: DetailType; +import { AWSMarketplaceSaaSProductProps } from '@cdklabs/sbt-aws' + +const aWSMarketplaceSaaSProductProps: AWSMarketplaceSaaSProductProps = { ... } ``` -- *Type:* DetailType +#### Properties -The incoming event DetailType that triggers this job. +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| entitlementSNSTopic | string | SNS topic ARN provided from AWS Marketplace. | +| marketplaceTechAdminEmail | string | Email to be notified on changes requiring action. | +| pricingModel | AWSMarketplaceSaaSPricingModel | The pricing model for the AWS Marketplace SaaS product. | +| productCode | string | Product code provided from AWS Marketplace. | +| subscriptionSNSTopic | string | SNS topic ARN provided from AWS Marketplace. | +| disableAPILogging | boolean | Flag to disable API logging. | +| eventManager | IEventManager | The EventManager for the AWS Marketplace SaaS product. | +| marketplaceSellerEmail | string | Seller email address, verified in SES and in 'Production' mode. | +| requiredFieldsForRegistration | string[] | List of required fields for registration. | --- -##### `outgoingEvent`Required +##### `entitlementSNSTopic`Required ```typescript -public readonly outgoingEvent: DetailType; +public readonly entitlementSNSTopic: string; ``` -- *Type:* DetailType +- *Type:* string + +SNS topic ARN provided from AWS Marketplace. -The outgoing event DetailType that is emitted upon job completion. +Must exist. --- -##### `permissions`Required +##### `marketplaceTechAdminEmail`Required ```typescript -public readonly permissions: PolicyDocument; +public readonly marketplaceTechAdminEmail: string; ``` -- *Type:* aws-cdk-lib.aws_iam.PolicyDocument +- *Type:* string -The IAM permission document for the BashJobRunner. +Email to be notified on changes requiring action. --- -##### `script`Required +##### `pricingModel`Required ```typescript -public readonly script: string; +public readonly pricingModel: AWSMarketplaceSaaSPricingModel; ``` -- *Type:* string +- *Type:* AWSMarketplaceSaaSPricingModel -The bash script to run as part of the BashJobRunner. +The pricing model for the AWS Marketplace SaaS product. --- -##### `environmentJSONVariablesFromIncomingEvent`Optional +##### `productCode`Required ```typescript -public readonly environmentJSONVariablesFromIncomingEvent: string[]; +public readonly productCode: string; ``` -- *Type:* string[] - -The environment variables to import into the BashJobRunner from event details field. +- *Type:* string -This argument consists of the names of only JSON-formatted string type variables. -Ex. '{"test": 2}' +Product code provided from AWS Marketplace. --- -##### `environmentStringVariablesFromIncomingEvent`Optional +##### `subscriptionSNSTopic`Required ```typescript -public readonly environmentStringVariablesFromIncomingEvent: string[]; +public readonly subscriptionSNSTopic: string; ``` -- *Type:* string[] +- *Type:* string -The environment variables to import into the BashJobRunner from event details field. +SNS topic ARN provided from AWS Marketplace. -This argument consists of the names of only string type variables. Ex. 'test' +Must exist. --- -##### `environmentVariablesToOutgoingEvent`Optional +##### `disableAPILogging`Optional ```typescript -public readonly environmentVariablesToOutgoingEvent: string[]; +public readonly disableAPILogging: boolean; ``` -- *Type:* string[] +- *Type:* boolean -The environment variables to export into the outgoing event once the BashJobRunner has finished. +Flag to disable API logging. --- -##### `postScript`Optional +##### `eventManager`Optional ```typescript -public readonly postScript: string; +public readonly eventManager: IEventManager; ``` -- *Type:* string +- *Type:* IEventManager -The bash script to run after the main script has completed. +The EventManager for the AWS Marketplace SaaS product. + +This is used to enable integration with sbt-aws. --- -##### `scriptEnvironmentVariables`Optional +##### `marketplaceSellerEmail`Optional ```typescript -public readonly scriptEnvironmentVariables: {[ key: string ]: string}; +public readonly marketplaceSellerEmail: string; ``` -- *Type:* {[ key: string ]: string} +- *Type:* string -The variables to pass into the codebuild BashJobRunner. +Seller email address, verified in SES and in 'Production' mode. --- -##### `tenantIdentifierKeyInIncomingEvent`Optional +##### `requiredFieldsForRegistration`Optional ```typescript -public readonly tenantIdentifierKeyInIncomingEvent: string; +public readonly requiredFieldsForRegistration: string[]; ``` -- *Type:* string -- *Default:* 'tenantId' +- *Type:* string[] + +List of required fields for registration. -The key where the tenant identifier is to be extracted from in the incoming event. +The existence of these +fields is checked when a new customer is registered. --- @@ -3215,7 +3385,7 @@ const coreApplicationPlaneProps: CoreApplicationPlaneProps = { ... } | **Name** | **Type** | **Description** | | --- | --- | --- | | eventManager | IEventManager | *No description.* | -| jobRunnersList | BashJobRunner[] | The list of JobRunners. | +| scriptJobs | ScriptJob[] | The list of JobRunners. | --- @@ -3229,13 +3399,13 @@ public readonly eventManager: IEventManager; --- -##### `jobRunnersList`Optional +##### `scriptJobs`Optional ```typescript -public readonly jobRunnersList: BashJobRunner[]; +public readonly scriptJobs: ScriptJob[]; ``` -- *Type:* BashJobRunner[] +- *Type:* ScriptJob[] The list of JobRunners. @@ -3271,260 +3441,497 @@ public readonly email: string; - *Type:* string -The email address of the new admin user. +The email address of the new admin user. + +--- + +##### `name`Required + +```typescript +public readonly name: string; +``` + +- *Type:* string + +The email address of the new admin user. + +--- + +##### `role`Required + +```typescript +public readonly role: string; +``` + +- *Type:* string + +The name of the role of the new admin user. + +--- + +### EventManagerProps + +Encapsulates the properties for an EventManager. + +#### Initializer + +```typescript +import { EventManagerProps } from '@cdklabs/sbt-aws' + +const eventManagerProps: EventManagerProps = { ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| applicationPlaneEventSource | string | The name of the event source for events coming from the SBT application plane. | +| controlPlaneEventSource | string | The name of the event source for events coming from the SBT control plane. | +| eventBus | aws-cdk-lib.aws_events.IEventBus | The event bus to register new rules with. | +| eventMetadata | {[ key: string ]: string} | The EventMetadata to use to update the event defaults. | + +--- + +##### `applicationPlaneEventSource`Optional + +```typescript +public readonly applicationPlaneEventSource: string; +``` + +- *Type:* string + +The name of the event source for events coming from the SBT application plane. + +--- + +##### `controlPlaneEventSource`Optional + +```typescript +public readonly controlPlaneEventSource: string; +``` + +- *Type:* string + +The name of the event source for events coming from the SBT control plane. + +--- + +##### `eventBus`Optional + +```typescript +public readonly eventBus: IEventBus; +``` + +- *Type:* aws-cdk-lib.aws_events.IEventBus + +The event bus to register new rules with. + +One will be created if not provided. + +--- + +##### `eventMetadata`Optional + +```typescript +public readonly eventMetadata: {[ key: string ]: string}; +``` + +- *Type:* {[ key: string ]: string} + +The EventMetadata to use to update the event defaults. + +--- + +### FirehoseAggregatorProps + +Encapsulates the list of properties for a FirehoseAggregator construct. + +#### Initializer + +```typescript +import { FirehoseAggregatorProps } from '@cdklabs/sbt-aws' + +const firehoseAggregatorProps: FirehoseAggregatorProps = { ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| aggregateKeyPath | string | The JMESPath to find the key value in the incoming data stream that will be aggregated. | +| aggregateValuePath | string | The JMESPath to find the numeric value of key in the incoming data stream that will be aggregated. | +| primaryKeyColumn | string | The name to use for the primary key column for the dynamoDB database. | +| primaryKeyPath | string | The JMESPath to find the primary key value in the incoming data stream. | + +--- + +##### `aggregateKeyPath`Required + +```typescript +public readonly aggregateKeyPath: string; +``` + +- *Type:* string + +The JMESPath to find the key value in the incoming data stream that will be aggregated. + +--- + +##### `aggregateValuePath`Required + +```typescript +public readonly aggregateValuePath: string; +``` + +- *Type:* string + +The JMESPath to find the numeric value of key in the incoming data stream that will be aggregated. + +--- + +##### `primaryKeyColumn`Required + +```typescript +public readonly primaryKeyColumn: string; +``` + +- *Type:* string + +The name to use for the primary key column for the dynamoDB database. + +--- + +##### `primaryKeyPath`Required + +```typescript +public readonly primaryKeyPath: string; +``` + +- *Type:* string + +The JMESPath to find the primary key value in the incoming data stream. + +--- + +### OutgoingEventDetailTypes + +Represents the DetailTypes that can be emitted as part of the outgoing event. + +#### Initializer + +```typescript +import { OutgoingEventDetailTypes } from '@cdklabs/sbt-aws' + +const outgoingEventDetailTypes: OutgoingEventDetailTypes = { ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| failure | DetailType | The detail type for a failed event. | +| success | DetailType | The detail type for a successful event. | + +--- + +##### `failure`Required + +```typescript +public readonly failure: DetailType; +``` + +- *Type:* DetailType + +The detail type for a failed event. + +--- + +##### `success`Required + +```typescript +public readonly success: DetailType; +``` + +- *Type:* DetailType + +The detail type for a successful event. + +--- + +### SampleRegistrationWebPageProps + +Properties for the SampleRegistrationWebPage construct. + +#### Initializer + +```typescript +import { SampleRegistrationWebPageProps } from '@cdklabs/sbt-aws' + +const sampleRegistrationWebPageProps: SampleRegistrationWebPageProps = { ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| registrationAPI | aws-cdk-lib.aws_apigateway.RestApiBase | The API Gateway that serves the following endpoints:. | +| userProvidedRequiredFieldsForRegistration | string[] | The list of required user-provided fields for registration. | +| autoDeleteBucketObjects | boolean | Whether to automatically delete objects from the S3 bucket when the stack is deleted. | +| imageLogoUrl | string | The URL of the image logo to display on the registration page. | + +--- + +##### `registrationAPI`Required + +```typescript +public readonly registrationAPI: RestApiBase; +``` + +- *Type:* aws-cdk-lib.aws_apigateway.RestApiBase + +The API Gateway that serves the following endpoints:. + +POST /redirectmarketplacetoken: redirects to a registration page. + +POST /subscriber: creates a new subscriber. + +--- + +##### `userProvidedRequiredFieldsForRegistration`Required + +```typescript +public readonly userProvidedRequiredFieldsForRegistration: string[]; +``` + +- *Type:* string[] + +The list of required user-provided fields for registration. + +This contains the set of fields that must be provided by the user +when registering a new customer. + +This is used to dynamically update the registration page to create a +form that accepts each of the fields present in this list. + +ex. ['name', 'phone'] --- -##### `name`Required +##### `autoDeleteBucketObjects`Optional ```typescript -public readonly name: string; +public readonly autoDeleteBucketObjects: boolean; ``` -- *Type:* string +- *Type:* boolean +- *Default:* false -The email address of the new admin user. +Whether to automatically delete objects from the S3 bucket when the stack is deleted. --- -##### `role`Required +##### `imageLogoUrl`Optional ```typescript -public readonly role: string; +public readonly imageLogoUrl: string; ``` - *Type:* string +- *Default:* Amazon logo -The name of the role of the new admin user. +The URL of the image logo to display on the registration page. --- -### EventManagerProps +### ScriptJobProps -Encapsulates the properties for an EventManager. +Encapsulates the list of properties for a ScriptJob. -#### Initializer +#### Initializer ```typescript -import { EventManagerProps } from '@cdklabs/sbt-aws' +import { ScriptJobProps } from '@cdklabs/sbt-aws' -const eventManagerProps: EventManagerProps = { ... } +const scriptJobProps: ScriptJobProps = { ... } ``` #### Properties | **Name** | **Type** | **Description** | | --- | --- | --- | -| applicationPlaneEventSource | string | The name of the event source for events coming from the SBT application plane. | -| controlPlaneEventSource | string | The name of the event source for events coming from the SBT control plane. | -| eventBus | aws-cdk-lib.aws_events.IEventBus | The event bus to register new rules with. | -| eventMetadata | {[ key: string ]: string} | The EventMetadata to use to update the event defaults. | +| eventManager | IEventManager | The EventManager instance that allows connecting to events flowing between the Control Plane and other components. | +| incomingEvent | DetailType | The incoming event DetailType that triggers this job. | +| jobFailureStatus | {[ key: string ]: string} | In the case of failure, this is the object that will be included in the outgoing event `jobOutput` field. | +| jobIdentifierKey | string | The key where the job identifier is to be extracted from in the incoming event. | +| outgoingEvent | OutgoingEventDetailTypes | The outgoing event DetailTypes that are emitted upon job success or failure. | +| permissions | aws-cdk-lib.aws_iam.PolicyDocument | The IAM permission document for the ScriptJob. | +| script | string | The bash script to run as part of the ScriptJob. | +| environmentJSONVariablesFromIncomingEvent | string[] | The environment variables to import into the ScriptJob from event details field. | +| environmentStringVariablesFromIncomingEvent | string[] | The environment variables to import into the ScriptJob from event details field. | +| environmentVariablesToOutgoingEvent | string[] | The environment variables to export into the outgoing event once the ScriptJob has finished. | +| postScript | string | The bash script to run after the main script has completed. | +| scriptEnvironmentVariables | {[ key: string ]: string} | The variables to pass into the codebuild ScriptJob. | --- -##### `applicationPlaneEventSource`Optional +##### `eventManager`Required ```typescript -public readonly applicationPlaneEventSource: string; +public readonly eventManager: IEventManager; ``` -- *Type:* string +- *Type:* IEventManager -The name of the event source for events coming from the SBT application plane. +The EventManager instance that allows connecting to events flowing between the Control Plane and other components. --- -##### `controlPlaneEventSource`Optional +##### `incomingEvent`Required ```typescript -public readonly controlPlaneEventSource: string; +public readonly incomingEvent: DetailType; ``` -- *Type:* string +- *Type:* DetailType -The name of the event source for events coming from the SBT control plane. +The incoming event DetailType that triggers this job. --- -##### `eventBus`Optional +##### `jobFailureStatus`Required ```typescript -public readonly eventBus: IEventBus; +public readonly jobFailureStatus: {[ key: string ]: string}; ``` -- *Type:* aws-cdk-lib.aws_events.IEventBus +- *Type:* {[ key: string ]: string} -The event bus to register new rules with. +In the case of failure, this is the object that will be included in the outgoing event `jobOutput` field. -One will be created if not provided. +Ex: If the job fails, the outgoing event will look like this: + {'tenantId': 'XXX', 'jobOutput': jobFailureStatus} --- -##### `eventMetadata`Optional +##### `jobIdentifierKey`Required ```typescript -public readonly eventMetadata: {[ key: string ]: string}; +public readonly jobIdentifierKey: string; ``` -- *Type:* {[ key: string ]: string} - -The EventMetadata to use to update the event defaults. - ---- - -### FirehoseAggregatorProps - -Encapsulates the list of properties for a FirehoseAggregator construct. - -#### Initializer - -```typescript -import { FirehoseAggregatorProps } from '@cdklabs/sbt-aws' +- *Type:* string -const firehoseAggregatorProps: FirehoseAggregatorProps = { ... } -``` +The key where the job identifier is to be extracted from in the incoming event. -#### Properties +This will be used as the key that will be populated with +the job identifier in the outgoing event. -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| aggregateKeyPath | string | The JMESPath to find the key value in the incoming data stream that will be aggregated. | -| aggregateValuePath | string | The JMESPath to find the numeric value of key in the incoming data stream that will be aggregated. | -| primaryKeyColumn | string | The name to use for the primary key column for the dynamoDB database. | -| primaryKeyPath | string | The JMESPath to find the primary key value in the incoming data stream. | +Ex: if jobIdentifierKey == 'tenantId' then +the incoming event should look something like this: + {'tenantId': '123', ....} +and the outgoing event will look something like this: + {'tenantId': '123', 'jobOutput': { ... }} --- -##### `aggregateKeyPath`Required +##### `outgoingEvent`Required ```typescript -public readonly aggregateKeyPath: string; +public readonly outgoingEvent: OutgoingEventDetailTypes; ``` -- *Type:* string +- *Type:* OutgoingEventDetailTypes -The JMESPath to find the key value in the incoming data stream that will be aggregated. +The outgoing event DetailTypes that are emitted upon job success or failure. --- -##### `aggregateValuePath`Required +##### `permissions`Required ```typescript -public readonly aggregateValuePath: string; +public readonly permissions: PolicyDocument; ``` -- *Type:* string +- *Type:* aws-cdk-lib.aws_iam.PolicyDocument -The JMESPath to find the numeric value of key in the incoming data stream that will be aggregated. +The IAM permission document for the ScriptJob. --- -##### `primaryKeyColumn`Required +##### `script`Required ```typescript -public readonly primaryKeyColumn: string; +public readonly script: string; ``` - *Type:* string -The name to use for the primary key column for the dynamoDB database. +The bash script to run as part of the ScriptJob. --- -##### `primaryKeyPath`Required +##### `environmentJSONVariablesFromIncomingEvent`Optional ```typescript -public readonly primaryKeyPath: string; +public readonly environmentJSONVariablesFromIncomingEvent: string[]; ``` -- *Type:* string - -The JMESPath to find the primary key value in the incoming data stream. - ---- - -### SampleRegistrationWebPageProps - -Properties for the SampleRegistrationWebPage construct. - -#### Initializer - -```typescript -import { SampleRegistrationWebPageProps } from '@cdklabs/sbt-aws' - -const sampleRegistrationWebPageProps: SampleRegistrationWebPageProps = { ... } -``` +- *Type:* string[] -#### Properties +The environment variables to import into the ScriptJob from event details field. -| **Name** | **Type** | **Description** | -| --- | --- | --- | -| registrationAPI | aws-cdk-lib.aws_apigateway.RestApiBase | The API Gateway that serves the following endpoints:. | -| userProvidedRequiredFieldsForRegistration | string[] | The list of required user-provided fields for registration. | -| autoDeleteBucketObjects | boolean | Whether to automatically delete objects from the S3 bucket when the stack is deleted. | -| imageLogoUrl | string | The URL of the image logo to display on the registration page. | +This argument consists of the names of only JSON-formatted string type variables. +Ex. '{"test": 2}' --- -##### `registrationAPI`Required +##### `environmentStringVariablesFromIncomingEvent`Optional ```typescript -public readonly registrationAPI: RestApiBase; +public readonly environmentStringVariablesFromIncomingEvent: string[]; ``` -- *Type:* aws-cdk-lib.aws_apigateway.RestApiBase - -The API Gateway that serves the following endpoints:. +- *Type:* string[] -POST /redirectmarketplacetoken: redirects to a registration page. +The environment variables to import into the ScriptJob from event details field. -POST /subscriber: creates a new subscriber. +This argument consists of the names of only string type variables. Ex. 'test' --- -##### `userProvidedRequiredFieldsForRegistration`Required +##### `environmentVariablesToOutgoingEvent`Optional ```typescript -public readonly userProvidedRequiredFieldsForRegistration: string[]; +public readonly environmentVariablesToOutgoingEvent: string[]; ``` - *Type:* string[] -The list of required user-provided fields for registration. - -This contains the set of fields that must be provided by the user -when registering a new customer. - -This is used to dynamically update the registration page to create a -form that accepts each of the fields present in this list. - -ex. ['name', 'phone'] +The environment variables to export into the outgoing event once the ScriptJob has finished. --- -##### `autoDeleteBucketObjects`Optional +##### `postScript`Optional ```typescript -public readonly autoDeleteBucketObjects: boolean; +public readonly postScript: string; ``` -- *Type:* boolean -- *Default:* false +- *Type:* string -Whether to automatically delete objects from the S3 bucket when the stack is deleted. +The bash script to run after the main script has completed. --- -##### `imageLogoUrl`Optional +##### `scriptEnvironmentVariables`Optional ```typescript -public readonly imageLogoUrl: string; +public readonly scriptEnvironmentVariables: {[ key: string ]: string}; ``` -- *Type:* string -- *Default:* Amazon logo +- *Type:* {[ key: string ]: string} -The URL of the image logo to display on the registration page. +The variables to pass into the codebuild ScriptJob. --- @@ -3632,6 +4039,134 @@ public readonly tenantManagementTable: TenantManagementTable; --- +### TenantLifecycleScriptJobProps + +Encapsulates the list of properties for a ScriptJobs that handle lifecycle management for tenants. + +#### Initializer + +```typescript +import { TenantLifecycleScriptJobProps } from '@cdklabs/sbt-aws' + +const tenantLifecycleScriptJobProps: TenantLifecycleScriptJobProps = { ... } +``` + +#### Properties + +| **Name** | **Type** | **Description** | +| --- | --- | --- | +| eventManager | IEventManager | The EventManager instance that allows connecting to events flowing between the Control Plane and other components. | +| permissions | aws-cdk-lib.aws_iam.PolicyDocument | The IAM permission document for the ScriptJob. | +| script | string | The bash script to run as part of the ScriptJob. | +| environmentJSONVariablesFromIncomingEvent | string[] | The environment variables to import into the ScriptJob from event details field. | +| environmentStringVariablesFromIncomingEvent | string[] | The environment variables to import into the ScriptJob from event details field. | +| environmentVariablesToOutgoingEvent | string[] | The environment variables to export into the outgoing event once the ScriptJob has finished. | +| postScript | string | The bash script to run after the main script has completed. | +| scriptEnvironmentVariables | {[ key: string ]: string} | The variables to pass into the codebuild ScriptJob. | + +--- + +##### `eventManager`Required + +```typescript +public readonly eventManager: IEventManager; +``` + +- *Type:* IEventManager + +The EventManager instance that allows connecting to events flowing between the Control Plane and other components. + +--- + +##### `permissions`Required + +```typescript +public readonly permissions: PolicyDocument; +``` + +- *Type:* aws-cdk-lib.aws_iam.PolicyDocument + +The IAM permission document for the ScriptJob. + +--- + +##### `script`Required + +```typescript +public readonly script: string; +``` + +- *Type:* string + +The bash script to run as part of the ScriptJob. + +--- + +##### `environmentJSONVariablesFromIncomingEvent`Optional + +```typescript +public readonly environmentJSONVariablesFromIncomingEvent: string[]; +``` + +- *Type:* string[] + +The environment variables to import into the ScriptJob from event details field. + +This argument consists of the names of only JSON-formatted string type variables. +Ex. '{"test": 2}' + +--- + +##### `environmentStringVariablesFromIncomingEvent`Optional + +```typescript +public readonly environmentStringVariablesFromIncomingEvent: string[]; +``` + +- *Type:* string[] + +The environment variables to import into the ScriptJob from event details field. + +This argument consists of the names of only string type variables. Ex. 'test' + +--- + +##### `environmentVariablesToOutgoingEvent`Optional + +```typescript +public readonly environmentVariablesToOutgoingEvent: string[]; +``` + +- *Type:* string[] + +The environment variables to export into the outgoing event once the ScriptJob has finished. + +--- + +##### `postScript`Optional + +```typescript +public readonly postScript: string; +``` + +- *Type:* string + +The bash script to run after the main script has completed. + +--- + +##### `scriptEnvironmentVariables`Optional + +```typescript +public readonly scriptEnvironmentVariables: {[ key: string ]: string}; +``` + +- *Type:* {[ key: string ]: string} + +The variables to pass into the codebuild ScriptJob. + +--- + ### TenantManagementLambdaProps Represents the properties required for the Tenant Management Lambda function. diff --git a/docs/public/README.md b/docs/public/README.md index f458f7d..a113ac2 100644 --- a/docs/public/README.md +++ b/docs/public/README.md @@ -177,7 +177,7 @@ export class ApplicationPlaneStack extends Stack { new sbt.CoreApplicationPlane(this, 'CoreApplicationPlane', { eventManager: props.eventManager, - jobRunnersList: [], + scriptJobs: [], }); } } @@ -191,14 +191,14 @@ Again, SBT allows builders to publish and subscribe directly to EventBridge, and #### Core Application Plane Utilities -Although entirely optional, SBT includes a utility that lets you define, and run arbitrary jobs upon receipt of a control plane message, called a `JobRunner`. This is the mechanism currently used for onboarding and off-boarding in the reference architectures which were ported to SBT (see references at the end of this document). That tenant provisioning/deprovisioning process is depicted below: +Although entirely optional, SBT includes a utility that lets you define, and run arbitrary jobs upon receipt of a control plane message, called a `ScriptJob`. This mechanism is extended to produce two new helper constructs `ProvisioningScriptJob` and `DeprovisioningScriptJob` which are used for onboarding and off-boarding, respectively, in the reference architectures which were ported to SBT (see references at the end of this document). That tenant provisioning/deprovisioning process is depicted below: ![sbt-provisioning.png](../../images/sbt-provisioning.png) -Notice the use of the `provisioning.sh` and `deprovisioning.sh` scripts at the top. These scripts are fed to the `JobRunner` as parameters. Internally the `JobRunner` launches an AWS CodeBuild project, wrapped inside an AWS Step Function, to execute the bash scripts. The `JobRunner` also lets you specify what input variables to feed to the scripts, along with what output variables you expect them to return. Note that in this version of SBT, you can create `JobRunner`s with [`jobRunnerProps`](/API.md#bashjobrunnerprops-) and configure `CoreAppPlane` with `JobRunner`s using its `jobRunnersList` property. The `CoreAppPlane` will then link these `JobRunner`s to EventBridge. Let's take a simple example: imagine our SaaS application deployed only a single S3 bucket per tenant. Let's create a job runner for that provisioning now. +Notice the use of the `provisioning.sh` and `deprovisioning.sh` scripts at the top. These scripts are fed to the `ProvisioningScriptJob` and `DeprovisioningScriptJob` as parameters. Internally the `ScriptJob` launches an AWS CodeBuild project, wrapped inside an AWS Step Function, to execute the bash scripts. The `ScriptJob` also lets you specify what input variables to feed to the scripts, along with what output variables you expect them to return. Note that in this version of SBT, you can create `ScriptJob`s with [`ScriptJobProps`](/API.md#scriptjobprops-) and configure `CoreAppPlane` with `ScriptJob`s using its `scriptJobs` property. The `CoreAppPlane` will then link these `ScriptJob`s to EventBridge. Let's take a simple example: imagine our SaaS application deployed only a single S3 bucket per tenant. Let's create a script job for that provisioning now. ```typescript -const provisioningJobRunnerProps = { +const scriptJobProps = { permissions: PolicyDocument.fromJson(/*See below*/), script: '' /*See below*/, environmentStringVariablesFromIncomingEvent: ['tenantId', 'tier'], @@ -212,7 +212,7 @@ const provisioningJobRunnerProps = { }; ``` -##### Bash Job Runner Properties +##### Script Job Properties Let's take a moment and dissect this object. @@ -220,14 +220,14 @@ Let's take a moment and dissect this object. | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | | **script** | string | A string in bash script format that represents the job to be run (example below) | | **permissions** | [PolicyDocument](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyDocument.html) | An IAM policy document giving this job the IAM permisisons it needs to do what it's being asked to do | -| **environmentStringVariablesFromIncomingEvent** | string[] | The environment variables to import into the BashJobRunner from event details field. | -| **environmentVariablesToOutgoingEvent** | string[] | The environment variables to export into the outgoing event once the BashJobRunner has finished. | -| **scriptEnvironmentVariables** | `{ [key: string]: string }` | The variables to pass into the codebuild BashJobRunner. | +| **environmentStringVariablesFromIncomingEvent** | string[] | The environment variables to import into the ScriptJob from event details field. | +| **environmentVariablesToOutgoingEvent** | string[] | The environment variables to export into the outgoing event once the ScriptJob has finished. | +| **scriptEnvironmentVariables** | `{ [key: string]: string }` | The variables to pass into the codebuild ScriptJob. | | **outgoingEvent** | any | Outgoing EventBridge wiring details | | **incomingEvent** | any | Incoming EventBridge wiring details | | **eventManager** | [IEventManager](/API.md#ieventmanager-) | The EventManager instance that allows connecting to events flowing between the Control Plane and other components. | -The heavy lifting of the `JobRunner` happens with the value of the `script` key. Recall, that this particular example is for provisioning. Also remember that the "SaaS application" we're illustrating here is only provisioning a new S3 bucket for each tenant. Let's take a look at that example provisioning script now: +The heavy lifting of the `ScriptJob` happens with the value of the `script` key. Let's take a look at the example provisioning script now: ```sh echo "starting..." @@ -296,7 +296,7 @@ echo "tenantId: $tenantId" echo "tier: $tier" ``` -Let's examine how exactly those variables get populated. Remember that the `JobRunner` creates an [AWS CodeBuild](https://docs.aws.amazon.com/codebuild/latest/userguide/welcome.html) project internally. When the `JobRunner` creates the CodeBuild project, it can specify what environment variables to provide. Also recall that the `JobRunner` utility is activated with an EventBridge message matching the criteria specified in the `incomingEvent` parameter of the `jobRunnerProps`. The message that arrives via EventBridge has a `detail` JSON Object (see [docs here](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-events-structure.html)) that carries with it contextual information included by the sender, in our case, the control plane. For each key in the `environmentStringVariablesFromIncomingEvent` key, the `JobRunner` extracts the value of a matching key found in the EventBridge message's detail JSON object, and provides that value to the CodeBuild project as an environment variable. +Let's examine how exactly those variables get populated. Remember that the `ScriptJob` creates an [AWS CodeBuild](https://docs.aws.amazon.com/codebuild/latest/userguide/welcome.html) project internally. When the `ScriptJob` creates the CodeBuild project, it can specify what environment variables to provide. Also recall that the `ScriptJob` utility is activated with an EventBridge message matching the criteria specified in the `incomingEvent` parameter of the `ScriptJobProps`. The message that arrives via EventBridge has a `detail` JSON Object (see [docs here](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-events-structure.html)) that carries with it contextual information included by the sender, in our case, the control plane. For each key in the `environmentStringVariablesFromIncomingEvent` key, the `ScriptJob` extracts the value of a matching key found in the EventBridge message's detail JSON object, and provides that value to the CodeBuild project as an environment variable. So, take for example, this sample EventBridge provisioning message sent by a control plane: @@ -347,7 +347,7 @@ echo $tenantConfig export tenantStatus="created" ``` -Similar to how it mapped incoming EventBridge message detail variables to environment variables, the `JobRunner` does almost the same thing but in reverse. The variables specified in the `environmentVariablesToOutgoingEvent` section of `jobRunnerProps` will be extracted from the environment, and sent back in the EventBridge message's detail section. +Similar to how it mapped incoming EventBridge message detail variables to environment variables, the `ScriptJob` does almost the same thing but in reverse. The variables specified in the `environmentVariablesToOutgoingEvent` section of `ScriptJobProps` will be extracted from the environment, and sent back in the EventBridge message's detail section. #### Putting it all together @@ -366,7 +366,7 @@ export class AppPlaneStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props: AppPlaneProps) { super(scope, id, props); - const provisioningJobRunnerProps = { + const provisioningScriptJobProps = { permissions: new PolicyDocument({ statements: [ new PolicyStatement({ @@ -427,15 +427,15 @@ echo "done!" eventManager: props.eventManager, }; - const provisioningJobRunner: sbt.BashJobRunner = new sbt.BashJobRunner( + const provisioningJobScript: sbt.ProvisioningScriptJob = new sbt.ProvisioningScriptJob( this, - 'provisioningJobRunner', - provisioningJobRunnerProps + 'provisioningJobScript', + provisioningScriptJobProps ); new sbt.CoreApplicationPlane(this, 'CoreApplicationPlane', { - eventManager: props.eventManager, - jobRunnersList: [provisioningJobRunner], + eventManager: eventManager, + scriptJobs: [provisioningJobScript, deprovisioningJobScript], }); } } @@ -543,7 +543,7 @@ Now that we've onboarded a tenant, let's take a look at the console to see what First, let's open the [DynamoDB console](https://console.aws.amazon.com/dynamodbv2/home#). Once open, click the `Explore Items` link on the left. On the "Tables" screen, select the table that starts with `ControlPlaneStack`. Notice there is an entry for the tenant we just onboarded. Also notice it's probably still "in progress" -Recall that we deployed a `JobRunner` with our application plane, and it's a wrapper around an AWS Step Function that runs our provisioning script via CodeBuild. Let's take a look at that Step Function now by clicking navigating to [Step Functions in the console](https://console.aws.amazon.com/states/home) (ensure you're in the same region you deployed to). +Recall that we deployed a `ScriptJob` with our application plane, and it's a wrapper around an AWS Step Function that runs our provisioning script via CodeBuild. Let's take a look at that Step Function now by clicking navigating to [Step Functions in the console](https://console.aws.amazon.com/states/home) (ensure you're in the same region you deployed to). The Step Function is likely still running, but feel free to examine the execution. Once finished, it'll return the results back to EventBridge, and close the loop with the Control plane. @@ -575,7 +575,7 @@ The control plane emits this event any time it onboards a new tenant. This event #### Tenant Provision Success -As per our configuration, the application plane emits this event upon completion of onboarding. It contains the `tenantId` and a `tenantOutput` object containing the environment variables (key/value pairs) whose keys have been identified in the `environmentVariablesToOutgoingEvent` parameter. In the example above, a provision success event would look something like this: +As per our configuration, the application plane emits this event upon completion of onboarding. It contains the `tenantId` and a `jobOutput` object containing the environment variables (key/value pairs) whose keys have been identified in the `environmentVariablesToOutgoingEvent` parameter. In the example above, a provision success event would look something like this: ##### Sample provision success event @@ -584,7 +584,7 @@ As per our configuration, the application plane emits this event upon completion "source": "applicationPlaneEventSource", "detail-type": "provisionSuccess", "detail": { - "tenantOutput": { + "jobOutput": { "tenantStatus": "created", "tenantConfig": "{\n \"userPoolId\": \"MY_SAAS_APP_USERPOOL_ID\",\n \"appClientId\": \"MY_SAAS_APP_CLIENT_ID\",\n \"apiGatewayUrl\": \"MY_API_GATEWAY_URL\"\n}", "tenantName": "tenant$RANDOM", @@ -624,7 +624,7 @@ The application plane emits this event upon completion of offboarding. Similar t "source": "applicationPlaneEventSource", "detail-type": "deprovisionSuccess", "detail": { - "tenantOutput": { + "jobOutput": { // defined in the deprovisioning job configuration }, "tenantId": "guid string" diff --git a/package-lock.json b/package-lock.json index 2ff02aa..dbf2dae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@aws-cdk/aws-kinesisfirehose-alpha": "2.140.0-alpha.0", "@aws-cdk/aws-kinesisfirehose-destinations-alpha": "2.140.0-alpha.0", - "@aws-cdk/aws-lambda-python-alpha": "^2.114.1-alpha.0", + "@aws-cdk/aws-lambda-python-alpha": "2.140.0-alpha.0", "cdk-nag": "^2.27.230" }, "devDependencies": { @@ -107,14 +107,14 @@ } }, "node_modules/@aws-cdk/aws-lambda-python-alpha": { - "version": "2.114.1-alpha.0", - "resolved": "https://registry.npmjs.org/@aws-cdk/aws-lambda-python-alpha/-/aws-lambda-python-alpha-2.114.1-alpha.0.tgz", - "integrity": "sha512-ozpcGNBrNjfrEOkTC8gpTJu9g1PCKV62NNGV3kE3hOkqjphss9ytwKjIfUIvS+yjqy8D8/BHM0btJKrNur0RoQ==", + "version": "2.140.0-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-lambda-python-alpha/-/aws-lambda-python-alpha-2.140.0-alpha.0.tgz", + "integrity": "sha512-tJ4GK4fIGjfHEN38NTYnxiovCB7xoR4sZRQtN9XefzpJKKllKxYMXLMF1PRRiOpewLjEtgupN5JG8Kfl/SRxcQ==", "engines": { "node": ">= 14.15.0" }, "peerDependencies": { - "aws-cdk-lib": "^2.114.1", + "aws-cdk-lib": "^2.140.0", "constructs": "^10.0.0" } }, diff --git a/package.json b/package.json index 3b8ad1d..a06c224 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "dependencies": { "@aws-cdk/aws-kinesisfirehose-alpha": "2.140.0-alpha.0", "@aws-cdk/aws-kinesisfirehose-destinations-alpha": "2.140.0-alpha.0", - "@aws-cdk/aws-lambda-python-alpha": "^2.114.1-alpha.0", + "@aws-cdk/aws-lambda-python-alpha": "2.140.0-alpha.0", "cdk-nag": "^2.27.230" }, "keywords": [ diff --git a/scripts/sbt-aws.sh b/scripts/sbt-aws.sh index 5bb8146..a2ce82e 100755 --- a/scripts/sbt-aws.sh +++ b/scripts/sbt-aws.sh @@ -441,7 +441,7 @@ case "$1" in "get-tenant") if [ $# -ne 2 ]; then - echo "Error: delete-tenant requires tenant id" + echo "Error: get-tenant requires tenant id" exit 1 fi get_tenant "$2" diff --git a/src/control-plane/integ.default.ts b/src/control-plane/integ.default.ts index 0a3fe05..8bca5f6 100644 --- a/src/control-plane/integ.default.ts +++ b/src/control-plane/integ.default.ts @@ -5,7 +5,7 @@ import * as cdk from 'aws-cdk-lib'; import { CfnRule, EventBus, Rule } from 'aws-cdk-lib/aws-events'; import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs'; import { AwsSolutionsChecks } from 'cdk-nag'; -import { CognitoAuth, ControlPlane } from '.'; +import * as sbt from '.'; import { DestroyPolicySetter } from '../cdk-aspect/destroy-policy-setter'; export interface IntegStackProps extends cdk.StackProps { @@ -16,11 +16,11 @@ export class IntegStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props: IntegStackProps) { super(scope, id, props); - const cognitoAuth = new CognitoAuth(this, 'CognitoAuth', { + const cognitoAuth = new sbt.CognitoAuth(this, 'CognitoAuth', { setAPIGWScopes: false, // only for testing purposes! }); - const controlPlane = new ControlPlane(this, 'ControlPlane', { + const controlPlane = new sbt.ControlPlane(this, 'ControlPlane', { auth: cognitoAuth, systemAdminEmail: props.systemAdminEmail, }); diff --git a/src/control-plane/tenant-management/tenant-management.service.ts b/src/control-plane/tenant-management/tenant-management.service.ts index 8c92d53..4b1e751 100644 --- a/src/control-plane/tenant-management/tenant-management.service.ts +++ b/src/control-plane/tenant-management/tenant-management.service.ts @@ -133,20 +133,17 @@ export class TenantManagementService extends Construct { const tenantUpdateServiceTarget = new ApiDestination(putTenantAPIDestination, { pathParameterValues: ['$.detail.tenantId'], - event: events.RuleTargetInput.fromEventPath('$.detail.tenantOutput'), + event: events.RuleTargetInput.fromEventPath('$.detail.jobOutput'), }); - props.eventManager.addTargetToEvent( - this, + [ DetailType.PROVISION_SUCCESS, - tenantUpdateServiceTarget - ); - - props.eventManager.addTargetToEvent( - this, + DetailType.PROVISION_FAILURE, DetailType.DEPROVISION_SUCCESS, - tenantUpdateServiceTarget - ); + DetailType.DEPROVISION_FAILURE, + ].forEach((detailType) => { + props.eventManager.addTargetToEvent(this, detailType, tenantUpdateServiceTarget); + }); this.table = table; } diff --git a/src/core-app-plane/core-app-plane.ts b/src/core-app-plane/core-app-plane.ts index 553db20..e8f4729 100644 --- a/src/core-app-plane/core-app-plane.ts +++ b/src/core-app-plane/core-app-plane.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { Construct } from 'constructs'; -import { BashJobRunner } from './bash-job-runner'; +import { ScriptJob } from './script-job'; import { IEventManager, addTemplateTag } from '../utils'; /** @@ -14,7 +14,7 @@ export interface CoreApplicationPlaneProps { /** * The list of JobRunners */ - readonly jobRunnersList?: BashJobRunner[]; + readonly scriptJobs?: ScriptJob[]; } /** @@ -35,8 +35,8 @@ export class CoreApplicationPlane extends Construct { addTemplateTag(this, 'CoreApplicationPlane'); this.eventManager = props.eventManager; - props.jobRunnersList?.forEach((jobRunner) => { - this.eventManager.addTargetToEvent(this, jobRunner.incomingEvent, jobRunner.eventTarget); + props.scriptJobs?.forEach((scriptJob) => { + this.eventManager.addTargetToEvent(this, scriptJob.incomingEvent, scriptJob.eventTarget); }); } } diff --git a/src/core-app-plane/index.ts b/src/core-app-plane/index.ts index fc20c51..5aa8363 100644 --- a/src/core-app-plane/index.ts +++ b/src/core-app-plane/index.ts @@ -2,4 +2,5 @@ // SPDX-License-Identifier: Apache-2.0 export * from './core-app-plane'; -export * from './bash-job-runner'; +export * from './script-job'; +export * from './tenant-lifecycle-script-jobs'; diff --git a/src/core-app-plane/integ.default.ts b/src/core-app-plane/integ.default.ts index e7a6bdb..62d8a62 100644 --- a/src/core-app-plane/integ.default.ts +++ b/src/core-app-plane/integ.default.ts @@ -6,10 +6,9 @@ import { CfnRule, EventBus, Rule } from 'aws-cdk-lib/aws-events'; import { Effect, PolicyDocument, PolicyStatement } from 'aws-cdk-lib/aws-iam'; import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs'; import { AwsSolutionsChecks, NagSuppressions } from 'cdk-nag'; -import { CoreApplicationPlane } from '.'; -import { BashJobRunner, BashJobRunnerProps } from './bash-job-runner'; +import * as sbt from '.'; import { DestroyPolicySetter } from '../cdk-aspect/destroy-policy-setter'; -import { DetailType, EventManager } from '../utils'; +import { EventManager } from '../utils'; export interface IntegStackProps extends cdk.StackProps { eventBusArn?: string; @@ -30,7 +29,7 @@ export class IntegStack extends cdk.Stack { eventManager = new EventManager(this, 'EventManager'); } - const provisioningJobRunnerProps: BashJobRunnerProps = { + const provisioningScriptJobProps: sbt.TenantLifecycleScriptJobProps = { permissions: new PolicyDocument({ statements: [ new PolicyStatement({ @@ -101,12 +100,10 @@ echo "done!" scriptEnvironmentVariables: { TEST: 'test', }, - outgoingEvent: DetailType.PROVISION_SUCCESS, - incomingEvent: DetailType.ONBOARDING_REQUEST, eventManager: eventManager, }; - const deprovisioningJobRunnerProps: BashJobRunnerProps = { + const deprovisioningScriptJobProps: sbt.TenantLifecycleScriptJobProps = { permissions: new PolicyDocument({ statements: [ new PolicyStatement({ @@ -133,25 +130,23 @@ echo "done!" `, environmentStringVariablesFromIncomingEvent: ['tenantId'], environmentVariablesToOutgoingEvent: ['tenantStatus'], - outgoingEvent: DetailType.DEPROVISION_SUCCESS, - incomingEvent: DetailType.OFFBOARDING_REQUEST, eventManager: eventManager, }; - const provisioningJobRunner: BashJobRunner = new BashJobRunner( + const provisioningJobScript: sbt.ProvisioningScriptJob = new sbt.ProvisioningScriptJob( this, - 'provisioningJobRunner', - provisioningJobRunnerProps + 'provisioningJobScript', + provisioningScriptJobProps ); - const deprovisioningJobRunner: BashJobRunner = new BashJobRunner( + const deprovisioningJobScript: sbt.DeprovisioningScriptJob = new sbt.DeprovisioningScriptJob( this, - 'deprovisioningJobRunner', - deprovisioningJobRunnerProps + 'deprovisioningJobScript', + deprovisioningScriptJobProps ); - new CoreApplicationPlane(this, 'CoreApplicationPlane', { + new sbt.CoreApplicationPlane(this, 'CoreApplicationPlane', { eventManager: eventManager, - jobRunnersList: [provisioningJobRunner, deprovisioningJobRunner], + scriptJobs: [provisioningJobScript, deprovisioningJobScript], }); const eventBusWatcherRule = new Rule(this, 'EventBusWatcherRule', { @@ -195,7 +190,7 @@ const integStack = new IntegStack(app, process.env.CDK_PARAM_STACK_ID ?? 'CoreAp NagSuppressions.addResourceSuppressionsByPath( integStack, - `/${integStack.artifactId}/deprovisioningJobRunner/codeBuildProvisionProjectRole/Resource`, + `/${integStack.artifactId}/provisioningJobScript/codeBuildProvisionProjectRole/Resource`, [ { id: 'AwsSolutions-IAM5', @@ -207,7 +202,7 @@ NagSuppressions.addResourceSuppressionsByPath( NagSuppressions.addResourceSuppressionsByPath( integStack, - `/${integStack.artifactId}/provisioningJobRunner/codeBuildProvisionProjectRole/Resource`, + `/${integStack.artifactId}/deprovisioningJobScript/codeBuildProvisionProjectRole/Resource`, [ { id: 'AwsSolutions-IAM5', diff --git a/src/core-app-plane/bash-job-runner.ts b/src/core-app-plane/script-job.ts similarity index 64% rename from src/core-app-plane/bash-job-runner.ts rename to src/core-app-plane/script-job.ts index e1ac5dd..41ea9e5 100644 --- a/src/core-app-plane/bash-job-runner.ts +++ b/src/core-app-plane/script-job.ts @@ -15,23 +15,59 @@ import { Construct } from 'constructs'; import { addTemplateTag, DetailType, IEventManager } from '../utils'; /** - * Encapsulates the list of properties for a BashJobRunner. + * Represents the DetailTypes that can be emitted + * as part of the outgoing event. + * @readonly */ -export interface BashJobRunnerProps { +export interface OutgoingEventDetailTypes { /** - * The key where the tenant identifier is to be extracted from in + * The detail type for a successful event. + */ + readonly success: DetailType; + + /** + * The detail type for a failed event. + */ + readonly failure: DetailType; +} + +/** + * Encapsulates the list of properties for a ScriptJob. + */ +export interface ScriptJobProps { + /** + * The key where the job identifier is to be extracted from in * the incoming event. - * @default 'tenantId' + * + * This will be used as the key that will be populated with + * the job identifier in the outgoing event. + * + * Ex: if jobIdentifierKey == 'tenantId' then + * the incoming event should look something like this: + * {'tenantId': '123', ....} + * and the outgoing event will look something like this: + * {'tenantId': '123', 'jobOutput': { ... }} */ - readonly tenantIdentifierKeyInIncomingEvent?: string; + readonly jobIdentifierKey: string; /** - * The IAM permission document for the BashJobRunner. + * In the case of failure, this is the object that will + * be included in the outgoing event `jobOutput` field. + * + * Ex: If the job fails, the outgoing event will look like this: + * {'tenantId': 'XXX', 'jobOutput': jobFailureStatus} + */ + readonly jobFailureStatus: { + [key: string]: string; + }; + + /** + * The IAM permission document for the ScriptJob. */ readonly permissions: iam.PolicyDocument; /** - * The bash script to run as part of the BashJobRunner. + * The bash script to run as part of the ScriptJob. */ readonly script: string; @@ -41,9 +77,9 @@ export interface BashJobRunnerProps { readonly incomingEvent: DetailType; /** - * The outgoing event DetailType that is emitted upon job completion. + * The outgoing event DetailTypes that are emitted upon job success or failure. */ - readonly outgoingEvent: DetailType; + readonly outgoingEvent: OutgoingEventDetailTypes; /** * The bash script to run after the main script has completed. @@ -51,25 +87,25 @@ export interface BashJobRunnerProps { readonly postScript?: string; /** - * The environment variables to import into the BashJobRunner from event details field. + * The environment variables to import into the ScriptJob from event details field. * This argument consists of the names of only string type variables. Ex. 'test' */ readonly environmentStringVariablesFromIncomingEvent?: string[]; /** - * The environment variables to import into the BashJobRunner from event details field. + * The environment variables to import into the ScriptJob from event details field. * This argument consists of the names of only JSON-formatted string type variables. * Ex. '{"test": 2}' */ readonly environmentJSONVariablesFromIncomingEvent?: string[]; /** - * The environment variables to export into the outgoing event once the BashJobRunner has finished. + * The environment variables to export into the outgoing event once the ScriptJob has finished. */ readonly environmentVariablesToOutgoingEvent?: string[]; /** - * The variables to pass into the codebuild BashJobRunner. + * The variables to pass into the codebuild ScriptJob. */ readonly scriptEnvironmentVariables?: { [key: string]: string; @@ -79,34 +115,33 @@ export interface BashJobRunnerProps { * The EventManager instance that allows connecting to events flowing between * the Control Plane and other components. */ - readonly eventManager: IEventManager; } /** - * Provides a BashJobRunner to execute arbitrary bash code. + * Provides a ScriptJob to execute arbitrary bash code. */ -export class BashJobRunner extends Construct { +export class ScriptJob extends Construct { /** - * The codebuildProject used to implement this BashJobRunner. + * The codebuildProject used to implement this ScriptJob. * @attribute */ public readonly codebuildProject: codebuild.Project; /** - * The StateMachine used to implement this BashJobRunner orchestration. + * The StateMachine used to implement this ScriptJob orchestration. * @attribute */ public readonly provisioningStateMachine: stepfunctions.StateMachine; /** - * The eventTarget to use when triggering this BashJobRunner. + * The eventTarget to use when triggering this ScriptJob. * @attribute */ public readonly eventTarget: IRuleTarget; /** - * The environment variables to export into the outgoing event once the BashJobRunner has finished. + * The environment variables to export into the outgoing event once the ScriptJob has finished. * @attribute */ public readonly environmentVariablesToOutgoingEvent?: string[]; @@ -116,9 +151,9 @@ export class BashJobRunner extends Construct { */ readonly incomingEvent: DetailType; - constructor(scope: Construct, id: string, props: BashJobRunnerProps) { + constructor(scope: Construct, id: string, props: ScriptJobProps) { super(scope, id); - addTemplateTag(this, 'BashJobRunner'); + addTemplateTag(this, 'ScriptJob'); const eventBus = EventBus.fromEventBusArn(this, 'EventBus', props.eventManager.busArn); this.environmentVariablesToOutgoingEvent = props.environmentVariablesToOutgoingEvent; @@ -137,7 +172,7 @@ export class BashJobRunner extends Construct { this.eventTarget = new targets.SfnStateMachine(this.provisioningStateMachine); } - private createCodeBuildProject(props: BashJobRunnerProps): codebuild.Project { + private createCodeBuildProject(props: ScriptJobProps): codebuild.Project { const environmentVariables: { [key: string]: codebuild.BuildEnvironmentVariable; } = {}; @@ -219,20 +254,18 @@ export class BashJobRunner extends Construct { } private createProvisioningStateMachine( - props: BashJobRunnerProps, + props: ScriptJobProps, jobRunnerCodeBuildProject: codebuild.Project, eventBus: IEventBus ): stepfunctions.StateMachine { - const eventSource = props.eventManager.supportedEvents[props.outgoingEvent]; + const successEventSource = props.eventManager.supportedEvents[props.outgoingEvent.success]; + const failureEventSource = props.eventManager.supportedEvents[props.outgoingEvent.failure]; const detailType = props.outgoingEvent; const environmentVariablesOverride: { [name: string]: codebuild.BuildEnvironmentVariable; } = {}; - const tenantIdentifierKeyInIncomingEvent = - props.tenantIdentifierKeyInIncomingEvent ?? 'tenantId'; - props.environmentStringVariablesFromIncomingEvent?.forEach((importedVar: string) => { environmentVariablesOverride[importedVar] = { type: codebuild.BuildEnvironmentVariableType.PLAINTEXT, @@ -255,44 +288,72 @@ export class BashJobRunner extends Construct { logGroupName: `/aws/vendedlogs/states/${this.node.id}-${this.node.addr}`, }); - const startProvisioningCodeBuild = new tasks.CodeBuildStartBuild( - this, - 'startProvisioningCodeBuild', - { - project: jobRunnerCodeBuildProject, - integrationPattern: stepfunctions.IntegrationPattern.RUN_JOB, - environmentVariablesOverride: environmentVariablesOverride, - resultPath: '$.startProvisioningCodeBuild', - } - ); + const startCodeBuild = new tasks.CodeBuildStartBuild(this, 'startCodeBuild', { + project: jobRunnerCodeBuildProject, + integrationPattern: stepfunctions.IntegrationPattern.RUN_JOB, + environmentVariablesOverride: environmentVariablesOverride, + resultPath: '$.startCodeBuild', + }); const exportedVarObj: { [key: string]: any } = { - tenantId: stepfunctions.JsonPath.stringAt(`$.detail.${tenantIdentifierKeyInIncomingEvent}`), - tenantOutput: {}, + [props.jobIdentifierKey]: stepfunctions.JsonPath.stringAt( + `$.detail.${props.jobIdentifierKey}` + ), + jobOutput: {}, }; props.environmentVariablesToOutgoingEvent?.forEach((exportedVar: string) => { - exportedVarObj.tenantOutput[exportedVar] = stepfunctions.JsonPath.arrayGetItem( + exportedVarObj.jobOutput[exportedVar] = stepfunctions.JsonPath.arrayGetItem( stepfunctions.JsonPath.listAt( - `$.startProvisioningCodeBuild.Build.ExportedEnvironmentVariables[?(@.Name==${exportedVar})].Value` + `$.startCodeBuild.Build.ExportedEnvironmentVariables[?(@.Name==${exportedVar})].Value` ), 0 ); }); - const notifyEventBridgeTask = new tasks.EventBridgePutEvents(this, 'notifyEventBridgeTask', { - entries: [ - { - detailType: detailType, - detail: stepfunctions.TaskInput.fromObject(exportedVarObj), - source: eventSource, - eventBus: eventBus, - }, - ], - resultPath: '$.notifyEventBridgeTask', + const notifySuccessEventBridgeTask = new tasks.EventBridgePutEvents( + this, + 'notifySuccessEventBridgeTask', + { + entries: [ + { + detailType: detailType.success, + detail: stepfunctions.TaskInput.fromObject(exportedVarObj), + source: successEventSource, + eventBus: eventBus, + }, + ], + resultPath: '$.notifySuccessEventBridgeTask', + } + ); + + const notifyFailureEventBridgeTask = new tasks.EventBridgePutEvents( + this, + 'notifyFailureEventBridgeTask', + { + entries: [ + { + detailType: detailType.failure, + detail: stepfunctions.TaskInput.fromObject({ + [props.jobIdentifierKey]: stepfunctions.JsonPath.stringAt( + `$.detail.${props.jobIdentifierKey}` + ), + jobOutput: props.jobFailureStatus, + }), + source: failureEventSource, + eventBus: eventBus, + }, + ], + resultPath: '$.notifyFailureEventBridgeTask', + } + ); + + startCodeBuild.addCatch(notifyFailureEventBridgeTask, { + errors: ['States.ALL'], + resultPath: '$.startCodeBuild.Catch', }); const definitionBody = stepfunctions.DefinitionBody.fromChainable( - startProvisioningCodeBuild.next(notifyEventBridgeTask) + startCodeBuild.next(notifySuccessEventBridgeTask) ); const provisioningStateMachine = new stepfunctions.StateMachine( diff --git a/src/core-app-plane/tenant-lifecycle-script-jobs.ts b/src/core-app-plane/tenant-lifecycle-script-jobs.ts new file mode 100644 index 0000000..4163933 --- /dev/null +++ b/src/core-app-plane/tenant-lifecycle-script-jobs.ts @@ -0,0 +1,105 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import * as iam from 'aws-cdk-lib/aws-iam'; +import { Construct } from 'constructs'; +import { ScriptJob, ScriptJobProps } from './script-job'; +import { DetailType, IEventManager } from '../utils'; + +/** + * Encapsulates the list of properties for a ScriptJobs that + * handle lifecycle management for tenants. + */ +export interface TenantLifecycleScriptJobProps { + /** + * The IAM permission document for the ScriptJob. + */ + readonly permissions: iam.PolicyDocument; + + /** + * The bash script to run as part of the ScriptJob. + */ + readonly script: string; + + /** + * The bash script to run after the main script has completed. + */ + readonly postScript?: string; + + /** + * The environment variables to import into the ScriptJob from event details field. + * This argument consists of the names of only string type variables. Ex. 'test' + */ + readonly environmentStringVariablesFromIncomingEvent?: string[]; + + /** + * The environment variables to import into the ScriptJob from event details field. + * This argument consists of the names of only JSON-formatted string type variables. + * Ex. '{"test": 2}' + */ + readonly environmentJSONVariablesFromIncomingEvent?: string[]; + + /** + * The environment variables to export into the outgoing event once the ScriptJob has finished. + */ + readonly environmentVariablesToOutgoingEvent?: string[]; + + /** + * The variables to pass into the codebuild ScriptJob. + */ + readonly scriptEnvironmentVariables?: { + [key: string]: string; + }; + + /** + * The EventManager instance that allows connecting to events flowing between + * the Control Plane and other components. + */ + readonly eventManager: IEventManager; +} + +/** + * Provides a ProvisioningScriptJob to execute arbitrary bash code. + * This is a simple wrapper around ScriptJob that reduces some of the parameters + * that need to be configured. + */ +export class ProvisioningScriptJob extends ScriptJob { + constructor(scope: Construct, id: string, props: TenantLifecycleScriptJobProps) { + const scriptJobProps: ScriptJobProps = { + ...props, + jobIdentifierKey: 'tenantId', + jobFailureStatus: { + tenantStatus: 'Failed to provision tenant.', + }, + incomingEvent: DetailType.ONBOARDING_REQUEST, + outgoingEvent: { + success: DetailType.PROVISION_SUCCESS, + failure: DetailType.PROVISION_FAILURE, + }, + }; + super(scope, id, scriptJobProps); + } +} + +/** + * Provides a ProvisioningScriptJob to execute arbitrary bash code. + * This is a simple wrapper around ScriptJob that reduces some of the parameters + * that need to be configured. + */ +export class DeprovisioningScriptJob extends ScriptJob { + constructor(scope: Construct, id: string, props: TenantLifecycleScriptJobProps) { + const scriptJobProps: ScriptJobProps = { + ...props, + jobIdentifierKey: 'tenantId', + jobFailureStatus: { + tenantStatus: 'Failed to deprovision tenant.', + }, + incomingEvent: DetailType.OFFBOARDING_REQUEST, + outgoingEvent: { + success: DetailType.DEPROVISION_SUCCESS, + failure: DetailType.DEPROVISION_FAILURE, + }, + }; + super(scope, id, scriptJobProps); + } +} diff --git a/test/core-app-plane.test.ts b/test/core-app-plane.test.ts index 8b256ea..26b5dd4 100644 --- a/test/core-app-plane.test.ts +++ b/test/core-app-plane.test.ts @@ -6,8 +6,8 @@ import { Annotations, Match, Template } from 'aws-cdk-lib/assertions'; import { PolicyDocument, PolicyStatement, Effect } from 'aws-cdk-lib/aws-iam'; import { AwsSolutionsChecks, NagSuppressions } from 'cdk-nag'; import { Construct, IConstruct } from 'constructs'; -import { CoreApplicationPlane, BashJobRunner } from '../src/core-app-plane'; -import { DetailType, EventManager } from '../src/utils'; +import { CoreApplicationPlane, ProvisioningScriptJob } from '../src/core-app-plane'; +import { EventManager } from '../src/utils'; class DestroyPolicySetter implements cdk.IAspect { public visit(node: IConstruct): void { @@ -23,12 +23,10 @@ describe('No unsuppressed cdk-nag Warnings or Errors', () => { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const eventManager = new EventManager(this, 'EventManager'); - const provisioningJobRunner: BashJobRunner = new BashJobRunner( + const provisioningJobScript: ProvisioningScriptJob = new ProvisioningScriptJob( this, - 'provisioningJobRunner', + 'provisioningJobScript', { - outgoingEvent: DetailType.PROVISION_SUCCESS, - incomingEvent: DetailType.ONBOARDING_REQUEST, permissions: new PolicyDocument({ statements: [ new PolicyStatement({ @@ -44,7 +42,7 @@ describe('No unsuppressed cdk-nag Warnings or Errors', () => { ); new CoreApplicationPlane(this, 'CoreApplicationPlane', { eventManager: eventManager, - jobRunnersList: [provisioningJobRunner], + scriptJobs: [provisioningJobScript], }); } } @@ -84,12 +82,10 @@ describe('CoreApplicationPlane', () => { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const eventManager = new EventManager(this, 'EventManager'); - const provisioningJobRunner: BashJobRunner = new BashJobRunner( + const provisioningJobScript: ProvisioningScriptJob = new ProvisioningScriptJob( this, - 'provisioningJobRunner', + 'provisioningJobScript', { - outgoingEvent: DetailType.PROVISION_SUCCESS, - incomingEvent: DetailType.ONBOARDING_REQUEST, permissions: new PolicyDocument({ statements: [ new PolicyStatement({ @@ -105,7 +101,7 @@ describe('CoreApplicationPlane', () => { ); new CoreApplicationPlane(this, 'CoreApplicationPlane', { eventManager: eventManager, - jobRunnersList: [provisioningJobRunner], + scriptJobs: [provisioningJobScript], }); } } @@ -130,12 +126,10 @@ describe('CoreApplicationPlane', () => { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const eventManager = new EventManager(this, 'EventManager'); - const provisioningJobRunner: BashJobRunner = new BashJobRunner( + const provisioningJobScript: ProvisioningScriptJob = new ProvisioningScriptJob( this, - 'provisioningJobRunner', + 'provisioningJobScript', { - outgoingEvent: DetailType.PROVISION_SUCCESS, - incomingEvent: DetailType.ONBOARDING_REQUEST, permissions: new PolicyDocument({ statements: [ new PolicyStatement({ @@ -154,7 +148,7 @@ describe('CoreApplicationPlane', () => { ); const coreApplicationPlane = new CoreApplicationPlane(this, 'CoreApplicationPlane', { eventManager: eventManager, - jobRunnersList: [provisioningJobRunner], + scriptJobs: [provisioningJobScript], }); cdk.Aspects.of(coreApplicationPlane).add(new DestroyPolicySetter()); } diff --git a/test/event-manager.test.ts b/test/event-manager.test.ts index 0e88f4d..72c3174 100644 --- a/test/event-manager.test.ts +++ b/test/event-manager.test.ts @@ -6,7 +6,7 @@ import { Capture, Template } from 'aws-cdk-lib/assertions'; import { Effect, PolicyDocument, PolicyStatement } from 'aws-cdk-lib/aws-iam'; import { AwsSolutionsChecks } from 'cdk-nag'; import { CognitoAuth, ControlPlane } from '../src/control-plane'; -import { CoreApplicationPlane, BashJobRunner } from '../src/core-app-plane'; +import { CoreApplicationPlane, ProvisioningScriptJob } from '../src/core-app-plane'; import { DetailType, EventManager } from '../src/utils'; function testForDuplicateRulesInCoreAppPlaneStack(stack: cdk.Stack) { @@ -47,7 +47,9 @@ function testForRulesInOtherStack(stack: cdk.Stack) { return; } - // template.allResourcesProperties('AWS::Events::Rule', eventRuleCapture); + // because there are rules in this stack, check if + // the existing rules are for the onboarding-request + // detail type which is defined in a separate stack const eventRules: { [key: string]: any } = []; do { eventRules.push(eventRuleCapture.asObject()); @@ -90,23 +92,19 @@ describe('EventManager', () => { }); const coreAppPlaneStack = new cdk.Stack(app, 'CoreApplicationPlaneStack'); - const firstProvisioningJobRunner: BashJobRunner = new BashJobRunner( + const firstProvisioningScriptJob: ProvisioningScriptJob = new ProvisioningScriptJob( coreAppPlaneStack, - 'firstProvisioningJobRunner', + 'firstProvisioningScriptJob', { - outgoingEvent: DetailType.PROVISION_SUCCESS, - incomingEvent: DetailType.ONBOARDING_REQUEST, permissions: samplePolicyDocument, script: '', eventManager: controlPlane.eventManager, } ); - const secondProvisioningJobRunner: BashJobRunner = new BashJobRunner( + const secondProvisioningScriptJob: ProvisioningScriptJob = new ProvisioningScriptJob( coreAppPlaneStack, - 'secondProvisioningJobRunner', + 'secondProvisioningScriptJob', { - outgoingEvent: DetailType.PROVISION_SUCCESS, - incomingEvent: DetailType.ONBOARDING_REQUEST, permissions: samplePolicyDocument, script: '', eventManager: controlPlane.eventManager, @@ -114,7 +112,7 @@ describe('EventManager', () => { ); new CoreApplicationPlane(coreAppPlaneStack, 'CoreApplicationPlane', { eventManager: controlPlane.eventManager, - jobRunnersList: [firstProvisioningJobRunner, secondProvisioningJobRunner], + scriptJobs: [firstProvisioningScriptJob, secondProvisioningScriptJob], }); cdk.Aspects.of(controlPlaneStack).add(new AwsSolutionsChecks({ verbose: true })); @@ -144,23 +142,19 @@ describe('EventManager', () => { }); const coreAppPlaneStack = new cdk.Stack(app, 'CoreApplicationPlaneStack'); - const firstProvisioningJobRunner: BashJobRunner = new BashJobRunner( + const firstProvisioningScriptJob: ProvisioningScriptJob = new ProvisioningScriptJob( coreAppPlaneStack, - 'firstProvisioningJobRunner', + 'firstProvisioningScriptJob', { - outgoingEvent: DetailType.PROVISION_SUCCESS, - incomingEvent: DetailType.ONBOARDING_REQUEST, permissions: samplePolicyDocument, script: '', eventManager: eventManager, } ); - const secondProvisioningJobRunner: BashJobRunner = new BashJobRunner( + const secondProvisioningScriptJob: ProvisioningScriptJob = new ProvisioningScriptJob( coreAppPlaneStack, - 'secondProvisioningJobRunner', + 'secondProvisioningScriptJob', { - outgoingEvent: DetailType.PROVISION_SUCCESS, - incomingEvent: DetailType.ONBOARDING_REQUEST, permissions: samplePolicyDocument, script: '', eventManager: eventManager, @@ -168,7 +162,7 @@ describe('EventManager', () => { ); new CoreApplicationPlane(coreAppPlaneStack, 'CoreApplicationPlane', { eventManager: eventManager, - jobRunnersList: [firstProvisioningJobRunner, secondProvisioningJobRunner], + scriptJobs: [firstProvisioningScriptJob, secondProvisioningScriptJob], }); cdk.Aspects.of(controlPlaneStack).add(new AwsSolutionsChecks({ verbose: true })); @@ -198,23 +192,19 @@ describe('EventManager', () => { }); const coreAppPlaneStack = new cdk.Stack(app, 'CoreApplicationPlaneStack'); - const firstProvisioningJobRunner: BashJobRunner = new BashJobRunner( + const firstProvisioningScriptJob: ProvisioningScriptJob = new ProvisioningScriptJob( coreAppPlaneStack, - 'firstProvisioningJobRunner', + 'firstProvisioningScriptJob', { - outgoingEvent: DetailType.PROVISION_SUCCESS, - incomingEvent: DetailType.ONBOARDING_REQUEST, permissions: samplePolicyDocument, script: '', eventManager: eventManager, } ); - const secondProvisioningJobRunner: BashJobRunner = new BashJobRunner( + const secondProvisioningScriptJob: ProvisioningScriptJob = new ProvisioningScriptJob( coreAppPlaneStack, - 'secondProvisioningJobRunner', + 'secondProvisioningScriptJob', { - outgoingEvent: DetailType.PROVISION_SUCCESS, - incomingEvent: DetailType.ONBOARDING_REQUEST, permissions: samplePolicyDocument, script: '', eventManager: eventManager, @@ -222,7 +212,7 @@ describe('EventManager', () => { ); new CoreApplicationPlane(coreAppPlaneStack, 'CoreApplicationPlane', { eventManager: eventManager, - jobRunnersList: [firstProvisioningJobRunner, secondProvisioningJobRunner], + scriptJobs: [firstProvisioningScriptJob, secondProvisioningScriptJob], }); cdk.Aspects.of(controlPlaneStack).add(new AwsSolutionsChecks({ verbose: true })); cdk.Aspects.of(coreAppPlaneStack).add(new AwsSolutionsChecks({ verbose: true })); @@ -246,7 +236,7 @@ describe('EventManager', () => { // and key-in using a DetailType, a value exists for the source, // which is used in the getOrCreateRule(...) function to create // a new event-manager rule. - // (ex. "source: [this.supportedEvents[eventType]]") + // (ex. "source: eventTypes.map((eventType) => this.supportedEvents[eventType]),") it('should have values for all DetailType enum entries', () => { Object.values(DetailType).forEach((detailTypeValues) => { expect(eventManager.supportedEvents[detailTypeValues]).toBeDefined(); From 51950dd2f89f7b12e95ccce777b1542f1e49877d Mon Sep 17 00:00:00 2001 From: Syed Hussain Date: Mon, 29 Jul 2024 22:40:44 +0000 Subject: [PATCH 2/3] fix typo --- API.md | 2 +- src/core-app-plane/tenant-lifecycle-script-jobs.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/API.md b/API.md index 1c69a64..c7360c5 100644 --- a/API.md +++ b/API.md @@ -1215,7 +1215,7 @@ The EventManager instance that allows connecting to events flowing between the C ### DeprovisioningScriptJob -Provides a ProvisioningScriptJob to execute arbitrary bash code. +Provides a DeprovisioningScriptJob to execute arbitrary bash code. This is a simple wrapper around ScriptJob that reduces some of the parameters that need to be configured. diff --git a/src/core-app-plane/tenant-lifecycle-script-jobs.ts b/src/core-app-plane/tenant-lifecycle-script-jobs.ts index 4163933..6b1162f 100644 --- a/src/core-app-plane/tenant-lifecycle-script-jobs.ts +++ b/src/core-app-plane/tenant-lifecycle-script-jobs.ts @@ -82,7 +82,7 @@ export class ProvisioningScriptJob extends ScriptJob { } /** - * Provides a ProvisioningScriptJob to execute arbitrary bash code. + * Provides a DeprovisioningScriptJob to execute arbitrary bash code. * This is a simple wrapper around ScriptJob that reduces some of the parameters * that need to be configured. */ From 9b84c83e3a6d56204edc7f92e89d2b64272f4e2a Mon Sep 17 00:00:00 2001 From: Syed Hussain Date: Fri, 2 Aug 2024 02:09:31 +0000 Subject: [PATCH 3/3] minor readme updates and remove unnecessary args from core-app-plane integ --- docs/public/README.md | 22 ++++++++-------------- src/core-app-plane/integ.default.ts | 2 -- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/docs/public/README.md b/docs/public/README.md index a113ac2..2481077 100644 --- a/docs/public/README.md +++ b/docs/public/README.md @@ -195,10 +195,10 @@ Although entirely optional, SBT includes a utility that lets you define, and run ![sbt-provisioning.png](../../images/sbt-provisioning.png) -Notice the use of the `provisioning.sh` and `deprovisioning.sh` scripts at the top. These scripts are fed to the `ProvisioningScriptJob` and `DeprovisioningScriptJob` as parameters. Internally the `ScriptJob` launches an AWS CodeBuild project, wrapped inside an AWS Step Function, to execute the bash scripts. The `ScriptJob` also lets you specify what input variables to feed to the scripts, along with what output variables you expect them to return. Note that in this version of SBT, you can create `ScriptJob`s with [`ScriptJobProps`](/API.md#scriptjobprops-) and configure `CoreAppPlane` with `ScriptJob`s using its `scriptJobs` property. The `CoreAppPlane` will then link these `ScriptJob`s to EventBridge. Let's take a simple example: imagine our SaaS application deployed only a single S3 bucket per tenant. Let's create a script job for that provisioning now. +Notice the use of the `provisioning.sh` and `deprovisioning.sh` scripts at the top. These scripts are fed to the `ProvisioningScriptJob` and `DeprovisioningScriptJob` as parameters. Internally the `ScriptJob` launches an AWS CodeBuild project, wrapped inside an AWS Step Function, to execute the bash scripts. The `ScriptJob` also lets you specify what input variables to feed to the scripts, along with what output variables you expect them to return. Note that in this version of SBT, you can create the `ScriptJob` construct with [`ScriptJobProps`](/API.md#scriptjobprops-) and configure `CoreAppPlane` with `ScriptJob`s using its `scriptJobs` property. The `CoreAppPlane` will then link these `ScriptJob`s to EventBridge. Let's take a simple example: imagine our SaaS application deployed only a single S3 bucket per tenant. Let's create a `ProvisioningScriptJob` for that provisioning now. ```typescript -const scriptJobProps = { +const scriptJobProps: TenantLifecycleScriptJobProps = { permissions: PolicyDocument.fromJson(/*See below*/), script: '' /*See below*/, environmentStringVariablesFromIncomingEvent: ['tenantId', 'tier'], @@ -206,28 +206,24 @@ const scriptJobProps = { scriptEnvironmentVariables: { TEST: 'test', }, - outgoingEvent: sbt.DetailType.PROVISION_SUCCESS, - incomingEvent: sbt.DetailType.ONBOARDING_REQUEST, eventManager: eventManager /*See below on how to create EventManager*/, }; ``` -##### Script Job Properties +##### ProvisioningScriptJob and DeprovisioningScriptJob Properties (TenantLifecycleScriptJobProps) Let's take a moment and dissect this object. | Key | Type | Purpose | | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | | **script** | string | A string in bash script format that represents the job to be run (example below) | -| **permissions** | [PolicyDocument](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyDocument.html) | An IAM policy document giving this job the IAM permisisons it needs to do what it's being asked to do | +| **permissions** | [PolicyDocument](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_iam.PolicyDocument.html) | An IAM policy document giving this job the IAM permissions it needs to do what it's being asked to do | | **environmentStringVariablesFromIncomingEvent** | string[] | The environment variables to import into the ScriptJob from event details field. | | **environmentVariablesToOutgoingEvent** | string[] | The environment variables to export into the outgoing event once the ScriptJob has finished. | | **scriptEnvironmentVariables** | `{ [key: string]: string }` | The variables to pass into the codebuild ScriptJob. | -| **outgoingEvent** | any | Outgoing EventBridge wiring details | -| **incomingEvent** | any | Incoming EventBridge wiring details | | **eventManager** | [IEventManager](/API.md#ieventmanager-) | The EventManager instance that allows connecting to events flowing between the Control Plane and other components. | -The heavy lifting of the `ScriptJob` happens with the value of the `script` key. Let's take a look at the example provisioning script now: +The heavy lifting of the `ScriptJob` construct (along with constructs that extend it like `ProvisioningScriptJob`) happens with the value of the `script` key. Let's take a look at the example provisioning script now: ```sh echo "starting..." @@ -296,7 +292,7 @@ echo "tenantId: $tenantId" echo "tier: $tier" ``` -Let's examine how exactly those variables get populated. Remember that the `ScriptJob` creates an [AWS CodeBuild](https://docs.aws.amazon.com/codebuild/latest/userguide/welcome.html) project internally. When the `ScriptJob` creates the CodeBuild project, it can specify what environment variables to provide. Also recall that the `ScriptJob` utility is activated with an EventBridge message matching the criteria specified in the `incomingEvent` parameter of the `ScriptJobProps`. The message that arrives via EventBridge has a `detail` JSON Object (see [docs here](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-events-structure.html)) that carries with it contextual information included by the sender, in our case, the control plane. For each key in the `environmentStringVariablesFromIncomingEvent` key, the `ScriptJob` extracts the value of a matching key found in the EventBridge message's detail JSON object, and provides that value to the CodeBuild project as an environment variable. +Let's examine how exactly those variables get populated. Remember that the `ScriptJob` (which is used to extend the `ProvisioningScriptJob` construct) creates an [AWS CodeBuild](https://docs.aws.amazon.com/codebuild/latest/userguide/welcome.html) project internally. When the `ScriptJob` creates the CodeBuild project, it can specify what environment variables to provide. The `ScriptJob` utility is also triggered by an EventBridge message matching the criteria specified in the `incomingEvent` parameter of the `ScriptJobProps`. (You don't need to worry about doing that for `ProvisioningScriptJob` and `DeprovisioningScriptJob` because that is already configured.) The message that arrives via EventBridge has a `detail` JSON Object (see [docs here](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-events-structure.html)) that carries with it contextual information included by the sender, in our case, the control plane. For each key in the `environmentStringVariablesFromIncomingEvent` key, the `ScriptJob` extracts the value of a matching key found in the EventBridge message's detail JSON object, and provides that value to the CodeBuild project as an environment variable. So, take for example, this sample EventBridge provisioning message sent by a control plane: @@ -366,7 +362,7 @@ export class AppPlaneStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props: AppPlaneProps) { super(scope, id, props); - const provisioningScriptJobProps = { + const provisioningScriptJobProps: sbt.TenantLifecycleScriptJobProps = { permissions: new PolicyDocument({ statements: [ new PolicyStatement({ @@ -422,8 +418,6 @@ echo "done!" scriptEnvironmentVariables: { TEST: 'test', }, - outgoingEvent: sbt.DetailType.PROVISION_SUCCESS, - incomingEvent: sbt.DetailType.ONBOARDING_REQUEST, eventManager: props.eventManager, }; @@ -435,7 +429,7 @@ echo "done!" new sbt.CoreApplicationPlane(this, 'CoreApplicationPlane', { eventManager: eventManager, - scriptJobs: [provisioningJobScript, deprovisioningJobScript], + scriptJobs: [provisioningJobScript], }); } } diff --git a/src/core-app-plane/integ.default.ts b/src/core-app-plane/integ.default.ts index 62d8a62..c36b96e 100644 --- a/src/core-app-plane/integ.default.ts +++ b/src/core-app-plane/integ.default.ts @@ -85,12 +85,10 @@ export tenantStatus="created" echo "done!" `, - postScript: '', environmentStringVariablesFromIncomingEvent: ['tenantId', 'tier', 'tenantName', 'email'], environmentJSONVariablesFromIncomingEvent: ['prices'], environmentVariablesToOutgoingEvent: [ 'tenantS3Bucket', - 'someOtherVariable', 'tenantConfig', 'tenantStatus', 'prices', // added so we don't lose it for targets beyond provisioning (ex. billing)