-
Notifications
You must be signed in to change notification settings - Fork 4.1k
/
Copy pathreplica-provider.ts
98 lines (85 loc) · 3 KB
/
replica-provider.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
import * as path from 'path';
import * as iam from '@aws-cdk/aws-iam';
import * as lambda from '@aws-cdk/aws-lambda';
import { Duration, NestedStack, Stack } from '@aws-cdk/core';
import * as cr from '@aws-cdk/custom-resources';
import { Construct } from 'constructs';
// keep this import separate from other imports to reduce chance for merge conflicts with v2-main
// eslint-disable-next-line no-duplicate-imports, import/order
import { Construct as CoreConstruct } from '@aws-cdk/core';
/**
* Properties for a ReplicaProvider
*/
export interface ReplicaProviderProps {
/**
* The timeout for the replication operation.
*
* @default Duration.minutes(30)
*/
readonly timeout?: Duration;
}
export class ReplicaProvider extends NestedStack {
/**
* Creates a stack-singleton resource provider nested stack.
*/
public static getOrCreate(scope: Construct, props: ReplicaProviderProps = {}) {
const stack = Stack.of(scope);
const uid = '@aws-cdk/aws-dynamodb.ReplicaProvider';
return stack.node.tryFindChild(uid) as ReplicaProvider ?? new ReplicaProvider(stack, uid, props);
}
/**
* The custom resource provider.
*/
public readonly provider: cr.Provider;
/**
* The onEvent handler
*/
public readonly onEventHandler: lambda.Function;
/**
* The isComplete handler
*/
public readonly isCompleteHandler: lambda.Function;
private constructor(scope: Construct, id: string, props: ReplicaProviderProps = {}) {
super(scope as CoreConstruct, id);
const code = lambda.Code.fromAsset(path.join(__dirname, 'replica-handler'));
// Issues UpdateTable API calls
this.onEventHandler = new lambda.Function(this, 'OnEventHandler', {
code,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.onEventHandler',
timeout: Duration.minutes(5),
});
// Checks if table is back to `ACTIVE` state
this.isCompleteHandler = new lambda.Function(this, 'IsCompleteHandler', {
code,
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.isCompleteHandler',
timeout: Duration.seconds(30),
});
// Allows the creation of the `AWSServiceRoleForDynamoDBReplication` service linked role
this.onEventHandler.addToRolePolicy(
new iam.PolicyStatement({
actions: ['iam:CreateServiceLinkedRole'],
resources: [Stack.of(this).formatArn({
service: 'iam',
region: '', // IAM is region-less
resource: 'role',
resourceName: 'aws-service-role/replication.dynamodb.amazonaws.com/AWSServiceRoleForDynamoDBReplication',
})],
}),
);
// Required for replica table creation
this.onEventHandler.addToRolePolicy(
new iam.PolicyStatement({
actions: ['dynamodb:DescribeLimits'],
resources: ['*'],
}),
);
this.provider = new cr.Provider(this, 'Provider', {
onEventHandler: this.onEventHandler,
isCompleteHandler: this.isCompleteHandler,
queryInterval: Duration.seconds(10),
totalTimeout: props.timeout,
});
}
}