packages/@aws-cdk/aws-msk-alpha/lib/serverless-cluster.ts (85 lines of code) (raw):

import * as ec2 from 'aws-cdk-lib/aws-ec2'; import { Fn, Lazy, Names, ValidationError } from 'aws-cdk-lib'; import * as constructs from 'constructs'; import { ClusterBase, ICluster } from '.'; import { CfnServerlessCluster } from 'aws-cdk-lib/aws-msk'; import { addConstructMetadata } from 'aws-cdk-lib/core/lib/metadata-resource'; /** * Properties for a MSK Serverless Cluster */ export interface ServerlessClusterProps { /** * The physical name of the cluster. * * @default - auto generate */ readonly clusterName?: string; /** * The configuration of the Amazon VPCs for the cluster. * You can specify up to 5 VPC configurations. */ readonly vpcConfigs: VpcConfig[]; } /** * The configuration of the Amazon VPCs for the cluster. */ export interface VpcConfig { /** * Defines the virtual networking environment for this cluster. * Must have at least 2 subnets in two different AZs. */ readonly vpc: ec2.IVpc; /** * The subnets associated with the cluster. * * @default - the Vpc default strategy if not specified. */ readonly vpcSubnets?: ec2.SubnetSelection; /** * The security groups associated with the cluster. * You can specify up to 5 security groups. * * @default - create new security group */ readonly securityGroups?: ec2.ISecurityGroup[]; } /** * Create a MSK Serverless Cluster. * * @resource AWS::MSK::ServerlessCluster */ export class ServerlessCluster extends ClusterBase { /** * Reference an existing cluster, defined outside of the CDK code, by name. */ public static fromClusterArn( scope: constructs.Construct, id: string, clusterArn: string, ): ICluster { class Import extends ClusterBase { public readonly clusterArn = clusterArn; public readonly clusterName = Fn.select(1, Fn.split('/', clusterArn)); // ['arn:partition:kafka:region:account-id', clusterName, clusterId] } return new Import(scope, id); } public readonly clusterArn: string; public readonly clusterName: string; private _securityGroups: ec2.ISecurityGroup[] = []; constructor(scope: constructs.Construct, id: string, props: ServerlessClusterProps) { super(scope, id, { physicalName: props.clusterName ?? Lazy.string({ produce: () => Names.uniqueResourceName(this, { maxLength: 64 }), }), }); // Enhanced CDK Analytics Telemetry addConstructMetadata(this, props); if (props.vpcConfigs.length < 1 || props.vpcConfigs.length > 5) { throw new ValidationError(`\`vpcConfigs\` must contain between 1 and 5 configurations, got ${props.vpcConfigs.length} configurations.`, this); } const vpcConfigs = props.vpcConfigs.map((vpcConfig, index) => this._renderVpcConfig(vpcConfig, index)); this._connections = new ec2.Connections({ securityGroups: this._securityGroups, }); /** * TODO At the time of implementation, MSK Serverless only supports IAM authentication, so it cannot be disabled. * If it becomes configurable in the future, the property will need to be exposed. * * @see https://docs.aws.amazon.com/msk/latest/developerguide/serverless.html */ const resource = new CfnServerlessCluster(this, 'Resource', { clusterName: this.physicalName, clientAuthentication: { sasl: { iam: { enabled: true, }, }, }, vpcConfigs, }); this.clusterName = this.getResourceNameAttribute( Fn.select(1, Fn.split('/', resource.ref)), ); this.clusterArn = resource.ref; } /** * Render Vpc Config property */ private _renderVpcConfig(vpcConfig: VpcConfig, index: number): CfnServerlessCluster.VpcConfigProperty { const subnetSelection = vpcConfig.vpc.selectSubnets(vpcConfig.vpcSubnets); if (subnetSelection.subnets.length < 2) { throw new ValidationError(`Cluster requires at least 2 subnets, got ${subnetSelection.subnets.length} subnet.`, this); } let securityGroups: ec2.ISecurityGroup[] = []; if (vpcConfig.securityGroups) { if (vpcConfig.securityGroups.length < 1 || vpcConfig.securityGroups.length > 5) { throw new ValidationError(`\`securityGroups\` must contain between 1 and 5 elements, got ${vpcConfig.securityGroups.length} elements.`, this); } securityGroups = vpcConfig.securityGroups; } else { securityGroups.push(new ec2.SecurityGroup(this, `SecurityGroup-${index}`, { description: 'MSK Serverless security group', vpc: vpcConfig.vpc, })); } this._securityGroups.push(...securityGroups); return { subnetIds: subnetSelection.subnets.map((subnet) => subnet.subnetId), securityGroups: securityGroups?.map((securityGroup) => securityGroup.securityGroupId), }; } }