-
Notifications
You must be signed in to change notification settings - Fork 4k
/
Copy pathscheduled-task-base.ts
225 lines (197 loc) · 6.98 KB
/
scheduled-task-base.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
import { Schedule } from '@aws-cdk/aws-applicationautoscaling';
import { ISecurityGroup, IVpc, SubnetSelection, SubnetType } from '@aws-cdk/aws-ec2';
import { AwsLogDriver, Cluster, ContainerImage, ICluster, LogDriver, Secret, TaskDefinition } from '@aws-cdk/aws-ecs';
import { Rule } from '@aws-cdk/aws-events';
import { EcsTask } from '@aws-cdk/aws-events-targets';
import { Stack } from '@aws-cdk/core';
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';
/**
* The properties for the base ScheduledEc2Task or ScheduledFargateTask task.
*/
export interface ScheduledTaskBaseProps {
/**
* The name of the cluster that hosts the service.
*
* If a cluster is specified, the vpc construct should be omitted. Alternatively, you can omit both cluster and vpc.
* @default - create a new cluster; if both cluster and vpc are omitted, a new VPC will be created for you.
*/
readonly cluster?: ICluster;
/**
* The VPC where the container instances will be launched or the elastic network interfaces (ENIs) will be deployed.
*
* If a vpc is specified, the cluster construct should be omitted. Alternatively, you can omit both vpc and cluster.
* @default - uses the VPC defined in the cluster or creates a new VPC.
*/
readonly vpc?: IVpc;
/**
* The schedule or rate (frequency) that determines when CloudWatch Events
* runs the rule. For more information, see
* [Schedule Expression Syntax for Rules](https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html)
* in the Amazon CloudWatch User Guide.
*/
readonly schedule: Schedule;
/**
* Indicates whether the rule is enabled.
*
* @default true
*/
readonly enabled?: boolean;
/**
* A name for the rule.
*
* @default - AWS CloudFormation generates a unique physical ID and uses that ID
* for the rule name. For more information, see [Name Type](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-name.html).
*/
readonly ruleName?: string;
/**
* The desired number of instantiations of the task definition to keep running on the service.
*
* @default 1
*/
readonly desiredTaskCount?: number;
/**
* In what subnets to place the task's ENIs
*
* (Only applicable in case the TaskDefinition is configured for AwsVpc networking)
*
* @default Private subnets
*/
readonly subnetSelection?: SubnetSelection;
/**
* Existing security groups to use for your service.
*
* @default - a new security group will be created.
*/
readonly securityGroups?: ISecurityGroup[]
}
export interface ScheduledTaskImageProps {
/**
* The image used to start a container. Image or taskDefinition must be specified, but not both.
*
* @default - none
*/
readonly image: ContainerImage;
/**
* The command that is passed to the container.
*
* If you provide a shell command as a single string, you have to quote command-line arguments.
*
* @default - CMD value built into container image.
*/
readonly command?: string[];
/**
* The environment variables to pass to the container.
*
* @default none
*/
readonly environment?: { [key: string]: string };
/**
* The secret to expose to the container as an environment variable.
*
* @default - No secret environment variables.
*/
readonly secrets?: { [key: string]: Secret };
/**
* The log driver to use.
*
* @default - AwsLogDriver if enableLogging is true
*/
readonly logDriver?: LogDriver;
}
/**
* The base class for ScheduledEc2Task and ScheduledFargateTask tasks.
*/
export abstract class ScheduledTaskBase extends CoreConstruct {
/**
* The name of the cluster that hosts the service.
*/
public readonly cluster: ICluster;
/**
* The desired number of instantiations of the task definition to keep running on the service.
*
* The minimum value is 1
*/
public readonly desiredTaskCount: number;
/**
* In what subnets to place the task's ENIs
*
* (Only applicable in case the TaskDefinition is configured for AwsVpc networking)
*
* @default Private subnets
*/
public readonly subnetSelection: SubnetSelection;
/**
* The CloudWatch Events rule for the service.
*/
public readonly eventRule: Rule;
/**
* The security group to use for the ECS Task.
*/
private readonly _securityGroups?: ISecurityGroup[];
/**
* Constructs a new instance of the ScheduledTaskBase class.
*/
constructor(scope: Construct, id: string, props: ScheduledTaskBaseProps) {
super(scope, id);
this.cluster = props.cluster || this.getDefaultCluster(this, props.vpc);
if (props.desiredTaskCount !== undefined && props.desiredTaskCount < 1) {
throw new Error('You must specify a desiredTaskCount greater than 0');
}
this.desiredTaskCount = props.desiredTaskCount || 1;
this.subnetSelection = props.subnetSelection || { subnetType: SubnetType.PRIVATE_WITH_NAT };
this._securityGroups = props.securityGroups;
// An EventRule that describes the event trigger (in this case a scheduled run)
this.eventRule = new Rule(this, 'ScheduledEventRule', {
schedule: props.schedule,
ruleName: props.ruleName,
enabled: props.enabled,
});
// add a warning on synth when minute is not defined in a cron schedule
props.schedule._bind(scope);
}
/**
* Create an ECS task using the task definition provided and add it to the scheduled event rule.
*
* @param taskDefinition the TaskDefinition to add to the event rule
*/
protected addTaskDefinitionToEventTarget(taskDefinition: TaskDefinition): EcsTask {
// Use the EcsTask as the target of the EventRule
const eventRuleTarget = new EcsTask( {
cluster: this.cluster,
taskDefinition,
taskCount: this.desiredTaskCount,
subnetSelection: this.subnetSelection,
securityGroups: this._securityGroups,
});
this.addTaskAsTarget(eventRuleTarget);
return eventRuleTarget;
}
/**
* Adds task as a target of the scheduled event rule.
*
* @param ecsTaskTarget the EcsTask to add to the event rule
*/
protected addTaskAsTarget(ecsTaskTarget: EcsTask) {
this.eventRule.addTarget(ecsTaskTarget);
}
/**
* Returns the default cluster.
*/
protected getDefaultCluster(scope: CoreConstruct, vpc?: IVpc): Cluster {
// magic string to avoid collision with user-defined constructs
const DEFAULT_CLUSTER_ID = `EcsDefaultClusterMnL3mNNYN${vpc ? vpc.node.id : ''}`;
const stack = Stack.of(scope);
return stack.node.tryFindChild(DEFAULT_CLUSTER_ID) as Cluster || new Cluster(stack, DEFAULT_CLUSTER_ID, { vpc });
}
/**
* Create an AWS Log Driver with the provided streamPrefix
*
* @param prefix the Cloudwatch logging prefix
*/
protected createAWSLogDriver(prefix: string): AwsLogDriver {
return new AwsLogDriver({ streamPrefix: prefix });
}
}