-
Notifications
You must be signed in to change notification settings - Fork 4k
/
Copy pathexternal-service.ts
190 lines (164 loc) · 7.3 KB
/
external-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
import { Construct } from 'constructs';
import * as appscaling from '../../../aws-applicationautoscaling';
import * as ec2 from '../../../aws-ec2';
import * as elbv2 from '../../../aws-elasticloadbalancingv2';
import * as cloudmap from '../../../aws-servicediscovery';
import { ArnFormat, Resource, Stack } from '../../../core';
import { AssociateCloudMapServiceOptions, BaseService, BaseServiceOptions, CloudMapOptions, DeploymentControllerType, EcsTarget, IBaseService, IEcsLoadBalancerTarget, IService, LaunchType, PropagatedTagSource } from '../base/base-service';
import { fromServiceAttributes } from '../base/from-service-attributes';
import { ScalableTaskCount } from '../base/scalable-task-count';
import { Compatibility, LoadBalancerTargetOptions, TaskDefinition } from '../base/task-definition';
import { ICluster } from '../cluster';
/**
* The properties for defining a service using the External launch type.
*/
export interface ExternalServiceProps extends BaseServiceOptions {
/**
* The task definition to use for tasks in the service.
*
* [disable-awslint:ref-via-interface]
*/
readonly taskDefinition: TaskDefinition;
/**
* 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 interface for a service using the External launch type on an ECS cluster.
*/
export interface IExternalService extends IService {
}
/**
* The properties to import from the service using the External launch type.
*/
export interface ExternalServiceAttributes {
/**
* 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 External launch type on an ECS cluster.
*
* @resource AWS::ECS::Service
*/
export class ExternalService extends BaseService implements IExternalService {
/**
* Imports from the specified service ARN.
*/
public static fromExternalServiceArn(scope: Construct, id: string, externalServiceArn: string): IExternalService {
class Import extends Resource implements IExternalService {
public readonly serviceArn = externalServiceArn;
public readonly serviceName = Stack.of(scope).splitArn(externalServiceArn, ArnFormat.SLASH_RESOURCE_NAME).resourceName as string;
}
return new Import(scope, id);
}
/**
* Imports from the specified service attributes.
*/
public static fromExternalServiceAttributes(scope: Construct, id: string, attrs: ExternalServiceAttributes): IBaseService {
return fromServiceAttributes(scope, id, attrs);
}
/**
* Constructs a new instance of the ExternalService class.
*/
constructor(scope: Construct, id: string, props: ExternalServiceProps) {
if (props.minHealthyPercent !== undefined && props.maxHealthyPercent !== undefined && props.minHealthyPercent >= props.maxHealthyPercent) {
throw new Error('Minimum healthy percent must be less than maximum healthy percent.');
}
if (props.taskDefinition.compatibility !== Compatibility.EXTERNAL) {
throw new Error('Supplied TaskDefinition is not configured for compatibility with ECS Anywhere cluster');
}
if (props.cluster.defaultCloudMapNamespace !== undefined) {
throw new Error (`Cloud map integration is not supported for External service ${props.cluster.defaultCloudMapNamespace}`);
}
if (props.cloudMapOptions !== undefined) {
throw new Error ('Cloud map options are not supported for External service');
}
if (props.enableExecuteCommand !== undefined) {
throw new Error ('Enable Execute Command options are not supported for External service');
}
if (props.capacityProviderStrategies !== undefined) {
throw new Error ('Capacity Providers are not supported for External service');
}
const propagateTagsFromSource = props.propagateTags ?? PropagatedTagSource.NONE;
super(scope, id, {
...props,
desiredCount: props.desiredCount,
maxHealthyPercent: props.maxHealthyPercent === undefined ? 100 : props.maxHealthyPercent,
minHealthyPercent: props.minHealthyPercent === undefined ? 0 : props.minHealthyPercent,
launchType: LaunchType.EXTERNAL,
propagateTags: propagateTagsFromSource,
enableECSManagedTags: props.enableECSManagedTags,
},
{
cluster: props.cluster.clusterName,
taskDefinition: props.deploymentController?.type === DeploymentControllerType.EXTERNAL ? undefined : props.taskDefinition.taskDefinitionArn,
}, props.taskDefinition);
this.node.addValidation({
validate: () => !this.taskDefinition.defaultContainer ? ['A TaskDefinition must have at least one essential container'] : [],
});
this.node.addValidation({
validate: () => this.networkConfiguration !== undefined ? ['Network configurations not supported for an external service'] : [],
});
}
/**
* Overriden method to throw error as `attachToApplicationTargetGroup` is not supported for external service
*/
public attachToApplicationTargetGroup(_targetGroup: elbv2.IApplicationTargetGroup): elbv2.LoadBalancerTargetProps {
throw new Error ('Application load balancer cannot be attached to an external service');
}
/**
* Overriden method to throw error as `loadBalancerTarget` is not supported for external service
*/
public loadBalancerTarget(_options: LoadBalancerTargetOptions): IEcsLoadBalancerTarget {
throw new Error ('External service cannot be attached as load balancer targets');
}
/**
* Overriden method to throw error as `registerLoadBalancerTargets` is not supported for external service
*/
public registerLoadBalancerTargets(..._targets: EcsTarget[]) {
throw new Error ('External service cannot be registered as load balancer targets');
}
/**
* Overriden method to throw error as `configureAwsVpcNetworkingWithSecurityGroups` is not supported for external service
*/
// eslint-disable-next-line max-len, no-unused-vars
protected configureAwsVpcNetworkingWithSecurityGroups(_vpc: ec2.IVpc, _assignPublicIp?: boolean, _vpcSubnets?: ec2.SubnetSelection, _securityGroups?: ec2.ISecurityGroup[]) {
throw new Error ('Only Bridge network mode is supported for external service');
}
/**
* Overriden method to throw error as `autoScaleTaskCount` is not supported for external service
*/
public autoScaleTaskCount(_props: appscaling.EnableScalingProps): ScalableTaskCount {
throw new Error ('Autoscaling not supported for external service');
}
/**
* Overriden method to throw error as `enableCloudMap` is not supported for external service
*/
public enableCloudMap(_options: CloudMapOptions): cloudmap.Service {
throw new Error ('Cloud map integration not supported for an external service');
}
/**
* Overriden method to throw error as `associateCloudMapService` is not supported for external service
*/
public associateCloudMapService(_options: AssociateCloudMapServiceOptions): void {
throw new Error ('Cloud map service association is not supported for an external service');
}
}