Skip to content

Commit

Permalink
feat: replicationConfiguration is to be array
Browse files Browse the repository at this point in the history
  • Loading branch information
badmintoncryer committed Mar 5, 2024
1 parent 41dcee4 commit f77fb2c
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 37 deletions.
43 changes: 23 additions & 20 deletions packages/aws-cdk-lib/aws-efs/lib/efs-file-system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ export interface FileSystemProps {
*
* @default - no replication
*/
readonly replicationConfiguration?: ReplicationConfiguration;
readonly replicationConfiguration?: ReplicationConfiguration[];
}

/**
Expand Down Expand Up @@ -599,23 +599,27 @@ export class FileSystem extends FileSystemBase {
throw new Error('ThroughputMode ELASTIC is not supported for file systems with performanceMode MAX_IO');
}

const { destinationFileSystem, region, availabilityZone, kmsKey } = props.replicationConfiguration ?? {};
if (props.replicationConfiguration) {
if (props.replicationOverwriteProtection === ReplicationOverwriteProtection.DISABLED) {
throw new Error('Cannot configure `replicationConfiguration` when `replicationOverwriteProtection` is set to `DISABLED`');
}

if (destinationFileSystem && (region || availabilityZone || kmsKey)) {
throw new Error('Cannot configure `replicationConfiguration.region`, `replicationConfiguration.az` or `replicationConfiguration.kmsKey` when `replicationConfiguration.destinationFileSystem` is set');
}

if (region && !Token.isUnresolved(region) && !/^[a-z]{2}-((iso[a-z]{0,1}-)|(gov-)){0,1}[a-z]+-{0,1}[0-9]{0,1}$/.test(region)) {
throw new Error('`replicationConfiguration.region` is invalid.');
if (props.replicationConfiguration.length !== 1) {
throw new Error('`replicationConfiguration` must contain exactly one destination');
}

if (availabilityZone && !Token.isUnresolved(availabilityZone) && !region) {
throw new Error('`replicationConfiguration.availabilityZone` cannot be specified without `replicationConfiguration.region`');
}
props.replicationConfiguration.forEach((config) => {
const { destinationFileSystem, region, availabilityZone, kmsKey } = config;

if (destinationFileSystem && (region || availabilityZone || kmsKey)) {
throw new Error('Cannot configure `replicationConfiguration.region`, `replicationConfiguration.az` or `replicationConfiguration.kmsKey` when `replicationConfiguration.destinationFileSystem` is set');
}
if (region && !Token.isUnresolved(region) && !/^[a-z]{2}-((iso[a-z]{0,1}-)|(gov-)){0,1}[a-z]+-{0,1}[0-9]{0,1}$/.test(region)) {
throw new Error('`replicationConfiguration.region` is invalid.');
}
if (availabilityZone && !Token.isUnresolved(availabilityZone) && !region) {
throw new Error('`replicationConfiguration.availabilityZone` cannot be specified without `replicationConfiguration.region`');
}
});
}

// we explictly use 'undefined' to represent 'false' to maintain backwards compatibility since
Expand Down Expand Up @@ -645,14 +649,13 @@ export class FileSystem extends FileSystemBase {
} : undefined;

const replicationConfiguration = props.replicationConfiguration ? {
destinations: [
{
fileSystemId: destinationFileSystem?.fileSystemId,
kmsKeyId: kmsKey?.keyArn,
region: destinationFileSystem ? destinationFileSystem.env.region : (region ?? Stack.of(this).region),
availabilityZoneName: availabilityZone,
},
],
destinations: props.replicationConfiguration.map(
(config) => ({
fileSystemId: config.destinationFileSystem?.fileSystemId,
kmsKeyId: config.kmsKey?.keyArn,
region: config.destinationFileSystem ? config.destinationFileSystem.env.region : (config.region ?? Stack.of(this).region),
availabilityZoneName: config.availabilityZone,
})),
} : undefined;

this._resource = new CfnFileSystem(this, 'Resource', {
Expand Down
45 changes: 28 additions & 17 deletions packages/aws-cdk-lib/aws-efs/test/efs-file-system.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as iam from '../../aws-iam';
import * as kms from '../../aws-kms';
import { App, RemovalPolicy, Size, Stack, Tags } from '../../core';
import * as cxapi from '../../cx-api';
import { FileSystem, LifecyclePolicy, PerformanceMode, ThroughputMode, OutOfInfrequentAccessPolicy, ReplicationOverwriteProtection } from '../lib';
import { FileSystem, LifecyclePolicy, PerformanceMode, ThroughputMode, OutOfInfrequentAccessPolicy, ReplicationOverwriteProtection, ReplicationConfiguration } from '../lib';

let stack = new Stack();
let vpc = new ec2.Vpc(stack, 'VPC');
Expand Down Expand Up @@ -964,7 +964,7 @@ describe('replication configuration', () => {
// WHEN
new FileSystem(stack, 'EfsFileSystem', {
vpc,
replicationConfiguration: {},
replicationConfiguration: [{}],
});

// THEN
Expand All @@ -989,9 +989,9 @@ describe('replication configuration', () => {
});
new FileSystem(stack, 'EfsFileSystem', {
vpc,
replicationConfiguration: {
replicationConfiguration: [{
destinationFileSystem: destination,
},
}],
});

// THEN
Expand All @@ -1012,11 +1012,11 @@ describe('replication configuration', () => {
// WHEN
new FileSystem(stack, 'EfsFileSystem', {
vpc,
replicationConfiguration: {
replicationConfiguration: [{
kmsKey: new kms.Key(stack, 'customKey'),
region: 'us-east-1',
availabilityZone: 'us-east-1a',
},
}],
});

// THEN
Expand All @@ -1043,9 +1043,9 @@ describe('replication configuration', () => {
expect(() => {
new FileSystem(stack, 'EfsFileSystem', {
vpc,
replicationConfiguration: {
replicationConfiguration: [{
region: 'us-east-1',
},
}],
replicationOverwriteProtection: ReplicationOverwriteProtection.DISABLED,
});
}).toThrow('Cannot configure `replicationConfiguration` when `replicationOverwriteProtection` is set to `DISABLED`');
Expand All @@ -1065,10 +1065,10 @@ describe('replication configuration', () => {
expect(() => {
new FileSystem(stack, 'EfsFileSystem', {
vpc,
replicationConfiguration: {
replicationConfiguration: [{
destinationFileSystem: destination,
...config,
},
}],
});
}).toThrow('Cannot configure `replicationConfiguration.region`, `replicationConfiguration.az` or `replicationConfiguration.kmsKey` when `replicationConfiguration.destinationFileSystem` is set');
});
Expand All @@ -1084,10 +1084,10 @@ describe('replication configuration', () => {
expect(() => {
new FileSystem(stack, 'EfsFileSystem', {
vpc,
replicationConfiguration: {
replicationConfiguration: [{
destinationFileSystem: destination,
kmsKey: new kms.Key(stack, 'customKey'),
},
}],
});
}).toThrow('Cannot configure `replicationConfiguration.region`, `replicationConfiguration.az` or `replicationConfiguration.kmsKey` when `replicationConfiguration.destinationFileSystem` is set');
});
Expand All @@ -1097,10 +1097,9 @@ describe('replication configuration', () => {
expect(() => {
new FileSystem(stack, 'EfsFileSystem', {
vpc,
replicationConfiguration: {
enable: true,
replicationConfiguration: [{
region: 'invalid-region',
},
}],
});
}).toThrow('`replicationConfiguration.region` is invalid.');
});
Expand All @@ -1110,10 +1109,22 @@ describe('replication configuration', () => {
expect(() => {
new FileSystem(stack, 'EfsFileSystem', {
vpc,
replicationConfiguration: {
replicationConfiguration: [{
availabilityZone: 'us-east-1a',
},
}],
});
}).toThrow('`replicationConfiguration.availabilityZone` cannot be specified without `replicationConfiguration.region`');
});

test.each([
[[]], [[{ region: 'us-east-1' }, { region: 'ap-northeast-1' }]],
])('throw error for invalid length of replicationConfiguration', (replicationConfiguration) => {
// THEN
expect(() => {
new FileSystem(stack, 'EfsFileSystem', {
vpc,
replicationConfiguration,
});
}).toThrow('`replicationConfiguration` must contain exactly one destination');
});
});

0 comments on commit f77fb2c

Please sign in to comment.