dcl-ops-lib 9.0.0 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/createFargateTask.d.ts +3 -2
- package/createFargateTask.js +19 -27
- package/createSQSTriggeredFargateTask.d.ts +63 -0
- package/createSQSTriggeredFargateTask.js +110 -0
- package/createScheduledFargateTask.d.ts +75 -0
- package/createScheduledFargateTask.js +108 -0
- package/fargateHelpers.d.ts +220 -0
- package/fargateHelpers.js +178 -0
- package/index.d.ts +32 -0
- package/index.js +52 -0
- package/package.json +1 -1
- package/scheduledTaskBase.d.ts +142 -0
- package/scheduledTaskBase.js +146 -0
- package/slack.d.ts +4 -0
- package/slack.js +21 -0
package/createFargateTask.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as aws from "@pulumi/aws";
|
|
|
2
2
|
import * as pulumi from "@pulumi/pulumi";
|
|
3
3
|
import { ExtraExposedServiceOptions } from "./exposePublicService";
|
|
4
4
|
import { HealthCheck } from "@pulumi/aws/ecs";
|
|
5
|
+
import { Team } from "./fargateHelpers";
|
|
5
6
|
export declare const getDefaultLogs: (serviceName: string, logGroup: aws.cloudwatch.LogGroup) => aws.ecs.LogConfiguration;
|
|
6
7
|
export declare function getClusterInstance(cluster: string | aws.ecs.Cluster | undefined): Promise<pulumi.Output<string> | string>;
|
|
7
8
|
export type ALBMapping = {
|
|
@@ -42,7 +43,7 @@ export type FargateTaskOptions = {
|
|
|
42
43
|
taskRolePolicies?: Record<string, pulumi.Input<string> | aws.iam.Policy>;
|
|
43
44
|
secrets?: aws.ecs.Secret[];
|
|
44
45
|
ignoreServiceDiscovery?: boolean;
|
|
45
|
-
team:
|
|
46
|
+
team: Team;
|
|
46
47
|
metrics?: {
|
|
47
48
|
port?: number | string;
|
|
48
49
|
path: "/metrics";
|
|
@@ -127,7 +128,7 @@ export type InternalServiceOptions = {
|
|
|
127
128
|
forceNewDeployment?: boolean;
|
|
128
129
|
dependsOn?: pulumi.Resource[];
|
|
129
130
|
volumes?: pulumi.Input<aws.types.input.ecs.TaskDefinitionVolume[]>;
|
|
130
|
-
team:
|
|
131
|
+
team: Team;
|
|
131
132
|
targetGroups: aws.alb.TargetGroup[];
|
|
132
133
|
runtimePlatform?: aws.types.input.ecs.TaskDefinitionRuntimePlatform;
|
|
133
134
|
appAutoscaling?: {
|
package/createFargateTask.js
CHANGED
|
@@ -13,11 +13,12 @@ const supra_1 = require("./supra");
|
|
|
13
13
|
const stack_1 = require("./stack");
|
|
14
14
|
const prometheus_1 = require("./prometheus");
|
|
15
15
|
const accessTheInternet_1 = require("./accessTheInternet");
|
|
16
|
+
const fargateHelpers_1 = require("./fargateHelpers");
|
|
16
17
|
const getDefaultLogs = (serviceName, logGroup) => {
|
|
17
18
|
return {
|
|
18
19
|
logDriver: "awslogs",
|
|
19
20
|
options: {
|
|
20
|
-
"awslogs-group":
|
|
21
|
+
"awslogs-group": logGroup.name,
|
|
21
22
|
"awslogs-region": "us-east-1",
|
|
22
23
|
"awslogs-stream-prefix": serviceName,
|
|
23
24
|
},
|
|
@@ -106,13 +107,13 @@ async function createFargateTask(serviceName, dockerImage, dockerListeningPort,
|
|
|
106
107
|
essential = true;
|
|
107
108
|
}
|
|
108
109
|
if (undefined === memoryReservation) {
|
|
109
|
-
memoryReservation =
|
|
110
|
+
memoryReservation = fargateHelpers_1.DEFAULT_MEMORY;
|
|
110
111
|
}
|
|
111
112
|
if (undefined === cpuReservation) {
|
|
112
|
-
cpuReservation =
|
|
113
|
+
cpuReservation = fargateHelpers_1.DEFAULT_CPU;
|
|
113
114
|
}
|
|
114
115
|
if (undefined === desiredCount) {
|
|
115
|
-
desiredCount =
|
|
116
|
+
desiredCount = fargateHelpers_1.DEFAULT_DESIRED_COUNT;
|
|
116
117
|
}
|
|
117
118
|
if (undefined === securityGroups) {
|
|
118
119
|
securityGroups = [];
|
|
@@ -156,7 +157,7 @@ async function createFargateTask(serviceName, dockerImage, dockerListeningPort,
|
|
|
156
157
|
const vpc = await (0, vpc_1.getVpc)();
|
|
157
158
|
const taskSecurityGroup = new aws.ec2.SecurityGroup(`${serviceName}-${version}`, {
|
|
158
159
|
vpcId: vpc.id,
|
|
159
|
-
tags:
|
|
160
|
+
tags: (0, fargateHelpers_1.createResourceTags)(serviceName, team),
|
|
160
161
|
});
|
|
161
162
|
if (dockerLabels.ECS_PROMETHEUS_EXPORTER_PORT) {
|
|
162
163
|
let fromPort = 0;
|
|
@@ -312,37 +313,28 @@ async function createInternalService(config) {
|
|
|
312
313
|
registryArn: serviceDiscovery.arn,
|
|
313
314
|
};
|
|
314
315
|
}
|
|
315
|
-
const logGroup =
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
tags: { ServiceName: serviceName, Team: team },
|
|
319
|
-
});
|
|
320
|
-
const taskDefinition = new aws.ecs.TaskDefinition((0, stack_1.getStackScopedName)(serviceName) + "-taskdefinition", {
|
|
316
|
+
const logGroup = (0, fargateHelpers_1.createLogGroup)(serviceName, team);
|
|
317
|
+
const taskDefinition = (0, fargateHelpers_1.createFargateTaskDefinition)({
|
|
318
|
+
name: serviceName,
|
|
321
319
|
executionRoleArn: executionRole?.arn,
|
|
322
320
|
taskRoleArn: taskRole?.arn,
|
|
323
|
-
tags: { ServiceName: serviceName, Team: team },
|
|
324
321
|
containerDefinitions: pulumi.jsonStringify([
|
|
325
322
|
{
|
|
326
323
|
...containerInfo,
|
|
327
324
|
logConfiguration: (0, exports.getDefaultLogs)(serviceName, logGroup),
|
|
328
325
|
},
|
|
329
326
|
]),
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
requiresCompatibilities: ["FARGATE"],
|
|
339
|
-
networkMode: "awsvpc",
|
|
340
|
-
volumes: volumes,
|
|
341
|
-
family: (0, stack_1.getStackScopedName)(serviceName),
|
|
342
|
-
}, { dependsOn: [logGroup] });
|
|
327
|
+
team,
|
|
328
|
+
cpu: containerInfo.cpu ?? fargateHelpers_1.DEFAULT_CPU,
|
|
329
|
+
memory: containerInfo.memoryReservation ?? fargateHelpers_1.DEFAULT_MEMORY,
|
|
330
|
+
ephemeralStorageInGB,
|
|
331
|
+
runtimePlatform,
|
|
332
|
+
volumes,
|
|
333
|
+
dependsOn: [logGroup],
|
|
334
|
+
});
|
|
343
335
|
const service = new aws.ecs.Service((0, stack_1.getStackScopedName)(serviceName), {
|
|
344
336
|
cluster: await getClusterInstance(cluster),
|
|
345
|
-
tags:
|
|
337
|
+
tags: (0, fargateHelpers_1.createResourceTags)(serviceName, team, { StackId: (0, stack_1.getStackId)() }),
|
|
346
338
|
networkConfiguration: {
|
|
347
339
|
subnets: await (0, network_1.getPrivateSubnetIds)(),
|
|
348
340
|
securityGroups: securityGroups,
|
|
@@ -363,7 +355,7 @@ async function createInternalService(config) {
|
|
|
363
355
|
],
|
|
364
356
|
}, {
|
|
365
357
|
...extraOpts,
|
|
366
|
-
dependsOn
|
|
358
|
+
dependsOn,
|
|
367
359
|
});
|
|
368
360
|
if (appAutoscaling) {
|
|
369
361
|
setAutoscaling(service, serviceName, { appAutoscaling, desiredCount });
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
2
|
+
import { BaseFargateTaskOptions } from "./scheduledTaskBase";
|
|
3
|
+
/**
|
|
4
|
+
* SQS trigger configuration for the task
|
|
5
|
+
*/
|
|
6
|
+
export type SqsTriggerConfig = {
|
|
7
|
+
/**
|
|
8
|
+
* ARN of the SQS queue to trigger from
|
|
9
|
+
*/
|
|
10
|
+
queueArn: pulumi.Input<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Number of messages per batch (default: 1)
|
|
13
|
+
* Each batch triggers one task invocation
|
|
14
|
+
*/
|
|
15
|
+
batchSize?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Maximum batching window in seconds (default: 0)
|
|
18
|
+
* How long to wait to accumulate messages before triggering
|
|
19
|
+
*/
|
|
20
|
+
maximumBatchingWindowSeconds?: number;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Options for creating an SQS-triggered Fargate task
|
|
24
|
+
*/
|
|
25
|
+
export type SQSTriggeredFargateTaskOptions = BaseFargateTaskOptions & {
|
|
26
|
+
/**
|
|
27
|
+
* SQS queue trigger configuration - required
|
|
28
|
+
*/
|
|
29
|
+
sqsTrigger: SqsTriggerConfig;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Creates a Fargate task that is triggered by messages in an SQS queue.
|
|
33
|
+
* Uses EventBridge Pipes to connect the SQS queue to ECS task execution.
|
|
34
|
+
*
|
|
35
|
+
* @param taskName A name for this task. For example, "order-processor"
|
|
36
|
+
* @param dockerImage The docker image to run
|
|
37
|
+
* @param options Configuration options for the SQS-triggered task
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* await createSQSTriggeredFargateTask("order-processor", "myapp/processor:latest", {
|
|
42
|
+
* sqsTrigger: {
|
|
43
|
+
* queueArn: ordersQueue.arn,
|
|
44
|
+
* batchSize: 10,
|
|
45
|
+
* maximumBatchingWindowSeconds: 30,
|
|
46
|
+
* },
|
|
47
|
+
* cpu: 512,
|
|
48
|
+
* memory: 1024,
|
|
49
|
+
* environment: [{ name: "DB_HOST", value: dbHost }],
|
|
50
|
+
* slackChannel: "#order-processing-alerts",
|
|
51
|
+
* team: "platform",
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function createSQSTriggeredFargateTask(taskName: string, dockerImage: string | Promise<string> | pulumi.OutputInstance<string>, options: SQSTriggeredFargateTaskOptions): Promise<{
|
|
56
|
+
taskDefinition: import("@pulumi/aws/ecs/taskDefinition").TaskDefinition;
|
|
57
|
+
taskSecurityGroup: import("@pulumi/aws/ec2/securityGroup").SecurityGroup;
|
|
58
|
+
logGroup: import("@pulumi/aws/cloudwatch/logGroup").LogGroup;
|
|
59
|
+
executionRole: import("@pulumi/aws/iam/role").Role;
|
|
60
|
+
taskRole: import("@pulumi/aws/iam/role").Role;
|
|
61
|
+
eventBridgeRole: import("@pulumi/aws/iam/role").Role;
|
|
62
|
+
pipe: import("@pulumi/aws/pipes/pipe").Pipe;
|
|
63
|
+
}>;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createSQSTriggeredFargateTask = void 0;
|
|
4
|
+
const aws = require("@pulumi/aws");
|
|
5
|
+
const pulumi = require("@pulumi/pulumi");
|
|
6
|
+
const stack_1 = require("./stack");
|
|
7
|
+
const scheduledTaskBase_1 = require("./scheduledTaskBase");
|
|
8
|
+
/**
|
|
9
|
+
* Creates a Fargate task that is triggered by messages in an SQS queue.
|
|
10
|
+
* Uses EventBridge Pipes to connect the SQS queue to ECS task execution.
|
|
11
|
+
*
|
|
12
|
+
* @param taskName A name for this task. For example, "order-processor"
|
|
13
|
+
* @param dockerImage The docker image to run
|
|
14
|
+
* @param options Configuration options for the SQS-triggered task
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* await createSQSTriggeredFargateTask("order-processor", "myapp/processor:latest", {
|
|
19
|
+
* sqsTrigger: {
|
|
20
|
+
* queueArn: ordersQueue.arn,
|
|
21
|
+
* batchSize: 10,
|
|
22
|
+
* maximumBatchingWindowSeconds: 30,
|
|
23
|
+
* },
|
|
24
|
+
* cpu: 512,
|
|
25
|
+
* memory: 1024,
|
|
26
|
+
* environment: [{ name: "DB_HOST", value: dbHost }],
|
|
27
|
+
* slackChannel: "#order-processing-alerts",
|
|
28
|
+
* team: "platform",
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
async function createSQSTriggeredFargateTask(taskName, dockerImage, options) {
|
|
33
|
+
const { sqsTrigger, ...baseOptions } = options;
|
|
34
|
+
// Create base infrastructure (task definition, security group, IAM roles, etc.)
|
|
35
|
+
const base = await (0, scheduledTaskBase_1.createBaseTaskInfrastructure)(taskName, dockerImage, baseOptions, ["pipes.amazonaws.com"] // EventBridge Pipes service
|
|
36
|
+
);
|
|
37
|
+
// Add SQS permissions to the EventBridge role
|
|
38
|
+
const sqsPolicy = new aws.iam.RolePolicy(`${base.resourcePrefix}-sqs-policy`, {
|
|
39
|
+
role: base.eventBridgeRole.id,
|
|
40
|
+
policy: pulumi.output(sqsTrigger.queueArn).apply((queueArn) => JSON.stringify({
|
|
41
|
+
Version: "2012-10-17",
|
|
42
|
+
Statement: [
|
|
43
|
+
{
|
|
44
|
+
Effect: "Allow",
|
|
45
|
+
Action: [
|
|
46
|
+
// Permissions needed to read from SQS
|
|
47
|
+
"sqs:ReceiveMessage",
|
|
48
|
+
"sqs:DeleteMessage",
|
|
49
|
+
"sqs:GetQueueAttributes",
|
|
50
|
+
],
|
|
51
|
+
Resource: queueArn,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
})),
|
|
55
|
+
});
|
|
56
|
+
// Create EventBridge Pipe to connect SQS queue to ECS task
|
|
57
|
+
const pipe = new aws.pipes.Pipe(`${base.resourcePrefix}-sqs-pipe`, {
|
|
58
|
+
// Unique name for this pipe
|
|
59
|
+
name: (0, stack_1.getStackScopedName)(taskName),
|
|
60
|
+
// IAM role that the pipe assumes to read from source and invoke target
|
|
61
|
+
roleArn: base.eventBridgeRole.arn,
|
|
62
|
+
// Source: the SQS queue to read messages from
|
|
63
|
+
source: sqsTrigger.queueArn,
|
|
64
|
+
// Source configuration for SQS
|
|
65
|
+
sourceParameters: {
|
|
66
|
+
sqsQueueParameters: {
|
|
67
|
+
// Number of messages to retrieve per batch (1-10000)
|
|
68
|
+
batchSize: sqsTrigger.batchSize || 1,
|
|
69
|
+
// Maximum time to wait for a full batch before triggering (0-300 seconds)
|
|
70
|
+
maximumBatchingWindowInSeconds: sqsTrigger.maximumBatchingWindowSeconds || 0,
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
// Target: the ECS cluster to run tasks on
|
|
74
|
+
target: base.clusterArn,
|
|
75
|
+
// Target configuration for ECS tasks
|
|
76
|
+
targetParameters: {
|
|
77
|
+
ecsTaskParameters: {
|
|
78
|
+
// The task definition to run
|
|
79
|
+
taskDefinitionArn: base.taskDefinition.arn,
|
|
80
|
+
// Number of task instances to launch per invocation
|
|
81
|
+
taskCount: base.taskCount,
|
|
82
|
+
// Launch type: FARGATE for serverless containers
|
|
83
|
+
launchType: "FARGATE",
|
|
84
|
+
// Network configuration for awsvpc network mode
|
|
85
|
+
networkConfiguration: {
|
|
86
|
+
awsVpcConfiguration: {
|
|
87
|
+
// Private subnets where the task will run
|
|
88
|
+
subnets: base.subnetIds,
|
|
89
|
+
// Security groups controlling inbound/outbound traffic
|
|
90
|
+
securityGroups: base.securityGroups,
|
|
91
|
+
// Whether to assign a public IP (ENABLED/DISABLED)
|
|
92
|
+
assignPublicIp: base.assignPublicIp ? "ENABLED" : "DISABLED",
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
tags: { ServiceName: taskName, Team: base.team },
|
|
98
|
+
}, { dependsOn: [base.eventBridgePolicy, sqsPolicy, base.taskDefinition] });
|
|
99
|
+
return {
|
|
100
|
+
taskDefinition: base.taskDefinition,
|
|
101
|
+
taskSecurityGroup: base.taskSecurityGroup,
|
|
102
|
+
logGroup: base.logGroup,
|
|
103
|
+
executionRole: base.executionRole,
|
|
104
|
+
taskRole: base.taskRole,
|
|
105
|
+
eventBridgeRole: base.eventBridgeRole,
|
|
106
|
+
pipe,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
exports.createSQSTriggeredFargateTask = createSQSTriggeredFargateTask;
|
|
110
|
+
//# sourceMappingURL=createSQSTriggeredFargateTask.js.map
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
2
|
+
import { BaseFargateTaskOptions, RetryPolicyConfig } from "./scheduledTaskBase";
|
|
3
|
+
/**
|
|
4
|
+
* Schedule configuration for the task
|
|
5
|
+
*/
|
|
6
|
+
export type ScheduleConfig = {
|
|
7
|
+
/**
|
|
8
|
+
* Schedule expression in cron or rate format
|
|
9
|
+
* Cron: "cron(0 12 * * ? *)" - runs daily at noon UTC
|
|
10
|
+
* Rate: "rate(1 hour)" - runs every hour
|
|
11
|
+
*/
|
|
12
|
+
expression: string;
|
|
13
|
+
/**
|
|
14
|
+
* Timezone for the schedule (default: "UTC")
|
|
15
|
+
* Example: "America/New_York", "Europe/London"
|
|
16
|
+
*/
|
|
17
|
+
timezone?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Whether the schedule is enabled (default: true)
|
|
20
|
+
*/
|
|
21
|
+
enabled?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Optional start date for the schedule (ISO 8601 format)
|
|
24
|
+
*/
|
|
25
|
+
startDate?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Optional end date for the schedule (ISO 8601 format)
|
|
28
|
+
*/
|
|
29
|
+
endDate?: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Options for creating a scheduled Fargate task
|
|
33
|
+
*/
|
|
34
|
+
export type ScheduledFargateTaskOptions = BaseFargateTaskOptions & {
|
|
35
|
+
/**
|
|
36
|
+
* Schedule configuration (cron/rate expression) - required
|
|
37
|
+
*/
|
|
38
|
+
schedule: ScheduleConfig;
|
|
39
|
+
/**
|
|
40
|
+
* Retry policy for failed task invocations
|
|
41
|
+
*/
|
|
42
|
+
retryPolicy?: RetryPolicyConfig;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Creates a scheduled Fargate task that runs on a cron/rate schedule.
|
|
46
|
+
*
|
|
47
|
+
* @param taskName A name for this task. For example, "daily-cleanup"
|
|
48
|
+
* @param dockerImage The docker image to run
|
|
49
|
+
* @param options Configuration options for the scheduled task
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```typescript
|
|
53
|
+
* await createScheduledFargateTask("daily-cleanup", "myapp/cleanup:latest", {
|
|
54
|
+
* schedule: {
|
|
55
|
+
* expression: "cron(0 2 * * ? *)", // Daily at 2 AM
|
|
56
|
+
* timezone: "America/New_York",
|
|
57
|
+
* },
|
|
58
|
+
* cpu: 512,
|
|
59
|
+
* memory: 1024,
|
|
60
|
+
* environment: [{ name: "DB_HOST", value: dbHost }],
|
|
61
|
+
* slackChannel: "#scheduled-tasks-alerts",
|
|
62
|
+
* team: "platform",
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare function createScheduledFargateTask(taskName: string, dockerImage: string | Promise<string> | pulumi.OutputInstance<string>, options: ScheduledFargateTaskOptions): Promise<{
|
|
67
|
+
taskDefinition: import("@pulumi/aws/ecs/taskDefinition").TaskDefinition;
|
|
68
|
+
taskSecurityGroup: import("@pulumi/aws/ec2/securityGroup").SecurityGroup;
|
|
69
|
+
logGroup: import("@pulumi/aws/cloudwatch/logGroup").LogGroup;
|
|
70
|
+
executionRole: import("@pulumi/aws/iam/role").Role;
|
|
71
|
+
taskRole: import("@pulumi/aws/iam/role").Role;
|
|
72
|
+
eventBridgeRole: import("@pulumi/aws/iam/role").Role;
|
|
73
|
+
scheduler: import("@pulumi/aws/scheduler/schedule").Schedule;
|
|
74
|
+
scheduleGroup: import("@pulumi/aws/scheduler/scheduleGroup").ScheduleGroup;
|
|
75
|
+
}>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createScheduledFargateTask = void 0;
|
|
4
|
+
const aws = require("@pulumi/aws");
|
|
5
|
+
const stack_1 = require("./stack");
|
|
6
|
+
const scheduledTaskBase_1 = require("./scheduledTaskBase");
|
|
7
|
+
/**
|
|
8
|
+
* Creates a scheduled Fargate task that runs on a cron/rate schedule.
|
|
9
|
+
*
|
|
10
|
+
* @param taskName A name for this task. For example, "daily-cleanup"
|
|
11
|
+
* @param dockerImage The docker image to run
|
|
12
|
+
* @param options Configuration options for the scheduled task
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* await createScheduledFargateTask("daily-cleanup", "myapp/cleanup:latest", {
|
|
17
|
+
* schedule: {
|
|
18
|
+
* expression: "cron(0 2 * * ? *)", // Daily at 2 AM
|
|
19
|
+
* timezone: "America/New_York",
|
|
20
|
+
* },
|
|
21
|
+
* cpu: 512,
|
|
22
|
+
* memory: 1024,
|
|
23
|
+
* environment: [{ name: "DB_HOST", value: dbHost }],
|
|
24
|
+
* slackChannel: "#scheduled-tasks-alerts",
|
|
25
|
+
* team: "platform",
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
async function createScheduledFargateTask(taskName, dockerImage, options) {
|
|
30
|
+
const { schedule, retryPolicy, ...baseOptions } = options;
|
|
31
|
+
// Create base infrastructure (task definition, security group, IAM roles, etc.)
|
|
32
|
+
const base = await (0, scheduledTaskBase_1.createBaseTaskInfrastructure)(taskName, dockerImage, baseOptions, ["scheduler.amazonaws.com"] // EventBridge Scheduler service
|
|
33
|
+
);
|
|
34
|
+
// Schedule groups allow organizing related schedules together
|
|
35
|
+
// and applying resource-based policies at the group level
|
|
36
|
+
const scheduleGroup = new aws.scheduler.ScheduleGroup(`${base.resourcePrefix}-schedule-group`, {
|
|
37
|
+
name: (0, stack_1.getStackScopedName)(taskName),
|
|
38
|
+
tags: { ServiceName: taskName, Team: base.team },
|
|
39
|
+
});
|
|
40
|
+
const scheduler = new aws.scheduler.Schedule(`${base.resourcePrefix}-schedule`, {
|
|
41
|
+
// Unique name for this schedule within the AWS account and region
|
|
42
|
+
name: (0, stack_1.getStackScopedName)(taskName),
|
|
43
|
+
// Associate with the schedule group for organization
|
|
44
|
+
groupName: scheduleGroup.name,
|
|
45
|
+
// Schedule expression: supports cron() and rate() formats
|
|
46
|
+
// Examples: "cron(0 12 * * ? *)" for daily at noon, "rate(1 hour)" for hourly
|
|
47
|
+
scheduleExpression: schedule.expression,
|
|
48
|
+
// Timezone for interpreting cron expressions (default: UTC)
|
|
49
|
+
// Examples: "America/New_York", "Europe/London", "UTC"
|
|
50
|
+
scheduleExpressionTimezone: schedule.timezone || "UTC",
|
|
51
|
+
// Whether the schedule is active (ENABLED) or paused (DISABLED)
|
|
52
|
+
state: schedule.enabled !== false ? "ENABLED" : "DISABLED",
|
|
53
|
+
// Optional: Schedule won't trigger before this date (ISO 8601 format)
|
|
54
|
+
startDate: schedule.startDate,
|
|
55
|
+
// Optional: Schedule won't trigger after this date (ISO 8601 format)
|
|
56
|
+
endDate: schedule.endDate,
|
|
57
|
+
// Flexible time window allows EventBridge to invoke the target within a window
|
|
58
|
+
// OFF = invoke at exact scheduled time, FLEXIBLE = invoke within specified window
|
|
59
|
+
flexibleTimeWindow: {
|
|
60
|
+
mode: "OFF",
|
|
61
|
+
},
|
|
62
|
+
target: {
|
|
63
|
+
// Target is the ECS cluster that will run the task
|
|
64
|
+
arn: base.clusterArn,
|
|
65
|
+
// IAM role that EventBridge assumes to invoke the target
|
|
66
|
+
roleArn: base.eventBridgeRole.arn,
|
|
67
|
+
// ECS-specific parameters for running Fargate tasks
|
|
68
|
+
ecsParameters: {
|
|
69
|
+
// The task definition to run
|
|
70
|
+
taskDefinitionArn: base.taskDefinition.arn,
|
|
71
|
+
// Number of task instances to launch (default: 1)
|
|
72
|
+
taskCount: base.taskCount,
|
|
73
|
+
// Launch type: FARGATE for serverless, EC2 for container instances
|
|
74
|
+
launchType: "FARGATE",
|
|
75
|
+
// Network configuration for tasks using awsvpc network mode
|
|
76
|
+
networkConfiguration: {
|
|
77
|
+
// Private subnets where the task will run
|
|
78
|
+
subnets: base.subnetIds,
|
|
79
|
+
// Security groups controlling inbound/outbound traffic
|
|
80
|
+
securityGroups: base.securityGroups,
|
|
81
|
+
// Whether to assign a public IP (needed for ECR pulls without NAT)
|
|
82
|
+
assignPublicIp: base.assignPublicIp,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
// Retry policy if the scheduler fails to invoke the target
|
|
86
|
+
retryPolicy: retryPolicy
|
|
87
|
+
? {
|
|
88
|
+
// Maximum number of retry attempts (0-185)
|
|
89
|
+
maximumRetryAttempts: retryPolicy.maxRetries,
|
|
90
|
+
// Maximum time to keep retrying before giving up (in seconds)
|
|
91
|
+
maximumEventAgeInSeconds: retryPolicy.maxAgeSeconds,
|
|
92
|
+
}
|
|
93
|
+
: undefined,
|
|
94
|
+
},
|
|
95
|
+
}, { dependsOn: [base.eventBridgePolicy, base.taskDefinition] });
|
|
96
|
+
return {
|
|
97
|
+
taskDefinition: base.taskDefinition,
|
|
98
|
+
taskSecurityGroup: base.taskSecurityGroup,
|
|
99
|
+
logGroup: base.logGroup,
|
|
100
|
+
executionRole: base.executionRole,
|
|
101
|
+
taskRole: base.taskRole,
|
|
102
|
+
eventBridgeRole: base.eventBridgeRole,
|
|
103
|
+
scheduler,
|
|
104
|
+
scheduleGroup,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
exports.createScheduledFargateTask = createScheduledFargateTask;
|
|
108
|
+
//# sourceMappingURL=createScheduledFargateTask.js.map
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import * as aws from "@pulumi/aws";
|
|
2
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
3
|
+
/**
|
|
4
|
+
* Team type used by all Fargate-related functions for ownership tagging
|
|
5
|
+
*/
|
|
6
|
+
export type Team = "dapps" | "platform" | "data" | "marketing" | "infra";
|
|
7
|
+
/**
|
|
8
|
+
* Prometheus metrics configuration
|
|
9
|
+
*/
|
|
10
|
+
export type MetricsConfig = {
|
|
11
|
+
/**
|
|
12
|
+
* Port where metrics are exposed
|
|
13
|
+
*/
|
|
14
|
+
port: number | string;
|
|
15
|
+
/**
|
|
16
|
+
* Path to the metrics endpoint (default: "/metrics")
|
|
17
|
+
*/
|
|
18
|
+
path?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Job name for Prometheus (default: task/service name)
|
|
21
|
+
*/
|
|
22
|
+
jobName?: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Default CPU units for Fargate tasks (256 = 0.25 vCPU)
|
|
26
|
+
*/
|
|
27
|
+
export declare const DEFAULT_CPU = 256;
|
|
28
|
+
/**
|
|
29
|
+
* Default memory in MB for Fargate tasks
|
|
30
|
+
*/
|
|
31
|
+
export declare const DEFAULT_MEMORY = 512;
|
|
32
|
+
/**
|
|
33
|
+
* Default CloudWatch log retention in days
|
|
34
|
+
*/
|
|
35
|
+
export declare const DEFAULT_LOG_RETENTION_DAYS = 60;
|
|
36
|
+
/**
|
|
37
|
+
* Default desired count for ECS services
|
|
38
|
+
*/
|
|
39
|
+
export declare const DEFAULT_DESIRED_COUNT = 1;
|
|
40
|
+
/**
|
|
41
|
+
* Creates standard resource tags for Fargate resources
|
|
42
|
+
*
|
|
43
|
+
* @param serviceName The name of the service/task
|
|
44
|
+
* @param team Team that owns this resource
|
|
45
|
+
* @param additionalTags Optional additional tags to merge
|
|
46
|
+
* @returns Record of tags
|
|
47
|
+
*/
|
|
48
|
+
export declare function createResourceTags(serviceName: string, team: Team, additionalTags?: Record<string, string>): Record<string, string>;
|
|
49
|
+
/**
|
|
50
|
+
* Creates a CloudWatch Log Group with consistent settings
|
|
51
|
+
*
|
|
52
|
+
* @param name The name for the log group (will be stack-scoped)
|
|
53
|
+
* @param team Team that owns this resource
|
|
54
|
+
* @param retentionInDays Log retention in days (default: 60)
|
|
55
|
+
* @returns The created CloudWatch Log Group
|
|
56
|
+
*/
|
|
57
|
+
export declare function createLogGroup(name: string, team: Team, retentionInDays?: number): aws.cloudwatch.LogGroup;
|
|
58
|
+
/**
|
|
59
|
+
* Creates a security group for a Fargate task/service with standard tags
|
|
60
|
+
*
|
|
61
|
+
* @param name Resource name for the security group
|
|
62
|
+
* @param vpcId The VPC ID where the security group will be created
|
|
63
|
+
* @param serviceName The name of the service (for tagging)
|
|
64
|
+
* @param team Team that owns this resource
|
|
65
|
+
* @returns The created EC2 Security Group
|
|
66
|
+
*/
|
|
67
|
+
export declare function createTaskSecurityGroup(name: string, vpcId: pulumi.Input<string>, serviceName: string, team: Team): aws.ec2.SecurityGroup;
|
|
68
|
+
/**
|
|
69
|
+
* Configures docker labels for Prometheus metrics discovery
|
|
70
|
+
*
|
|
71
|
+
* @param taskName The name of the task/service
|
|
72
|
+
* @param metrics Metrics configuration
|
|
73
|
+
* @returns Docker labels, port mappings, and the parsed metrics port
|
|
74
|
+
*/
|
|
75
|
+
export declare function configurePrometheusMetrics(taskName: string, metrics: MetricsConfig): {
|
|
76
|
+
dockerLabels: Record<string, string>;
|
|
77
|
+
portMappings: aws.ecs.PortMapping[];
|
|
78
|
+
metricsPort: number;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Creates security group rules to allow Prometheus metrics scraping
|
|
82
|
+
*
|
|
83
|
+
* @param resourcePrefix Prefix for resource names
|
|
84
|
+
* @param securityGroup The security group to add rules to
|
|
85
|
+
* @param vpcCidrBlock The VPC CIDR block for ingress rules
|
|
86
|
+
* @param metricsPort The port where metrics are exposed
|
|
87
|
+
* @param taskName The name of the task/service
|
|
88
|
+
*/
|
|
89
|
+
export declare function setupPrometheusSecurityRules(resourcePrefix: string, securityGroup: aws.ec2.SecurityGroup, vpcCidrBlock: string, metricsPort: number, taskName: string): void;
|
|
90
|
+
/**
|
|
91
|
+
* Options for building a container definition
|
|
92
|
+
*/
|
|
93
|
+
export type ContainerDefinitionOptions = {
|
|
94
|
+
/**
|
|
95
|
+
* Container name
|
|
96
|
+
*/
|
|
97
|
+
name: string;
|
|
98
|
+
/**
|
|
99
|
+
* Docker image to run
|
|
100
|
+
*/
|
|
101
|
+
image: string | Promise<string> | pulumi.OutputInstance<string>;
|
|
102
|
+
/**
|
|
103
|
+
* CPU units for this container
|
|
104
|
+
*/
|
|
105
|
+
cpu: number;
|
|
106
|
+
/**
|
|
107
|
+
* Memory reservation in MB
|
|
108
|
+
*/
|
|
109
|
+
memory: number;
|
|
110
|
+
/**
|
|
111
|
+
* Environment variables
|
|
112
|
+
*/
|
|
113
|
+
environment?: {
|
|
114
|
+
name: string;
|
|
115
|
+
value: pulumi.Input<string>;
|
|
116
|
+
}[];
|
|
117
|
+
/**
|
|
118
|
+
* Secrets from SSM/Secrets Manager
|
|
119
|
+
*/
|
|
120
|
+
secrets?: aws.ecs.Secret[];
|
|
121
|
+
/**
|
|
122
|
+
* Override command
|
|
123
|
+
*/
|
|
124
|
+
command?: string[];
|
|
125
|
+
/**
|
|
126
|
+
* Override entry point
|
|
127
|
+
*/
|
|
128
|
+
entryPoint?: string[];
|
|
129
|
+
/**
|
|
130
|
+
* Port mappings
|
|
131
|
+
*/
|
|
132
|
+
portMappings?: aws.ecs.PortMapping[];
|
|
133
|
+
/**
|
|
134
|
+
* Docker labels (e.g., for Prometheus)
|
|
135
|
+
*/
|
|
136
|
+
dockerLabels?: Record<string, string>;
|
|
137
|
+
/**
|
|
138
|
+
* Mount points for volumes
|
|
139
|
+
*/
|
|
140
|
+
mountPoints?: aws.ecs.MountPoint[];
|
|
141
|
+
/**
|
|
142
|
+
* Repository credentials for private registries
|
|
143
|
+
*/
|
|
144
|
+
repositoryCredentials?: aws.ecs.RepositoryCredentials;
|
|
145
|
+
/**
|
|
146
|
+
* Log configuration
|
|
147
|
+
*/
|
|
148
|
+
logConfiguration: aws.ecs.LogConfiguration;
|
|
149
|
+
/**
|
|
150
|
+
* Whether this container is essential (default: true)
|
|
151
|
+
*/
|
|
152
|
+
essential?: boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Container health check
|
|
155
|
+
*/
|
|
156
|
+
healthCheck?: aws.ecs.HealthCheck;
|
|
157
|
+
};
|
|
158
|
+
/**
|
|
159
|
+
* Builds a container definition object for ECS task definitions
|
|
160
|
+
*
|
|
161
|
+
* @param options Container definition options
|
|
162
|
+
* @returns Container definition object
|
|
163
|
+
*/
|
|
164
|
+
export declare function buildContainerDefinition(options: ContainerDefinitionOptions): aws.ecs.ContainerDefinition;
|
|
165
|
+
/**
|
|
166
|
+
* Options for creating a Fargate task definition
|
|
167
|
+
*/
|
|
168
|
+
export type FargateTaskDefinitionOptions = {
|
|
169
|
+
/**
|
|
170
|
+
* Name for the task definition
|
|
171
|
+
*/
|
|
172
|
+
name: string;
|
|
173
|
+
/**
|
|
174
|
+
* Execution role ARN (optional for some use cases)
|
|
175
|
+
*/
|
|
176
|
+
executionRoleArn?: pulumi.Input<string>;
|
|
177
|
+
/**
|
|
178
|
+
* Task role ARN (optional for some use cases)
|
|
179
|
+
*/
|
|
180
|
+
taskRoleArn?: pulumi.Input<string>;
|
|
181
|
+
/**
|
|
182
|
+
* JSON-stringified container definitions
|
|
183
|
+
*/
|
|
184
|
+
containerDefinitions: pulumi.Input<string>;
|
|
185
|
+
/**
|
|
186
|
+
* Team that owns this resource
|
|
187
|
+
*/
|
|
188
|
+
team: Team;
|
|
189
|
+
/**
|
|
190
|
+
* CPU units for the task
|
|
191
|
+
*/
|
|
192
|
+
cpu: pulumi.Input<number>;
|
|
193
|
+
/**
|
|
194
|
+
* Memory in MB for the task
|
|
195
|
+
*/
|
|
196
|
+
memory: pulumi.Input<number>;
|
|
197
|
+
/**
|
|
198
|
+
* Ephemeral storage in GB (20-200)
|
|
199
|
+
*/
|
|
200
|
+
ephemeralStorageInGB?: number;
|
|
201
|
+
/**
|
|
202
|
+
* Runtime platform configuration (e.g., for ARM64)
|
|
203
|
+
*/
|
|
204
|
+
runtimePlatform?: aws.types.input.ecs.TaskDefinitionRuntimePlatform;
|
|
205
|
+
/**
|
|
206
|
+
* Volumes to attach
|
|
207
|
+
*/
|
|
208
|
+
volumes?: pulumi.Input<aws.types.input.ecs.TaskDefinitionVolume[]>;
|
|
209
|
+
/**
|
|
210
|
+
* Resources to depend on
|
|
211
|
+
*/
|
|
212
|
+
dependsOn?: pulumi.Resource[];
|
|
213
|
+
};
|
|
214
|
+
/**
|
|
215
|
+
* Creates a Fargate task definition with standard settings
|
|
216
|
+
*
|
|
217
|
+
* @param options Task definition options
|
|
218
|
+
* @returns The created ECS Task Definition
|
|
219
|
+
*/
|
|
220
|
+
export declare function createFargateTaskDefinition(options: FargateTaskDefinitionOptions): aws.ecs.TaskDefinition;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createFargateTaskDefinition = exports.buildContainerDefinition = exports.setupPrometheusSecurityRules = exports.configurePrometheusMetrics = exports.createTaskSecurityGroup = exports.createLogGroup = exports.createResourceTags = exports.DEFAULT_DESIRED_COUNT = exports.DEFAULT_LOG_RETENTION_DAYS = exports.DEFAULT_MEMORY = exports.DEFAULT_CPU = void 0;
|
|
4
|
+
const aws = require("@pulumi/aws");
|
|
5
|
+
const pulumi = require("@pulumi/pulumi");
|
|
6
|
+
const stack_1 = require("./stack");
|
|
7
|
+
const prometheus_1 = require("./prometheus");
|
|
8
|
+
// ============================================================================
|
|
9
|
+
// Default Constants
|
|
10
|
+
// ============================================================================
|
|
11
|
+
/**
|
|
12
|
+
* Default CPU units for Fargate tasks (256 = 0.25 vCPU)
|
|
13
|
+
*/
|
|
14
|
+
exports.DEFAULT_CPU = 256;
|
|
15
|
+
/**
|
|
16
|
+
* Default memory in MB for Fargate tasks
|
|
17
|
+
*/
|
|
18
|
+
exports.DEFAULT_MEMORY = 512;
|
|
19
|
+
/**
|
|
20
|
+
* Default CloudWatch log retention in days
|
|
21
|
+
*/
|
|
22
|
+
exports.DEFAULT_LOG_RETENTION_DAYS = 60;
|
|
23
|
+
/**
|
|
24
|
+
* Default desired count for ECS services
|
|
25
|
+
*/
|
|
26
|
+
exports.DEFAULT_DESIRED_COUNT = 1;
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// Helper Functions
|
|
29
|
+
// ============================================================================
|
|
30
|
+
/**
|
|
31
|
+
* Creates standard resource tags for Fargate resources
|
|
32
|
+
*
|
|
33
|
+
* @param serviceName The name of the service/task
|
|
34
|
+
* @param team Team that owns this resource
|
|
35
|
+
* @param additionalTags Optional additional tags to merge
|
|
36
|
+
* @returns Record of tags
|
|
37
|
+
*/
|
|
38
|
+
function createResourceTags(serviceName, team, additionalTags) {
|
|
39
|
+
return {
|
|
40
|
+
ServiceName: serviceName,
|
|
41
|
+
Team: team,
|
|
42
|
+
...additionalTags,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
exports.createResourceTags = createResourceTags;
|
|
46
|
+
/**
|
|
47
|
+
* Creates a CloudWatch Log Group with consistent settings
|
|
48
|
+
*
|
|
49
|
+
* @param name The name for the log group (will be stack-scoped)
|
|
50
|
+
* @param team Team that owns this resource
|
|
51
|
+
* @param retentionInDays Log retention in days (default: 60)
|
|
52
|
+
* @returns The created CloudWatch Log Group
|
|
53
|
+
*/
|
|
54
|
+
function createLogGroup(name, team, retentionInDays = 60) {
|
|
55
|
+
return new aws.cloudwatch.LogGroup((0, stack_1.getStackScopedName)(name), {
|
|
56
|
+
name: (0, stack_1.getStackScopedName)(name),
|
|
57
|
+
retentionInDays,
|
|
58
|
+
tags: { ServiceName: name, Team: team },
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
exports.createLogGroup = createLogGroup;
|
|
62
|
+
/**
|
|
63
|
+
* Creates a security group for a Fargate task/service with standard tags
|
|
64
|
+
*
|
|
65
|
+
* @param name Resource name for the security group
|
|
66
|
+
* @param vpcId The VPC ID where the security group will be created
|
|
67
|
+
* @param serviceName The name of the service (for tagging)
|
|
68
|
+
* @param team Team that owns this resource
|
|
69
|
+
* @returns The created EC2 Security Group
|
|
70
|
+
*/
|
|
71
|
+
function createTaskSecurityGroup(name, vpcId, serviceName, team) {
|
|
72
|
+
return new aws.ec2.SecurityGroup(name, {
|
|
73
|
+
vpcId,
|
|
74
|
+
tags: { ServiceName: serviceName, Team: team },
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
exports.createTaskSecurityGroup = createTaskSecurityGroup;
|
|
78
|
+
/**
|
|
79
|
+
* Configures docker labels for Prometheus metrics discovery
|
|
80
|
+
*
|
|
81
|
+
* @param taskName The name of the task/service
|
|
82
|
+
* @param metrics Metrics configuration
|
|
83
|
+
* @returns Docker labels, port mappings, and the parsed metrics port
|
|
84
|
+
*/
|
|
85
|
+
function configurePrometheusMetrics(taskName, metrics) {
|
|
86
|
+
const metricsPort = typeof metrics.port === "string" ? parseInt(metrics.port) : metrics.port;
|
|
87
|
+
const dockerLabels = {
|
|
88
|
+
ECS_PROMETHEUS_EXPORTER_PORT: "" + metricsPort,
|
|
89
|
+
ECS_PROMETHEUS_METRICS_PATH: metrics.path || "/metrics",
|
|
90
|
+
ECS_PROMETHEUS_JOB_NAME: metrics.jobName || taskName,
|
|
91
|
+
};
|
|
92
|
+
const portMappings = [
|
|
93
|
+
{
|
|
94
|
+
containerPort: metricsPort,
|
|
95
|
+
hostPort: metricsPort,
|
|
96
|
+
protocol: "tcp",
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
return { dockerLabels, portMappings, metricsPort };
|
|
100
|
+
}
|
|
101
|
+
exports.configurePrometheusMetrics = configurePrometheusMetrics;
|
|
102
|
+
/**
|
|
103
|
+
* Creates security group rules to allow Prometheus metrics scraping
|
|
104
|
+
*
|
|
105
|
+
* @param resourcePrefix Prefix for resource names
|
|
106
|
+
* @param securityGroup The security group to add rules to
|
|
107
|
+
* @param vpcCidrBlock The VPC CIDR block for ingress rules
|
|
108
|
+
* @param metricsPort The port where metrics are exposed
|
|
109
|
+
* @param taskName The name of the task/service
|
|
110
|
+
*/
|
|
111
|
+
function setupPrometheusSecurityRules(resourcePrefix, securityGroup, vpcCidrBlock, metricsPort, taskName) {
|
|
112
|
+
// Create security group rule for metrics access from VPC
|
|
113
|
+
new aws.ec2.SecurityGroupRule(`${resourcePrefix}-metrics-${metricsPort}`, {
|
|
114
|
+
type: "ingress",
|
|
115
|
+
fromPort: metricsPort,
|
|
116
|
+
toPort: metricsPort,
|
|
117
|
+
protocol: "tcp",
|
|
118
|
+
cidrBlocks: [vpcCidrBlock],
|
|
119
|
+
securityGroupId: securityGroup.id,
|
|
120
|
+
});
|
|
121
|
+
// Enable Prometheus to access the metrics port
|
|
122
|
+
(0, prometheus_1.makeSecurityGroupAccessibleByPrometheus)(securityGroup, metricsPort, metricsPort, taskName);
|
|
123
|
+
}
|
|
124
|
+
exports.setupPrometheusSecurityRules = setupPrometheusSecurityRules;
|
|
125
|
+
/**
|
|
126
|
+
* Builds a container definition object for ECS task definitions
|
|
127
|
+
*
|
|
128
|
+
* @param options Container definition options
|
|
129
|
+
* @returns Container definition object
|
|
130
|
+
*/
|
|
131
|
+
function buildContainerDefinition(options) {
|
|
132
|
+
const { name, image, cpu, memory, environment = [], secrets = [], command, entryPoint, portMappings = [], dockerLabels = {}, mountPoints = [], repositoryCredentials, logConfiguration, essential = true, healthCheck, } = options;
|
|
133
|
+
return {
|
|
134
|
+
name,
|
|
135
|
+
image,
|
|
136
|
+
essential,
|
|
137
|
+
environment,
|
|
138
|
+
secrets,
|
|
139
|
+
command,
|
|
140
|
+
entryPoint,
|
|
141
|
+
cpu,
|
|
142
|
+
memoryReservation: memory,
|
|
143
|
+
portMappings,
|
|
144
|
+
dockerLabels,
|
|
145
|
+
mountPoints,
|
|
146
|
+
repositoryCredentials,
|
|
147
|
+
logConfiguration,
|
|
148
|
+
healthCheck,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
exports.buildContainerDefinition = buildContainerDefinition;
|
|
152
|
+
/**
|
|
153
|
+
* Creates a Fargate task definition with standard settings
|
|
154
|
+
*
|
|
155
|
+
* @param options Task definition options
|
|
156
|
+
* @returns The created ECS Task Definition
|
|
157
|
+
*/
|
|
158
|
+
function createFargateTaskDefinition(options) {
|
|
159
|
+
const { name, executionRoleArn, taskRoleArn, containerDefinitions, team, cpu, memory, ephemeralStorageInGB, runtimePlatform, volumes, dependsOn = [], } = options;
|
|
160
|
+
return new aws.ecs.TaskDefinition(`${(0, stack_1.getStackScopedName)(name)}-taskdefinition`, {
|
|
161
|
+
executionRoleArn,
|
|
162
|
+
taskRoleArn,
|
|
163
|
+
tags: createResourceTags(name, team),
|
|
164
|
+
containerDefinitions,
|
|
165
|
+
ephemeralStorage: ephemeralStorageInGB
|
|
166
|
+
? { sizeInGib: ephemeralStorageInGB }
|
|
167
|
+
: undefined,
|
|
168
|
+
cpu: pulumi.output(cpu).apply((c) => c.toString()),
|
|
169
|
+
memory: pulumi.output(memory).apply((m) => m.toString()),
|
|
170
|
+
runtimePlatform,
|
|
171
|
+
requiresCompatibilities: ["FARGATE"],
|
|
172
|
+
networkMode: "awsvpc",
|
|
173
|
+
volumes,
|
|
174
|
+
family: (0, stack_1.getStackScopedName)(name),
|
|
175
|
+
}, { dependsOn });
|
|
176
|
+
}
|
|
177
|
+
exports.createFargateTaskDefinition = createFargateTaskDefinition;
|
|
178
|
+
//# sourceMappingURL=fargateHelpers.js.map
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export * from "./acceptAlb";
|
|
2
|
+
export * from "./acceptBastion";
|
|
3
|
+
export * from "./acceptDb";
|
|
4
|
+
export * from "./accessTheInternet";
|
|
5
|
+
export * from "./alb";
|
|
6
|
+
export * from "./buildStatic";
|
|
7
|
+
export * from "./certificate";
|
|
8
|
+
export * from "./cloudflare";
|
|
9
|
+
export * from "./cloudwatchLogs";
|
|
10
|
+
export * from "./createBucketWithUser";
|
|
11
|
+
export * from "./createFargateTask";
|
|
12
|
+
export * from "./createImageFromContext";
|
|
13
|
+
export * from "./createScheduledFargateTask";
|
|
14
|
+
export * from "./createSQSTriggeredFargateTask";
|
|
15
|
+
export * from "./domain";
|
|
16
|
+
export * from "./exposePublicService";
|
|
17
|
+
export * from "./getAmi";
|
|
18
|
+
export * from "./getDomainAndSubdomain";
|
|
19
|
+
export * from "./getImageRegistryAndCredentials";
|
|
20
|
+
export * from "./lambda";
|
|
21
|
+
export * from "./network";
|
|
22
|
+
export * from "./prometheus";
|
|
23
|
+
export * from "./scheduledTaskBase";
|
|
24
|
+
export * from "./secrets";
|
|
25
|
+
export * from "./slack";
|
|
26
|
+
export * from "./stack";
|
|
27
|
+
export * from "./StaticWebsite";
|
|
28
|
+
export * from "./supra";
|
|
29
|
+
export * from "./utils";
|
|
30
|
+
export * from "./values";
|
|
31
|
+
export * from "./vpc";
|
|
32
|
+
export { default as withCache } from "./withCache";
|
package/index.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Re-export all modules for convenient imports from "dcl-ops-lib"
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
15
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.withCache = void 0;
|
|
19
|
+
__exportStar(require("./acceptAlb"), exports);
|
|
20
|
+
__exportStar(require("./acceptBastion"), exports);
|
|
21
|
+
__exportStar(require("./acceptDb"), exports);
|
|
22
|
+
__exportStar(require("./accessTheInternet"), exports);
|
|
23
|
+
__exportStar(require("./alb"), exports);
|
|
24
|
+
__exportStar(require("./buildStatic"), exports);
|
|
25
|
+
__exportStar(require("./certificate"), exports);
|
|
26
|
+
__exportStar(require("./cloudflare"), exports);
|
|
27
|
+
__exportStar(require("./cloudwatchLogs"), exports);
|
|
28
|
+
__exportStar(require("./createBucketWithUser"), exports);
|
|
29
|
+
__exportStar(require("./createFargateTask"), exports);
|
|
30
|
+
__exportStar(require("./createImageFromContext"), exports);
|
|
31
|
+
__exportStar(require("./createScheduledFargateTask"), exports);
|
|
32
|
+
__exportStar(require("./createSQSTriggeredFargateTask"), exports);
|
|
33
|
+
__exportStar(require("./domain"), exports);
|
|
34
|
+
__exportStar(require("./exposePublicService"), exports);
|
|
35
|
+
__exportStar(require("./getAmi"), exports);
|
|
36
|
+
__exportStar(require("./getDomainAndSubdomain"), exports);
|
|
37
|
+
__exportStar(require("./getImageRegistryAndCredentials"), exports);
|
|
38
|
+
__exportStar(require("./lambda"), exports);
|
|
39
|
+
__exportStar(require("./network"), exports);
|
|
40
|
+
__exportStar(require("./prometheus"), exports);
|
|
41
|
+
__exportStar(require("./scheduledTaskBase"), exports);
|
|
42
|
+
__exportStar(require("./secrets"), exports);
|
|
43
|
+
__exportStar(require("./slack"), exports);
|
|
44
|
+
__exportStar(require("./stack"), exports);
|
|
45
|
+
__exportStar(require("./StaticWebsite"), exports);
|
|
46
|
+
__exportStar(require("./supra"), exports);
|
|
47
|
+
__exportStar(require("./utils"), exports);
|
|
48
|
+
__exportStar(require("./values"), exports);
|
|
49
|
+
__exportStar(require("./vpc"), exports);
|
|
50
|
+
var withCache_1 = require("./withCache");
|
|
51
|
+
Object.defineProperty(exports, "withCache", { enumerable: true, get: function () { return withCache_1.default; } });
|
|
52
|
+
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import * as aws from "@pulumi/aws";
|
|
2
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
3
|
+
import { Team, MetricsConfig } from "./fargateHelpers";
|
|
4
|
+
export { Team, MetricsConfig };
|
|
5
|
+
/**
|
|
6
|
+
* Retry policy configuration
|
|
7
|
+
*/
|
|
8
|
+
export type RetryPolicyConfig = {
|
|
9
|
+
/**
|
|
10
|
+
* Maximum number of retry attempts (0-185)
|
|
11
|
+
*/
|
|
12
|
+
maxRetries?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Maximum age of the event in seconds before it's discarded
|
|
15
|
+
*/
|
|
16
|
+
maxAgeSeconds?: number;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Base options shared between scheduled and SQS-triggered tasks
|
|
20
|
+
*/
|
|
21
|
+
export type BaseFargateTaskOptions = {
|
|
22
|
+
/**
|
|
23
|
+
* Team that owns this task
|
|
24
|
+
*/
|
|
25
|
+
team: Team;
|
|
26
|
+
/**
|
|
27
|
+
* CPU units for the task (256, 512, 1024, 2048, 4096)
|
|
28
|
+
*/
|
|
29
|
+
cpu?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Memory in MB for the task (512 - 30720, depending on CPU)
|
|
32
|
+
*/
|
|
33
|
+
memory?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Ephemeral storage in GB (20-200)
|
|
36
|
+
*/
|
|
37
|
+
ephemeralStorageInGB?: number;
|
|
38
|
+
/**
|
|
39
|
+
* Environment variables for the container
|
|
40
|
+
*/
|
|
41
|
+
environment?: {
|
|
42
|
+
name: string;
|
|
43
|
+
value: pulumi.Input<string>;
|
|
44
|
+
}[];
|
|
45
|
+
/**
|
|
46
|
+
* Secrets from SSM/Secrets Manager
|
|
47
|
+
*/
|
|
48
|
+
secrets?: aws.ecs.Secret[];
|
|
49
|
+
/**
|
|
50
|
+
* Override the container's default command
|
|
51
|
+
*/
|
|
52
|
+
command?: string[];
|
|
53
|
+
/**
|
|
54
|
+
* Override the container's entry point
|
|
55
|
+
*/
|
|
56
|
+
entryPoint?: string[];
|
|
57
|
+
/**
|
|
58
|
+
* Additional security groups
|
|
59
|
+
*/
|
|
60
|
+
securityGroups?: (string | pulumi.Output<string>)[];
|
|
61
|
+
/**
|
|
62
|
+
* Whether to assign a public IP (default: false)
|
|
63
|
+
*/
|
|
64
|
+
assignPublicIp?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Prometheus metrics configuration
|
|
67
|
+
*/
|
|
68
|
+
metrics?: MetricsConfig;
|
|
69
|
+
/**
|
|
70
|
+
* CloudWatch log retention in days (default: 60)
|
|
71
|
+
*/
|
|
72
|
+
logRetentionDays?: number;
|
|
73
|
+
/**
|
|
74
|
+
* Policies for the task execution role
|
|
75
|
+
*/
|
|
76
|
+
executionRolePolicies?: Record<string, pulumi.Input<string> | aws.iam.Policy>;
|
|
77
|
+
/**
|
|
78
|
+
* Policies for the task role (application permissions)
|
|
79
|
+
*/
|
|
80
|
+
taskRolePolicies?: Record<string, pulumi.Input<string> | aws.iam.Policy>;
|
|
81
|
+
/**
|
|
82
|
+
* ECS cluster to run the task on
|
|
83
|
+
*/
|
|
84
|
+
cluster?: aws.ecs.Cluster | string;
|
|
85
|
+
/**
|
|
86
|
+
* Number of tasks to launch per invocation (default: 1)
|
|
87
|
+
*/
|
|
88
|
+
taskCount?: number;
|
|
89
|
+
/**
|
|
90
|
+
* Runtime platform configuration (e.g., for ARM64)
|
|
91
|
+
*/
|
|
92
|
+
runtimePlatform?: aws.types.input.ecs.TaskDefinitionRuntimePlatform;
|
|
93
|
+
/**
|
|
94
|
+
* Volumes to attach to the task
|
|
95
|
+
*/
|
|
96
|
+
volumes?: pulumi.Input<aws.types.input.ecs.TaskDefinitionVolume[]>;
|
|
97
|
+
/**
|
|
98
|
+
* Mount points for the container
|
|
99
|
+
*/
|
|
100
|
+
mountPoints?: aws.ecs.MountPoint[];
|
|
101
|
+
/**
|
|
102
|
+
* Repository credentials for private registries
|
|
103
|
+
*/
|
|
104
|
+
repositoryCredentials?: aws.ecs.RepositoryCredentials;
|
|
105
|
+
/**
|
|
106
|
+
* Additional resources to depend on
|
|
107
|
+
*/
|
|
108
|
+
dependsOn?: pulumi.Resource[];
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Result of creating the base task infrastructure
|
|
112
|
+
*/
|
|
113
|
+
export type BaseTaskInfrastructure = {
|
|
114
|
+
taskDefinition: aws.ecs.TaskDefinition;
|
|
115
|
+
taskSecurityGroup: aws.ec2.SecurityGroup;
|
|
116
|
+
logGroup: aws.cloudwatch.LogGroup;
|
|
117
|
+
executionRole: aws.iam.Role;
|
|
118
|
+
taskRole: aws.iam.Role;
|
|
119
|
+
eventBridgeRole: aws.iam.Role;
|
|
120
|
+
eventBridgePolicy: aws.iam.RolePolicy;
|
|
121
|
+
clusterArn: string | pulumi.Output<string>;
|
|
122
|
+
subnetIds: string[];
|
|
123
|
+
securityGroups: (string | pulumi.Output<string>)[];
|
|
124
|
+
assignPublicIp: boolean;
|
|
125
|
+
taskCount: number;
|
|
126
|
+
resourcePrefix: string;
|
|
127
|
+
taskName: string;
|
|
128
|
+
team: Team;
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Creates the base infrastructure shared by both scheduled and SQS-triggered Fargate tasks.
|
|
132
|
+
* This includes: task definition, security group, log group, and IAM roles.
|
|
133
|
+
*
|
|
134
|
+
* Note: Slack notifications are now handled globally by the ops-lambdas EventBridge rule.
|
|
135
|
+
*
|
|
136
|
+
* @param taskName A name for this task
|
|
137
|
+
* @param dockerImage The docker image to run
|
|
138
|
+
* @param options Base configuration options
|
|
139
|
+
* @param eventBridgeServices AWS services that can assume the EventBridge role
|
|
140
|
+
* @returns Base infrastructure resources
|
|
141
|
+
*/
|
|
142
|
+
export declare function createBaseTaskInfrastructure(taskName: string, dockerImage: string | Promise<string> | pulumi.OutputInstance<string>, options: BaseFargateTaskOptions, eventBridgeServices: string[]): Promise<BaseTaskInfrastructure>;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createBaseTaskInfrastructure = void 0;
|
|
4
|
+
const aws = require("@pulumi/aws");
|
|
5
|
+
const pulumi = require("@pulumi/pulumi");
|
|
6
|
+
const network_1 = require("./network");
|
|
7
|
+
const vpc_1 = require("./vpc");
|
|
8
|
+
const stack_1 = require("./stack");
|
|
9
|
+
const accessTheInternet_1 = require("./accessTheInternet");
|
|
10
|
+
const createFargateTask_1 = require("./createFargateTask");
|
|
11
|
+
const fargateHelpers_1 = require("./fargateHelpers");
|
|
12
|
+
/**
|
|
13
|
+
* Creates the base infrastructure shared by both scheduled and SQS-triggered Fargate tasks.
|
|
14
|
+
* This includes: task definition, security group, log group, and IAM roles.
|
|
15
|
+
*
|
|
16
|
+
* Note: Slack notifications are now handled globally by the ops-lambdas EventBridge rule.
|
|
17
|
+
*
|
|
18
|
+
* @param taskName A name for this task
|
|
19
|
+
* @param dockerImage The docker image to run
|
|
20
|
+
* @param options Base configuration options
|
|
21
|
+
* @param eventBridgeServices AWS services that can assume the EventBridge role
|
|
22
|
+
* @returns Base infrastructure resources
|
|
23
|
+
*/
|
|
24
|
+
async function createBaseTaskInfrastructure(taskName, dockerImage, options, eventBridgeServices) {
|
|
25
|
+
const { team, cpu = fargateHelpers_1.DEFAULT_CPU, memory = fargateHelpers_1.DEFAULT_MEMORY, ephemeralStorageInGB, environment = [], secrets = [], command, entryPoint, securityGroups = [], assignPublicIp = false, metrics, logRetentionDays = fargateHelpers_1.DEFAULT_LOG_RETENTION_DAYS, executionRolePolicies = {}, taskRolePolicies = {}, cluster, taskCount = fargateHelpers_1.DEFAULT_DESIRED_COUNT, runtimePlatform, volumes, mountPoints = [], repositoryCredentials, dependsOn = [], } = options;
|
|
26
|
+
const version = (0, stack_1.getStackId)();
|
|
27
|
+
const resourcePrefix = `${taskName}-${version}`;
|
|
28
|
+
// Create execution role
|
|
29
|
+
const { role: executionRole, policies: executionPolicies } = (0, createFargateTask_1.getFargateExecutionRole)(`${resourcePrefix}-execution`, executionRolePolicies);
|
|
30
|
+
dependsOn.push(...executionPolicies);
|
|
31
|
+
// Create task role
|
|
32
|
+
const { role: taskRole, policies: taskPolicies } = (0, createFargateTask_1.getFargateTaskRole)(`${resourcePrefix}-task`, taskRolePolicies);
|
|
33
|
+
dependsOn.push(...taskPolicies);
|
|
34
|
+
// Get VPC for security group
|
|
35
|
+
const vpc = await (0, vpc_1.getVpc)();
|
|
36
|
+
// Create security group for the task
|
|
37
|
+
const taskSecurityGroup = (0, fargateHelpers_1.createTaskSecurityGroup)(resourcePrefix, vpc.id, taskName, team);
|
|
38
|
+
// Configure docker labels for Prometheus metrics
|
|
39
|
+
let dockerLabels = {};
|
|
40
|
+
let portMappings = [];
|
|
41
|
+
if (metrics) {
|
|
42
|
+
const prometheusConfig = (0, fargateHelpers_1.configurePrometheusMetrics)(taskName, metrics);
|
|
43
|
+
dockerLabels = prometheusConfig.dockerLabels;
|
|
44
|
+
portMappings = prometheusConfig.portMappings;
|
|
45
|
+
// Setup security group rules for Prometheus access
|
|
46
|
+
(0, fargateHelpers_1.setupPrometheusSecurityRules)(resourcePrefix, taskSecurityGroup, vpc.cidrBlock, prometheusConfig.metricsPort, taskName);
|
|
47
|
+
}
|
|
48
|
+
// Enable egress traffic to the internet
|
|
49
|
+
(0, accessTheInternet_1.makeSecurityGroupAccessTheInternetV2)(taskSecurityGroup, taskName);
|
|
50
|
+
// Create CloudWatch Log Group
|
|
51
|
+
const logGroup = (0, fargateHelpers_1.createLogGroup)(taskName, team, logRetentionDays);
|
|
52
|
+
// Build container definition
|
|
53
|
+
const containerDefinition = (0, fargateHelpers_1.buildContainerDefinition)({
|
|
54
|
+
name: taskName,
|
|
55
|
+
image: dockerImage,
|
|
56
|
+
cpu,
|
|
57
|
+
memory,
|
|
58
|
+
environment,
|
|
59
|
+
secrets,
|
|
60
|
+
command,
|
|
61
|
+
entryPoint,
|
|
62
|
+
portMappings,
|
|
63
|
+
dockerLabels,
|
|
64
|
+
mountPoints,
|
|
65
|
+
repositoryCredentials,
|
|
66
|
+
logConfiguration: (0, createFargateTask_1.getDefaultLogs)(taskName, logGroup),
|
|
67
|
+
});
|
|
68
|
+
// Create ECS Task Definition
|
|
69
|
+
const taskDefinition = (0, fargateHelpers_1.createFargateTaskDefinition)({
|
|
70
|
+
name: taskName,
|
|
71
|
+
executionRoleArn: executionRole.arn,
|
|
72
|
+
taskRoleArn: taskRole.arn,
|
|
73
|
+
containerDefinitions: pulumi.jsonStringify([containerDefinition]),
|
|
74
|
+
team,
|
|
75
|
+
cpu,
|
|
76
|
+
memory,
|
|
77
|
+
ephemeralStorageInGB,
|
|
78
|
+
runtimePlatform,
|
|
79
|
+
volumes,
|
|
80
|
+
dependsOn: [logGroup, ...dependsOn],
|
|
81
|
+
});
|
|
82
|
+
// Get cluster ARN and subnet IDs
|
|
83
|
+
const clusterArn = await (0, createFargateTask_1.getClusterInstance)(cluster);
|
|
84
|
+
const subnetIds = await (0, network_1.getPrivateSubnetIds)();
|
|
85
|
+
// Create IAM role for EventBridge to run ECS tasks
|
|
86
|
+
const eventBridgeRole = new aws.iam.Role(`${resourcePrefix}-eventbridge-role`, {
|
|
87
|
+
assumeRolePolicy: JSON.stringify({
|
|
88
|
+
Version: "2012-10-17",
|
|
89
|
+
Statement: [
|
|
90
|
+
{
|
|
91
|
+
Effect: "Allow",
|
|
92
|
+
Principal: {
|
|
93
|
+
Service: eventBridgeServices,
|
|
94
|
+
},
|
|
95
|
+
Action: "sts:AssumeRole",
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
}),
|
|
99
|
+
tags: (0, fargateHelpers_1.createResourceTags)(taskName, team),
|
|
100
|
+
});
|
|
101
|
+
// Create policy for EventBridge to run ECS tasks
|
|
102
|
+
const eventBridgePolicy = new aws.iam.RolePolicy(`${resourcePrefix}-eventbridge-policy`, {
|
|
103
|
+
role: eventBridgeRole.id,
|
|
104
|
+
policy: pulumi
|
|
105
|
+
.all([taskDefinition.arn, executionRole.arn, taskRole.arn])
|
|
106
|
+
.apply(([taskDefArn, execRoleArn, taskRoleArn]) => JSON.stringify({
|
|
107
|
+
Version: "2012-10-17",
|
|
108
|
+
Statement: [
|
|
109
|
+
{
|
|
110
|
+
Effect: "Allow",
|
|
111
|
+
Action: "ecs:RunTask",
|
|
112
|
+
Resource: taskDefArn,
|
|
113
|
+
Condition: {
|
|
114
|
+
ArnLike: {
|
|
115
|
+
"ecs:cluster": clusterArn,
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
Effect: "Allow",
|
|
121
|
+
Action: "iam:PassRole",
|
|
122
|
+
Resource: [execRoleArn, taskRoleArn],
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
})),
|
|
126
|
+
});
|
|
127
|
+
return {
|
|
128
|
+
taskDefinition,
|
|
129
|
+
taskSecurityGroup,
|
|
130
|
+
logGroup,
|
|
131
|
+
executionRole,
|
|
132
|
+
taskRole,
|
|
133
|
+
eventBridgeRole,
|
|
134
|
+
eventBridgePolicy,
|
|
135
|
+
clusterArn,
|
|
136
|
+
subnetIds,
|
|
137
|
+
securityGroups: [taskSecurityGroup.id, ...securityGroups],
|
|
138
|
+
assignPublicIp,
|
|
139
|
+
taskCount,
|
|
140
|
+
resourcePrefix,
|
|
141
|
+
taskName,
|
|
142
|
+
team,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
exports.createBaseTaskInfrastructure = createBaseTaskInfrastructure;
|
|
146
|
+
//# sourceMappingURL=scheduledTaskBase.js.map
|
package/slack.d.ts
ADDED
package/slack.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSlackNotificationLambdaArn = exports.getSlackNotificationTopicArn = exports.slackStack = void 0;
|
|
4
|
+
const pulumi = require("@pulumi/pulumi");
|
|
5
|
+
const domain_1 = require("./domain");
|
|
6
|
+
const withCache_1 = require("./withCache");
|
|
7
|
+
// Stack reference to the ops-lambdas stack that contains the Slack notifier infrastructure
|
|
8
|
+
exports.slackStack = (0, withCache_1.default)(async () => {
|
|
9
|
+
return new pulumi.StackReference(`ops-lambdas-${domain_1.env}`);
|
|
10
|
+
});
|
|
11
|
+
// Get the SNS topic ARN for Slack notifications
|
|
12
|
+
exports.getSlackNotificationTopicArn = (0, withCache_1.default)(async () => {
|
|
13
|
+
const stack = await (0, exports.slackStack)();
|
|
14
|
+
return (await stack.requireOutputValue("slackNotifierTopicArn"));
|
|
15
|
+
});
|
|
16
|
+
// Get the Lambda ARN for direct invocation (optional, prefer SNS topic)
|
|
17
|
+
exports.getSlackNotificationLambdaArn = (0, withCache_1.default)(async () => {
|
|
18
|
+
const stack = await (0, exports.slackStack)();
|
|
19
|
+
return (await stack.requireOutputValue("slackNotifierLambdaArn"));
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=slack.js.map
|