-
Notifications
You must be signed in to change notification settings - Fork 3.7k
/
cluster-resource-provider.ts
124 lines (106 loc) · 4.36 KB
/
cluster-resource-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
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
import * as path from 'path';
import * as ec2 from '@aws-cdk/aws-ec2';
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 { NodeProxyAgentLayer } from '@aws-cdk/lambda-layer-node-proxy-agent';
import { Construct } from 'constructs';
// v2 - keep this import as a separate section to reduce merge conflict when forward merging with the v2 branch.
// eslint-disable-next-line
import { Construct as CoreConstruct } from '@aws-cdk/core';
const HANDLER_DIR = path.join(__dirname, 'cluster-resource-handler');
const HANDLER_RUNTIME = lambda.Runtime.NODEJS_12_X;
export interface ClusterResourceProviderProps {
/**
* The IAM role to assume in order to interact with the cluster.
*/
readonly adminRole: iam.IRole;
/**
* The VPC to provision the functions in.
*/
readonly vpc?: ec2.IVpc;
/**
* The subnets to place the functions in.
*/
readonly subnets?: ec2.ISubnet[];
/**
* Environment to add to the handler.
*/
readonly environment?: { [key: string]: string };
/**
* An AWS Lambda layer that includes the NPM dependency `proxy-agent`.
*
* If not defined, a default layer will be used.
*/
readonly proxyAgentLayer?: lambda.ILayerVersion;
/**
* The security group to associate with the functions.
*
* @default - No security group.
*/
readonly securityGroup?: ec2.ISecurityGroup;
}
/**
* A custom resource provider that handles cluster operations. It serves
* multiple custom resources such as the cluster resource and the fargate
* resource.
*
* @internal
*/
export class ClusterResourceProvider extends NestedStack {
public static getOrCreate(scope: Construct, props: ClusterResourceProviderProps) {
const stack = Stack.of(scope);
const uid = '@aws-cdk/aws-eks.ClusterResourceProvider';
return stack.node.tryFindChild(uid) as ClusterResourceProvider ?? new ClusterResourceProvider(stack, uid, props);
}
/**
* The custom resource provider to use for custom resources.
*/
public readonly provider: cr.Provider;
private constructor(scope: Construct, id: string, props: ClusterResourceProviderProps) {
super(scope as CoreConstruct, id);
// Allow user to override the layer. Layer must contain `proxy-agent` node_module which is required to proxy AWS SDK requests.
const proxyAgentLayer = props.proxyAgentLayer ? props.proxyAgentLayer : new NodeProxyAgentLayer(this, 'NodeProxyAgentLayer');
// This is the only Lambda that calls AWS's EKS API.
const onEvent = new lambda.Function(this, 'OnEventHandler', {
code: lambda.Code.fromAsset(HANDLER_DIR),
description: 'onEvent handler for EKS cluster resource provider',
runtime: HANDLER_RUNTIME,
environment: props.environment,
handler: 'index.onEvent',
timeout: Duration.minutes(1),
vpc: props.subnets ? props.vpc : undefined,
vpcSubnets: props.subnets ? { subnets: props.subnets } : undefined,
securityGroups: props.securityGroup ? [props.securityGroup] : undefined,
layers: [proxyAgentLayer],
});
const isComplete = new lambda.Function(this, 'IsCompleteHandler', {
code: lambda.Code.fromAsset(HANDLER_DIR),
description: 'isComplete handler for EKS cluster resource provider',
runtime: HANDLER_RUNTIME,
environment: props.environment,
handler: 'index.isComplete',
timeout: Duration.minutes(1),
vpc: props.subnets ? props.vpc : undefined,
vpcSubnets: props.subnets ? { subnets: props.subnets } : undefined,
securityGroups: props.securityGroup ? [props.securityGroup] : undefined,
layers: [proxyAgentLayer],
});
this.provider = new cr.Provider(this, 'Provider', {
onEventHandler: onEvent,
isCompleteHandler: isComplete,
totalTimeout: Duration.hours(1),
queryInterval: Duration.minutes(1),
vpc: props.subnets ? props.vpc : undefined,
vpcSubnets: props.subnets ? { subnets: props.subnets } : undefined,
securityGroups: props.securityGroup ? [props.securityGroup] : undefined,
});
props.adminRole.grant(onEvent.role!, 'sts:AssumeRole');
props.adminRole.grant(isComplete.role!, 'sts:AssumeRole');
}
/**
* The custom resource service token for this provider.
*/
public get serviceToken() { return this.provider.serviceToken; }
}