-
Notifications
You must be signed in to change notification settings - Fork 3.9k
/
fargate-service.ts
223 lines (195 loc) · 6.77 KB
/
fargate-service.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
import { Construct } from 'constructs';
import * as ec2 from '../../../aws-ec2';
import * as cdk from '../../../core';
import { BaseService, BaseServiceOptions, DeploymentControllerType, IBaseService, IService, LaunchType } from '../base/base-service';
import { fromServiceAttributes, extractServiceNameFromArn } from '../base/from-service-attributes';
import { TaskDefinition } from '../base/task-definition';
import { ICluster } from '../cluster';
/**
* The properties for defining a service using the Fargate launch type.
*/
export interface FargateServiceProps extends BaseServiceOptions {
/**
* The task definition to use for tasks in the service.
*
* [disable-awslint:ref-via-interface]
*/
readonly taskDefinition: TaskDefinition;
/**
* Specifies whether the task's elastic network interface receives a public IP address.
*
* If true, each task will receive a public IP address.
*
* @default false
*/
readonly assignPublicIp?: boolean;
/**
* The subnets to associate with the service.
*
* @default - Public subnets if `assignPublicIp` is set, otherwise the first available one of Private, Isolated, Public, in that order.
*/
readonly vpcSubnets?: ec2.SubnetSelection;
/**
* The security groups to associate with the service. If you do not specify a security group, a new security group is created.
*
* @default - A new security group is created.
* @deprecated use securityGroups instead.
*/
readonly securityGroup?: ec2.ISecurityGroup;
/**
* The security groups to associate with the service. If you do not specify a security group, a new security group is created.
*
* @default - A new security group is created.
*/
readonly securityGroups?: ec2.ISecurityGroup[];
/**
* The platform version on which to run your service.
*
* If one is not specified, the LATEST platform version is used by default. For more information, see
* [AWS Fargate Platform Versions](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/platform_versions.html)
* in the Amazon Elastic Container Service Developer Guide.
*
* @default Latest
*/
readonly platformVersion?: FargatePlatformVersion;
}
/**
* The interface for a service using the Fargate launch type on an ECS cluster.
*/
export interface IFargateService extends IService {
}
/**
* The properties to import from the service using the Fargate launch type.
*/
export interface FargateServiceAttributes {
/**
* The cluster that hosts the service.
*/
readonly cluster: ICluster;
/**
* The service ARN.
*
* @default - either this, or `serviceName`, is required
*/
readonly serviceArn?: string;
/**
* The name of the service.
*
* @default - either this, or `serviceArn`, is required
*/
readonly serviceName?: string;
}
/**
* This creates a service using the Fargate launch type on an ECS cluster.
*
* @resource AWS::ECS::Service
*/
export class FargateService extends BaseService implements IFargateService {
/**
* Imports from the specified service ARN.
*/
public static fromFargateServiceArn(scope: Construct, id: string, fargateServiceArn: string): IFargateService {
class Import extends cdk.Resource implements IFargateService {
public readonly serviceArn = fargateServiceArn;
public readonly serviceName = extractServiceNameFromArn(this, fargateServiceArn);
}
return new Import(scope, id);
}
/**
* Imports from the specified service attributes.
*/
public static fromFargateServiceAttributes(scope: Construct, id: string, attrs: FargateServiceAttributes): IBaseService {
return fromServiceAttributes(scope, id, attrs);
}
/**
* Constructs a new instance of the FargateService class.
*/
constructor(scope: Construct, id: string, props: FargateServiceProps) {
if (!props.taskDefinition.isFargateCompatible) {
throw new Error('Supplied TaskDefinition is not configured for compatibility with Fargate');
}
if (props.securityGroup !== undefined && props.securityGroups !== undefined) {
throw new Error('Only one of SecurityGroup or SecurityGroups can be populated.');
}
super(scope, id, {
...props,
desiredCount: props.desiredCount,
launchType: LaunchType.FARGATE,
capacityProviderStrategies: props.capacityProviderStrategies,
enableECSManagedTags: props.enableECSManagedTags,
}, {
cluster: props.cluster.clusterName,
taskDefinition: props.deploymentController?.type === DeploymentControllerType.EXTERNAL ? undefined : props.taskDefinition.taskDefinitionArn,
platformVersion: props.platformVersion,
}, props.taskDefinition);
let securityGroups;
if (props.securityGroup !== undefined) {
securityGroups = [props.securityGroup];
} else if (props.securityGroups !== undefined) {
securityGroups = props.securityGroups;
}
if (!props.deploymentController ||
(props.deploymentController.type !== DeploymentControllerType.EXTERNAL)) {
this.configureAwsVpcNetworkingWithSecurityGroups(props.cluster.vpc, props.assignPublicIp, props.vpcSubnets, securityGroups);
}
this.node.addValidation({
validate: () => this.taskDefinition.referencesSecretJsonField
&& props.platformVersion
&& SECRET_JSON_FIELD_UNSUPPORTED_PLATFORM_VERSIONS.includes(props.platformVersion)
? [`The task definition of this service uses at least one container that references a secret JSON field. This feature requires platform version ${FargatePlatformVersion.VERSION1_4} or later.`]
: [],
});
this.node.addValidation({
validate: () => !this.taskDefinition.defaultContainer ? ['A TaskDefinition must have at least one essential container'] : [],
});
}
}
/**
* The platform version on which to run your service.
*
* @see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/platform_versions.html
*/
export enum FargatePlatformVersion {
/**
* The latest, recommended platform version.
*/
LATEST = 'LATEST',
/**
* Version 1.4.0
*
* Supports EFS endpoints, CAP_SYS_PTRACE Linux capability,
* network performance metrics in CloudWatch Container Insights,
* consolidated 20 GB ephemeral volume.
*/
VERSION1_4 = '1.4.0',
/**
* Version 1.3.0
*
* Supports secrets, task recycling.
*/
VERSION1_3 = '1.3.0',
/**
* Version 1.2.0
*
* Supports private registries.
*/
VERSION1_2 = '1.2.0',
/**
* Version 1.1.0
*
* Supports task metadata, health checks, service discovery.
*/
VERSION1_1 = '1.1.0',
/**
* Initial release
*
* Based on Amazon Linux 2017.09.
*/
VERSION1_0 = '1.0.0',
}
const SECRET_JSON_FIELD_UNSUPPORTED_PLATFORM_VERSIONS = [
FargatePlatformVersion.VERSION1_0,
FargatePlatformVersion.VERSION1_1,
FargatePlatformVersion.VERSION1_2,
FargatePlatformVersion.VERSION1_3,
];