/
efs-file-system.test.ts
304 lines (260 loc) · 8.45 KB
/
efs-file-system.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
import { ABSENT, expect as expectCDK, haveResource, ResourcePart, countResources } from '@aws-cdk/assert-internal';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as kms from '@aws-cdk/aws-kms';
import { RemovalPolicy, Size, Stack, Tags } from '@aws-cdk/core';
import * as cxapi from '@aws-cdk/cx-api';
import { FileSystem, LifecyclePolicy, PerformanceMode, ThroughputMode } from '../lib';
let stack = new Stack();
let vpc = new ec2.Vpc(stack, 'VPC');
beforeEach(() => {
stack = new Stack();
vpc = new ec2.Vpc(stack, 'VPC');
});
test(`when ${cxapi.EFS_DEFAULT_ENCRYPTION_AT_REST} is enabled, encryption is enabled by default`, () => {
const customStack = new Stack();
customStack.node.setContext(cxapi.EFS_DEFAULT_ENCRYPTION_AT_REST, true);
const customVpc = new ec2.Vpc(customStack, 'VPC');
new FileSystem(customVpc, 'EfsFileSystem', {
vpc: customVpc,
});
expectCDK(customStack).to(haveResource('AWS::EFS::FileSystem', {
Encrypted: true,
}));
});
test(`when ${cxapi.EFS_DEFAULT_ENCRYPTION_AT_REST} is disabled, encryption is disabled by default`, () => {
const customStack = new Stack();
customStack.node.setContext(cxapi.EFS_DEFAULT_ENCRYPTION_AT_REST, false);
const customVpc = new ec2.Vpc(customStack, 'VPC');
new FileSystem(customVpc, 'EfsFileSystem', {
vpc: customVpc,
});
expectCDK(customStack).to(haveResource('AWS::EFS::FileSystem', {
Encrypted: ABSENT,
}));
});
test(`when ${cxapi.EFS_DEFAULT_ENCRYPTION_AT_REST} is missing, encryption is disabled by default`, () => {
const customStack = new Stack();
const customVpc = new ec2.Vpc(customStack, 'VPC');
new FileSystem(customVpc, 'EfsFileSystem', {
vpc: customVpc,
});
expectCDK(customStack).to(haveResource('AWS::EFS::FileSystem', {
Encrypted: ABSENT,
}));
});
test('default file system is created correctly', () => {
// WHEN
new FileSystem(stack, 'EfsFileSystem', {
vpc,
});
// THEN
expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', {
DeletionPolicy: 'Retain',
UpdateReplacePolicy: 'Retain',
}, ResourcePart.CompleteDefinition));
expectCDK(stack).to(haveResource('AWS::EFS::MountTarget'));
expectCDK(stack).to(haveResource('AWS::EC2::SecurityGroup'));
});
test('unencrypted file system is created correctly with default KMS', () => {
// WHEN
new FileSystem(stack, 'EfsFileSystem', {
vpc,
encrypted: false,
});
// THEN
expectCDK(stack).notTo(haveResource('AWS::EFS::FileSystem', {
Encrypted: true,
}));
});
test('encrypted file system is created correctly with default KMS', () => {
// WHEN
new FileSystem(stack, 'EfsFileSystem', {
vpc,
encrypted: true,
});
// THEN
expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', {
Encrypted: true,
}));
});
test('encrypted file system is created correctly with custom KMS', () => {
const key = new kms.Key(stack, 'customKeyFS');
// WHEN
new FileSystem(stack, 'EfsFileSystem', {
vpc,
encrypted: true,
kmsKey: key,
});
// THEN
/*
* CDK appends 8-digit MD5 hash of the resource path to the logical Id of the resource in order to make sure
* that the id is unique across multiple stacks. There isnt a direct way to identify the exact name of the resource
* in generated CDK, hence hardcoding the MD5 hash here for assertion. Assumption is that the path of the Key wont
* change in this UT. Checked the unique id by generating the cloud formation stack.
*/
expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', {
Encrypted: true,
KmsKeyId: {
'Fn::GetAtt': [
'customKeyFSDDB87C6D',
'Arn',
],
},
}));
});
test('file system is created correctly with a life cycle property', () => {
// WHEN
new FileSystem(stack, 'EfsFileSystem', {
vpc,
lifecyclePolicy: LifecyclePolicy.AFTER_7_DAYS,
});
// THEN
expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', {
LifecyclePolicies: [{
TransitionToIA: 'AFTER_7_DAYS',
}],
}));
});
test('file system is created correctly with performance mode', () => {
// WHEN
new FileSystem(stack, 'EfsFileSystem', {
vpc,
performanceMode: PerformanceMode.MAX_IO,
});
// THEN
expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', {
PerformanceMode: 'maxIO',
}));
});
test('file system is created correctly with bursting throughput mode', () => {
// WHEN
new FileSystem(stack, 'EfsFileSystem', {
vpc,
throughputMode: ThroughputMode.BURSTING,
});
// THEN
expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', {
ThroughputMode: 'bursting',
}));
});
test('Exception when throughput mode is set to PROVISIONED, but provisioned throughput is not set', () => {
expect(() => {
new FileSystem(stack, 'EfsFileSystem', {
vpc,
throughputMode: ThroughputMode.PROVISIONED,
});
}).toThrowError(/Property provisionedThroughputPerSecond is required when throughputMode is PROVISIONED/);
});
test('fails when provisioned throughput is less than the valid range', () => {
expect(() => new FileSystem(stack, 'EfsFileSystem', {
vpc,
throughputMode: ThroughputMode.PROVISIONED,
provisionedThroughputPerSecond: Size.kibibytes(10),
})).toThrow(/cannot be converted into a whole number/);
});
test('fails when provisioned throughput is not a whole number of mebibytes', () => {
expect(() => {
new FileSystem(stack, 'EfsFileSystem2', {
vpc,
throughputMode: ThroughputMode.PROVISIONED,
provisionedThroughputPerSecond: Size.kibibytes(2050),
});
}).toThrowError(/cannot be converted into a whole number/);
});
test('file system is created correctly with provisioned throughput mode', () => {
// WHEN
new FileSystem(stack, 'EfsFileSystem', {
vpc,
throughputMode: ThroughputMode.PROVISIONED,
provisionedThroughputPerSecond: Size.mebibytes(5),
});
// THEN
expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', {
ThroughputMode: 'provisioned',
ProvisionedThroughputInMibps: 5,
}));
});
test('existing file system is imported correctly', () => {
// WHEN
const fs = FileSystem.fromFileSystemAttributes(stack, 'existingFS', {
fileSystemId: 'fs123',
securityGroup: ec2.SecurityGroup.fromSecurityGroupId(stack, 'SG', 'sg-123456789', {
allowAllOutbound: false,
}),
});
fs.connections.allowToAnyIpv4(ec2.Port.tcp(443));
// THEN
expectCDK(stack).to(haveResource('AWS::EC2::SecurityGroupEgress', {
GroupId: 'sg-123456789',
}));
});
test('support tags', () => {
// WHEN
const fileSystem = new FileSystem(stack, 'EfsFileSystem', {
vpc,
});
Tags.of(fileSystem).add('Name', 'LookAtMeAndMyFancyTags');
// THEN
expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', {
FileSystemTags: [
{ Key: 'Name', Value: 'LookAtMeAndMyFancyTags' },
],
}));
});
test('file system is created correctly when given a name', () => {
// WHEN
new FileSystem(stack, 'EfsFileSystem', {
fileSystemName: 'MyNameableFileSystem',
vpc,
});
// THEN
expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', {
FileSystemTags: [
{ Key: 'Name', Value: 'MyNameableFileSystem' },
],
}));
});
test('auto-named if none provided', () => {
// WHEN
const fileSystem = new FileSystem(stack, 'EfsFileSystem', {
vpc,
});
// THEN
expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', {
FileSystemTags: [
{ Key: 'Name', Value: fileSystem.node.path },
],
}));
});
test('removalPolicy is DESTROY', () => {
// WHEN
new FileSystem(stack, 'EfsFileSystem', { vpc, removalPolicy: RemovalPolicy.DESTROY });
// THEN
expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', {
DeletionPolicy: 'Delete',
UpdateReplacePolicy: 'Delete',
}, ResourcePart.CompleteDefinition));
});
test('can specify backup policy', () => {
// WHEN
new FileSystem(stack, 'EfsFileSystem', { vpc, enableAutomaticBackups: true });
// THEN
expectCDK(stack).to(haveResource('AWS::EFS::FileSystem', {
BackupPolicy: {
Status: 'ENABLED',
},
}));
});
test('can create when using a VPC with multiple subnets per availability zone', () => {
// create a vpc with two subnets in the same availability zone.
const oneAzVpc = new ec2.Vpc(stack, 'Vpc', {
maxAzs: 1,
subnetConfiguration: [{ name: 'One', subnetType: ec2.SubnetType.ISOLATED }, { name: 'Two', subnetType: ec2.SubnetType.ISOLATED }],
natGateways: 0,
});
new FileSystem(stack, 'EfsFileSystem', {
vpc: oneAzVpc,
});
// make sure only one mount target is created.
expectCDK(stack).to(countResources('AWS::EFS::MountTarget', 1));
});