diff --git a/config/constants.ts b/config/constants.ts index d34231430..c334512df 100644 --- a/config/constants.ts +++ b/config/constants.ts @@ -36,6 +36,9 @@ export const vpcProps: VpcLookupOptions = { }, }; +// slack topic for event notification +export const slackTopicName = 'AwsChatBotTopic'; + /** * The SSM Parameter Name for HTTP Lambda Authorizer ARN defined in authorization stack manager */ diff --git a/config/stacks/icaEventPipe.ts b/config/stacks/icaEventPipe.ts index f82166dfb..29b2ce703 100644 --- a/config/stacks/icaEventPipe.ts +++ b/config/stacks/icaEventPipe.ts @@ -1,11 +1,11 @@ import { IcaEventPipeStackProps } from '../../lib/workload/stateful/stacks/ica-event-pipe/stack'; -import { eventBusName, icaAwsAccountNumber } from '../constants'; +import { eventBusName, icaAwsAccountNumber, slackTopicName } from '../constants'; export const getIcaEventPipeStackProps = (): IcaEventPipeStackProps => { return { name: 'IcaEventPipeStack', eventBusName: eventBusName, - slackTopicName: 'AwsChatBotTopic', + slackTopicName: slackTopicName, icaAwsAccountNumber: icaAwsAccountNumber, }; }; diff --git a/config/stacks/sequenceRunManager.ts b/config/stacks/sequenceRunManager.ts index d613f7285..bdcdb1f95 100644 --- a/config/stacks/sequenceRunManager.ts +++ b/config/stacks/sequenceRunManager.ts @@ -1,4 +1,5 @@ import { + region, AppStage, basespaceAccessTokenSecretName, cognitoApiGatewayConfig, @@ -7,10 +8,14 @@ import { eventBusName, logsApiGatewayConfig, vpcProps, + slackTopicName, + accountIdAlias, } from '../constants'; import { SequenceRunManagerStackProps } from '../../lib/workload/stateless/stacks/sequence-run-manager/deploy/stack'; export const getSequenceRunManagerStackProps = (stage: AppStage): SequenceRunManagerStackProps => { + const slackTopicArn = + 'arn:aws:sns:' + region + ':' + accountIdAlias[stage] + ':' + slackTopicName; return { vpcProps, lambdaSecurityGroupName: computeSecurityGroupName, @@ -23,5 +28,6 @@ export const getSequenceRunManagerStackProps = (stage: AppStage): SequenceRunMan customDomainNamePrefix: 'sequence', }, bsshTokenSecretName: basespaceAccessTokenSecretName, + slackTopicArn: slackTopicArn, }; }; diff --git a/lib/workload/stateless/stacks/sequence-run-manager/deploy/stack.ts b/lib/workload/stateless/stacks/sequence-run-manager/deploy/stack.ts index 237204099..38751be39 100644 --- a/lib/workload/stateless/stacks/sequence-run-manager/deploy/stack.ts +++ b/lib/workload/stateless/stacks/sequence-run-manager/deploy/stack.ts @@ -4,7 +4,8 @@ import { aws_lambda, aws_secretsmanager, Duration, Stack } from 'aws-cdk-lib'; import { Construct } from 'constructs'; import { ISecurityGroup, IVpc, SecurityGroup, Vpc, VpcLookupOptions } from 'aws-cdk-lib/aws-ec2'; import { EventBus, IEventBus, Rule } from 'aws-cdk-lib/aws-events'; -import { LambdaFunction } from 'aws-cdk-lib/aws-events-targets'; +import { Topic } from 'aws-cdk-lib/aws-sns'; +import { LambdaFunction, SnsTopic } from 'aws-cdk-lib/aws-events-targets'; import { PythonFunction, PythonLayerVersion } from '@aws-cdk/aws-lambda-python-alpha'; import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations'; import { @@ -24,6 +25,7 @@ export interface SequenceRunManagerStackProps { mainBusName: string; apiGatewayCognitoProps: ApiGatewayConstructProps; bsshTokenSecretName: string; + slackTopicArn: string; } export class SequenceRunManagerStack extends Stack { @@ -92,9 +94,12 @@ export class SequenceRunManagerStack extends Stack { compatibleArchitectures: [Architecture.ARM_64], }); + const topic: Topic = Topic.fromTopicArn(this, 'SlackTopic', props.slackTopicArn) as Topic; + this.createMigrationHandler(); this.createApiHandlerAndIntegration(props); this.createProcSqsHandler(); + this.createSlackNotificationHandler(topic); } private createPythonFunction(name: string, props: object): PythonFunction { @@ -217,4 +222,28 @@ export class SequenceRunManagerStack extends Stack { eventRule.addTarget(new LambdaFunction(fn)); } + + private createSlackNotificationHandler(topic: Topic) { + /** + * subscribe to the 'SequenceRunStateChange' event, and send the slack notification toptic when the failed event is triggered. + */ + + const eventRule = new Rule(this, this.stackName + 'EventRule', { + ruleName: this.stackName + 'EventRule', + description: 'Rule to send Failed SequenceRunStateChange events to the SlackTopic', + eventBus: this.mainBus, + }); + eventRule.addEventPattern({ + source: ['orcabus.sequencerunmanager'], + detailType: ['SequenceRunStateChange'], + detail: { + status: ['FAILED'], + id: [{ exists: true }], + instrumentRunId: [{ exists: true }], + sampleSheetName: [{ exists: true }], + startTime: [{ exists: true }], + }, + }); + eventRule.addTarget(new SnsTopic(topic)); + } }