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.
@@ -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: "dapps" | "platform" | "data" | "marketing" | "infra";
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: string;
131
+ team: Team;
131
132
  targetGroups: aws.alb.TargetGroup[];
132
133
  runtimePlatform?: aws.types.input.ecs.TaskDefinitionRuntimePlatform;
133
134
  appAutoscaling?: {
@@ -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": (0, stack_1.getStackScopedName)(serviceName),
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 = 512;
110
+ memoryReservation = fargateHelpers_1.DEFAULT_MEMORY;
110
111
  }
111
112
  if (undefined === cpuReservation) {
112
- cpuReservation = 256;
113
+ cpuReservation = fargateHelpers_1.DEFAULT_CPU;
113
114
  }
114
115
  if (undefined === desiredCount) {
115
- desiredCount = 1;
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: { ServiceName: serviceName, Team: team },
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 = new aws.cloudwatch.LogGroup((0, stack_1.getStackScopedName)(serviceName), {
316
- name: (0, stack_1.getStackScopedName)(serviceName),
317
- retentionInDays: 60,
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
- ephemeralStorage: !!ephemeralStorageInGB
331
- ? {
332
- sizeInGib: ephemeralStorageInGB,
333
- }
334
- : undefined,
335
- cpu: containerInfo.cpu?.toString(),
336
- memory: containerInfo.memoryReservation?.toString(),
337
- runtimePlatform: runtimePlatform,
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: { ServiceName: serviceName, StackId: (0, stack_1.getStackId)(), Team: team },
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dcl-ops-lib",
3
- "version": "9.0.0",
3
+ "version": "9.1.0",
4
4
  "scripts": {
5
5
  "build": "tsc && cp bin/* . && node test.js",
6
6
  "clean": "rm *.d.ts *.js *.js.map"
@@ -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
@@ -0,0 +1,4 @@
1
+ import * as pulumi from "@pulumi/pulumi";
2
+ export declare const slackStack: () => Promise<pulumi.StackReference>;
3
+ export declare const getSlackNotificationTopicArn: () => Promise<string>;
4
+ export declare const getSlackNotificationLambdaArn: () => Promise<string>;
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