in packages/@aws-cdk/aws-neptune-alpha/lib/cluster.ts [618:752]
constructor(scope: Construct, id: string, props: DatabaseClusterProps) {
super(scope, id);
// Enhanced CDK Analytics Telemetry
addConstructMetadata(this, props);
this.vpc = props.vpc;
this.vpcSubnets = props.vpcSubnets ?? { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS };
// Determine the subnet(s) to deploy the Neptune cluster to
const { subnetIds, internetConnectivityEstablished } = this.vpc.selectSubnets(this.vpcSubnets);
// Cannot test whether the subnets are in different AZs, but at least we can test the amount.
if (subnetIds.length < 2) {
throw new Error(`Cluster requires at least 2 subnets, got ${subnetIds.length}`);
}
this.subnetGroup = props.subnetGroup ?? new SubnetGroup(this, 'Subnets', {
description: `Subnets for ${id} database`,
vpc: this.vpc,
vpcSubnets: this.vpcSubnets,
removalPolicy: props.removalPolicy === RemovalPolicy.RETAIN ? props.removalPolicy : undefined,
});
const securityGroups = props.securityGroups ?? [
new ec2.SecurityGroup(this, 'SecurityGroup', {
description: 'Neptune security group',
vpc: this.vpc,
}),
];
// Default to encrypted storage
const storageEncrypted = props.storageEncrypted ?? true;
if (props.kmsKey && !storageEncrypted) {
throw new Error('KMS key supplied but storageEncrypted is false');
}
const deletionProtection = props.deletionProtection ?? (props.removalPolicy === RemovalPolicy.RETAIN ? true : undefined);
this.enableIamAuthentication = props.iamAuthentication;
if (props.instanceType === InstanceType.SERVERLESS && !props.serverlessScalingConfiguration) {
throw new Error('You need to specify a serverless scaling configuration with a db.serverless instance type.');
}
this.validateServerlessScalingConfiguration(props.serverlessScalingConfiguration);
// Create the Neptune cluster
const cluster = new CfnDBCluster(this, 'Resource', {
// Basic
engineVersion: props.engineVersion?.version,
dbClusterIdentifier: props.dbClusterName,
dbSubnetGroupName: this.subnetGroup.subnetGroupName,
vpcSecurityGroupIds: securityGroups.map(sg => sg.securityGroupId),
dbClusterParameterGroupName: props.clusterParameterGroup?.clusterParameterGroupName,
deletionProtection: deletionProtection,
associatedRoles: props.associatedRoles ? props.associatedRoles.map(role => ({ roleArn: role.roleArn })) : undefined,
iamAuthEnabled: Lazy.any({ produce: () => this.enableIamAuthentication }),
dbPort: props.port,
// Backup
backupRetentionPeriod: props.backupRetention?.toDays(),
preferredBackupWindow: props.preferredBackupWindow,
preferredMaintenanceWindow: props.preferredMaintenanceWindow,
// Encryption
kmsKeyId: props.kmsKey?.keyArn,
// CloudWatch Logs exports
enableCloudwatchLogsExports: props.cloudwatchLogsExports?.map(logType => logType.value),
storageEncrypted,
serverlessScalingConfiguration: props.serverlessScalingConfiguration,
// Tags
copyTagsToSnapshot: props.copyTagsToSnapshot,
});
cluster.applyRemovalPolicy(props.removalPolicy, {
applyToUpdateReplacePolicy: true,
});
this.clusterIdentifier = cluster.ref;
this.clusterResourceIdentifier = cluster.attrClusterResourceId;
const port = Token.asNumber(cluster.attrPort);
this.clusterEndpoint = new Endpoint(cluster.attrEndpoint, port);
this.clusterReadEndpoint = new Endpoint(cluster.attrReadEndpoint, port);
// Log retention
const retention = props.cloudwatchLogsRetention;
if (retention) {
props.cloudwatchLogsExports?.forEach(logType => {
new logs.LogRetention(this, `${logType.value}LogRetention`, {
logGroupName: `/aws/neptune/${this.clusterIdentifier}/${logType.value}`,
role: props.cloudwatchLogsRetentionRole,
retention,
});
});
}
// Create the instances
const instanceCount = props.instances ?? DatabaseCluster.DEFAULT_NUM_INSTANCES;
if (instanceCount < 1) {
throw new Error('At least one instance is required');
}
for (let i = 0; i < instanceCount; i++) {
const instanceIndex = i + 1;
const instanceIdentifier = props.instanceIdentifierBase != null ? `${props.instanceIdentifierBase}${instanceIndex}`
: props.dbClusterName != null ? `${props.dbClusterName}instance${instanceIndex}` : undefined;
const instance = new CfnDBInstance(this, `Instance${instanceIndex}`, {
// Link to cluster
dbClusterIdentifier: cluster.ref,
dbInstanceIdentifier: instanceIdentifier,
// Instance properties
dbInstanceClass: props.instanceType._instanceType,
dbParameterGroupName: props.parameterGroup?.parameterGroupName,
autoMinorVersionUpgrade: props.autoMinorVersionUpgrade === true,
});
// We must have a dependency on the NAT gateway provider here to create
// things in the right order.
instance.node.addDependency(internetConnectivityEstablished);
instance.applyRemovalPolicy(props.removalPolicy, {
applyToUpdateReplacePolicy: true,
});
this.instanceIdentifiers.push(instance.ref);
this.instanceEndpoints.push(new Endpoint(instance.attrEndpoint, port));
}
this.connections = new ec2.Connections({
defaultPort: ec2.Port.tcp(port),
securityGroups: securityGroups,
});
}