|
1 | 1 | import {Construct} from "constructs" |
2 | 2 | import {CfnCollection, CfnIndex} from "aws-cdk-lib/aws-opensearchserverless" |
| 3 | +import {CustomResource} from "aws-cdk-lib" |
| 4 | +import {ManagedPolicy, PolicyStatement} from "aws-cdk-lib/aws-iam" |
| 5 | +import {Provider} from "aws-cdk-lib/custom-resources" |
| 6 | +import {LambdaFunction} from "../constructs/LambdaFunction" |
3 | 7 |
|
4 | 8 | export interface VectorIndexProps { |
5 | 9 | readonly indexName: string |
6 | 10 | readonly collection: CfnCollection |
7 | 11 | readonly endpoint: string |
| 12 | + readonly account: string |
| 13 | + readonly region: string |
| 14 | + readonly stackName: string |
| 15 | + readonly logRetentionInDays: number |
| 16 | + readonly logLevel: string |
8 | 17 | } |
9 | 18 |
|
10 | 19 | export class VectorIndex extends Construct { |
11 | 20 | public readonly cfnIndex: CfnIndex |
| 21 | + public readonly indexReady: CustomResource |
12 | 22 |
|
13 | 23 | constructor(scope: Construct, id: string, props: VectorIndexProps) { |
14 | 24 | super(scope, id) |
@@ -61,8 +71,56 @@ export class VectorIndex extends Construct { |
61 | 71 | } |
62 | 72 | }) |
63 | 73 |
|
| 74 | + const collectionArn = `arn:aws:aoss:${props.region}:${props.account}:collection/${props.collection.name}` |
| 75 | + const indexArn = `arn:aws:aoss:${props.region}:${props.account}:index/${props.collection.name}/${props.indexName}` |
| 76 | + |
| 77 | + const getCollectionPolicy = new PolicyStatement({ |
| 78 | + actions: [ |
| 79 | + "opensearchserverless:BatchGetCollection" |
| 80 | + ], |
| 81 | + resources: [collectionArn] |
| 82 | + }) |
| 83 | + const getIndexPolicy = new PolicyStatement({ |
| 84 | + actions: [ |
| 85 | + "opensearchserverless:BatchGetIndex" |
| 86 | + ], |
| 87 | + resources: [indexArn] |
| 88 | + }) |
| 89 | + const waiterFnManagedPolicy = new ManagedPolicy(this, "Policy", { |
| 90 | + description: "Policy for Bedrock Knowledge Base to access S3 and OpenSearch", |
| 91 | + statements: [ |
| 92 | + getCollectionPolicy, |
| 93 | + getIndexPolicy |
| 94 | + ] |
| 95 | + }) |
| 96 | + |
| 97 | + const waiterFn = new LambdaFunction(this, "SlackBotLambda", { |
| 98 | + stackName: props.stackName, |
| 99 | + functionName: `${props.stackName}-VectorIndexWaiter`, |
| 100 | + packageBasePath: "packages/cdk/resources/lambda", |
| 101 | + handler: "index_waiter.handler", |
| 102 | + logRetentionInDays: props.logRetentionInDays, |
| 103 | + logLevel: props.logLevel, |
| 104 | + additionalPolicies: [waiterFnManagedPolicy] |
| 105 | + }) |
| 106 | + |
| 107 | + const provider = new Provider(this, "IndexWaiterProvider", { |
| 108 | + onEventHandler: waiterFn.function |
| 109 | + }) |
| 110 | + |
| 111 | + const indexReady = new CustomResource(this, "IndexReady", { |
| 112 | + serviceToken: provider.serviceToken, |
| 113 | + properties: { |
| 114 | + CollectionName: props.collection.name, |
| 115 | + IndexName: props.indexName |
| 116 | + } |
| 117 | + }) |
64 | 118 | // Ensure collection exists before creating index |
65 | 119 | cfnIndex.node.addDependency(props.collection) |
| 120 | + indexReady.node.addDependency(props.collection) |
| 121 | + indexReady.node.addDependency(cfnIndex) |
| 122 | + |
66 | 123 | this.cfnIndex = cfnIndex |
| 124 | + this.indexReady = indexReady |
67 | 125 | } |
68 | 126 | } |
0 commit comments