@fjall/components-infrastructure 0.96.0 → 0.99.3
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/dist/lib/app.d.ts +68 -1
- package/dist/lib/app.js +113 -4
- package/dist/lib/config/aws/__t17fixture.d.ts +1 -0
- package/dist/lib/config/aws/__t17fixture.js +3 -0
- package/dist/lib/config/aws/__t17fixtureType.d.ts +2 -0
- package/dist/lib/config/aws/__t17fixtureType.js +1 -0
- package/dist/lib/config/aws/alarmTopic.js +8 -4
- package/dist/lib/config/aws/cloudTrail.js +1 -1
- package/dist/lib/config/aws/disasterRecovery.js +11 -16
- package/dist/lib/config/aws/ecrDefaultImage.d.ts +0 -1
- package/dist/lib/config/aws/ecrDefaultImage.js +13 -23
- package/dist/lib/config/aws/identityCenter.d.ts +10 -3
- package/dist/lib/config/aws/identityCenter.js +101 -37
- package/dist/lib/config/aws/identityCenterGroupMembership.js +8 -2
- package/dist/lib/config/aws/identityCenterMembership.d.ts +11 -0
- package/dist/lib/config/aws/identityCenterMembership.js +61 -0
- package/dist/lib/config/aws/index.d.ts +1 -1
- package/dist/lib/config/aws/index.js +1 -1
- package/dist/lib/config/aws/ipam.js +6 -11
- package/dist/lib/config/aws/oidcConnector.js +5 -1
- package/dist/lib/config/aws/scpPreset.js +4 -1
- package/dist/lib/patterns/aws/_eslint_test_tmp/leak.d.ts +1 -0
- package/dist/lib/patterns/aws/_eslint_test_tmp/leak.js +4 -0
- package/dist/lib/patterns/aws/account.js +2 -4
- package/dist/lib/patterns/aws/apexDomainPattern.js +10 -10
- package/dist/lib/patterns/aws/bastionFactory.d.ts +10 -0
- package/dist/lib/patterns/aws/bastionFactory.js +29 -0
- package/dist/lib/patterns/aws/buildkite.d.ts +2 -2
- package/dist/lib/patterns/aws/buildkite.js +51 -97
- package/dist/lib/patterns/aws/cdn.js +1 -1
- package/dist/lib/patterns/aws/clickhouseDatabase.d.ts +173 -0
- package/dist/lib/patterns/aws/clickhouseDatabase.js +601 -0
- package/dist/lib/patterns/aws/compute.d.ts +4 -6
- package/dist/lib/patterns/aws/compute.js +7 -13
- package/dist/lib/patterns/aws/computeEcs.d.ts +93 -5
- package/dist/lib/patterns/aws/computeEcs.js +867 -37
- package/dist/lib/patterns/aws/computeEcsTypes.d.ts +528 -25
- package/dist/lib/patterns/aws/computeEcsTypes.js +10 -0
- package/dist/lib/patterns/aws/computeLambda.d.ts +0 -5
- package/dist/lib/patterns/aws/computeLambda.js +1 -2
- package/dist/lib/patterns/aws/database.d.ts +50 -8
- package/dist/lib/patterns/aws/database.js +183 -27
- package/dist/lib/patterns/aws/domain.js +6 -4
- package/dist/lib/patterns/aws/index.d.ts +1 -0
- package/dist/lib/patterns/aws/index.js +1 -0
- package/dist/lib/patterns/aws/interfaces/compute.d.ts +7 -1
- package/dist/lib/patterns/aws/interfaces/database.d.ts +187 -8
- package/dist/lib/patterns/aws/interfaces/database.js +17 -3
- package/dist/lib/patterns/aws/interfaces/index.d.ts +2 -1
- package/dist/lib/patterns/aws/interfaces/index.js +3 -1
- package/dist/lib/patterns/aws/interfaces/messaging.d.ts +7 -0
- package/dist/lib/patterns/aws/interfaces/migrationContributor.d.ts +47 -0
- package/dist/lib/patterns/aws/interfaces/migrationContributor.js +9 -0
- package/dist/lib/patterns/aws/messaging.d.ts +66 -10
- package/dist/lib/patterns/aws/messaging.js +115 -20
- package/dist/lib/patterns/aws/network.js +16 -7
- package/dist/lib/patterns/aws/organisation.d.ts +4 -0
- package/dist/lib/patterns/aws/organisation.js +22 -4
- package/dist/lib/patterns/aws/storage.d.ts +1 -2
- package/dist/lib/patterns/aws/storage.js +3 -2
- package/dist/lib/patterns/aws/vpcPeer.js +3 -1
- package/dist/lib/resources/aws/analytics/clickhouse.js +18 -9
- package/dist/lib/resources/aws/analytics/clickhouseAlarms.d.ts +24 -9
- package/dist/lib/resources/aws/analytics/clickhouseAlarms.js +61 -10
- package/dist/lib/resources/aws/analytics/clickhouseConstants.d.ts +3 -3
- package/dist/lib/resources/aws/analytics/clickhouseConstants.js +3 -3
- package/dist/lib/resources/aws/analytics/clickhouseTypes.d.ts +7 -1
- package/dist/lib/resources/aws/analytics/clickhouseUserData.d.ts +1 -1
- package/dist/lib/resources/aws/analytics/clickhouseUserData.js +53 -3
- package/dist/lib/resources/aws/base/awsStack.js +4 -2
- package/dist/lib/resources/aws/compute/__tmp__/regression-shape.d.ts +2 -0
- package/dist/lib/resources/aws/compute/__tmp__/regression-shape.js +11 -0
- package/dist/lib/resources/aws/compute/asgInlineLifecycleHook.d.ts +52 -0
- package/dist/lib/resources/aws/compute/asgInlineLifecycleHook.js +60 -0
- package/dist/lib/resources/aws/compute/blockDeviceVolume.d.ts +8 -0
- package/dist/lib/resources/aws/compute/blockDeviceVolume.js +10 -0
- package/dist/lib/resources/aws/compute/ec2.d.ts +132 -12
- package/dist/lib/resources/aws/compute/ec2.js +163 -23
- package/dist/lib/resources/aws/compute/ec2GracefulTerminationHandler.d.ts +41 -0
- package/dist/lib/resources/aws/compute/ec2GracefulTerminationHandler.js +194 -0
- package/dist/lib/resources/aws/compute/ec2GracefulTerminationLambda.source.cjs +458 -0
- package/dist/lib/resources/aws/compute/ecs.d.ts +27 -1
- package/dist/lib/resources/aws/compute/ecs.js +42 -2
- package/dist/lib/resources/aws/compute/ecsConstants.d.ts +9 -0
- package/dist/lib/resources/aws/compute/ecsConstants.js +16 -0
- package/dist/lib/resources/aws/compute/ecsImages.js +32 -20
- package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.d.ts +96 -0
- package/dist/lib/resources/aws/compute/ecsLifecycleHookMigration.js +113 -0
- package/dist/lib/resources/aws/compute/ecsNetworking.d.ts +2 -1
- package/dist/lib/resources/aws/compute/ecsNetworking.js +18 -6
- package/dist/lib/resources/aws/compute/ecsServiceFactory.d.ts +13 -4
- package/dist/lib/resources/aws/compute/ecsServiceFactory.js +155 -33
- package/dist/lib/resources/aws/compute/ecsTaskDefinition.d.ts +31 -1
- package/dist/lib/resources/aws/compute/ecsTaskDefinition.js +102 -6
- package/dist/lib/resources/aws/compute/ecsTypes.d.ts +173 -13
- package/dist/lib/resources/aws/compute/ecsValidation.d.ts +9 -0
- package/dist/lib/resources/aws/compute/ecsValidation.js +63 -0
- package/dist/lib/resources/aws/compute/index.d.ts +2 -0
- package/dist/lib/resources/aws/compute/index.js +2 -0
- package/dist/lib/resources/aws/compute/lambda.d.ts +7 -13
- package/dist/lib/resources/aws/compute/lambda.js +30 -38
- package/dist/lib/resources/aws/compute/lifecycleHookLambda.source.cjs +192 -0
- package/dist/lib/resources/aws/compute/persistentDataVolume.d.ts +104 -0
- package/dist/lib/resources/aws/compute/persistentDataVolume.js +245 -0
- package/dist/lib/resources/aws/compute/persistentDataVolumeLambda.source.cjs +398 -0
- package/dist/lib/resources/aws/compute/samApplication.d.ts +15 -0
- package/dist/lib/resources/aws/compute/samApplication.js +27 -0
- package/dist/lib/resources/aws/database/clickhouseConstants.d.ts +159 -0
- package/dist/lib/resources/aws/database/clickhouseConstants.js +181 -0
- package/dist/lib/resources/aws/database/clickhouseSchemas.d.ts +71 -0
- package/dist/lib/resources/aws/database/clickhouseSchemas.js +160 -0
- package/dist/lib/resources/aws/database/clickhouseSecurityGroup.d.ts +14 -0
- package/dist/lib/resources/aws/database/clickhouseSecurityGroup.js +23 -0
- package/dist/lib/resources/aws/database/clickhouseUserData.d.ts +69 -0
- package/dist/lib/resources/aws/database/clickhouseUserData.js +371 -0
- package/dist/lib/resources/aws/database/clickhouseXmlRenderer.d.ts +56 -0
- package/dist/lib/resources/aws/database/clickhouseXmlRenderer.js +112 -0
- package/dist/lib/resources/aws/database/rdsAurora.d.ts +8 -1
- package/dist/lib/resources/aws/database/rdsAurora.js +42 -32
- package/dist/lib/resources/aws/database/rdsAuroraGlobal.d.ts +15 -2
- package/dist/lib/resources/aws/database/rdsAuroraGlobal.js +39 -43
- package/dist/lib/resources/aws/database/rdsDefaults.d.ts +6 -0
- package/dist/lib/resources/aws/database/rdsDefaults.js +7 -1
- package/dist/lib/resources/aws/database/rdsHelpers.d.ts +3 -3
- package/dist/lib/resources/aws/database/rdsHelpers.js +1 -0
- package/dist/lib/resources/aws/database/rdsInstance.d.ts +8 -1
- package/dist/lib/resources/aws/database/rdsInstance.js +51 -34
- package/dist/lib/resources/aws/database/rdsProxyOutput.d.ts +1 -1
- package/dist/lib/resources/aws/database/rdsProxyOutput.js +1 -1
- package/dist/lib/resources/aws/iam/delegationRole.js +1 -1
- package/dist/lib/resources/aws/iam/identityCenter/groupMembership.d.ts +9 -0
- package/dist/lib/resources/aws/iam/identityCenter/groupMembership.js +12 -0
- package/dist/lib/resources/aws/iam/identityCenter/index.d.ts +1 -0
- package/dist/lib/resources/aws/iam/identityCenter/index.js +1 -0
- package/dist/lib/resources/aws/iam/identityCenter/permissionSet.d.ts +1 -0
- package/dist/lib/resources/aws/iam/identityCenter/permissionSet.js +1 -0
- package/dist/lib/resources/aws/logging/logGroup.d.ts +0 -8
- package/dist/lib/resources/aws/logging/logGroup.js +0 -11
- package/dist/lib/resources/aws/messaging/defaultEventBus.d.ts +7 -0
- package/dist/lib/resources/aws/messaging/defaultEventBus.js +21 -0
- package/dist/lib/resources/aws/messaging/eventBridgeRule.d.ts +96 -0
- package/dist/lib/resources/aws/messaging/eventBridgeRule.js +110 -0
- package/dist/lib/resources/aws/messaging/eventTargets.d.ts +84 -0
- package/dist/lib/resources/aws/messaging/eventTargets.js +152 -0
- package/dist/lib/resources/aws/messaging/eventbridge.d.ts +25 -2
- package/dist/lib/resources/aws/messaging/eventbridge.js +22 -10
- package/dist/lib/resources/aws/messaging/index.d.ts +5 -0
- package/dist/lib/resources/aws/messaging/index.js +2 -0
- package/dist/lib/resources/aws/messaging/schedule.d.ts +118 -0
- package/dist/lib/resources/aws/messaging/schedule.js +64 -0
- package/dist/lib/resources/aws/messaging/sns.d.ts +2 -1
- package/dist/lib/resources/aws/messaging/sqs.d.ts +2 -1
- package/dist/lib/resources/aws/messaging/subscription.d.ts +112 -0
- package/dist/lib/resources/aws/messaging/subscription.js +67 -0
- package/dist/lib/resources/aws/messaging/utils.d.ts +6 -0
- package/dist/lib/resources/aws/messaging/utils.js +10 -0
- package/dist/lib/resources/aws/monitoring/clickhouseAlarms.d.ts +60 -0
- package/dist/lib/resources/aws/monitoring/clickhouseAlarms.js +139 -0
- package/dist/lib/resources/aws/monitoring/index.d.ts +2 -0
- package/dist/lib/resources/aws/monitoring/index.js +2 -0
- package/dist/lib/resources/aws/monitoring/scheduleAlarms.d.ts +47 -0
- package/dist/lib/resources/aws/monitoring/scheduleAlarms.js +106 -0
- package/dist/lib/resources/aws/networking/crossAccountDelegationRecord.js +6 -4
- package/dist/lib/resources/aws/networking/crossAccountReturnRoutes.js +17 -13
- package/dist/lib/resources/aws/networking/dnsRecord/dnsRecordBase.js +7 -5
- package/dist/lib/resources/aws/networking/domainCertificate.d.ts +2 -2
- package/dist/lib/resources/aws/networking/domainCertificate.js +6 -4
- package/dist/lib/resources/aws/networking/hostedZone.js +6 -5
- package/dist/lib/resources/aws/networking/serviceDiscovery.d.ts +96 -0
- package/dist/lib/resources/aws/networking/serviceDiscovery.js +96 -0
- package/dist/lib/resources/aws/networking/vpc.d.ts +4 -1
- package/dist/lib/resources/aws/networking/vpc.js +4 -1
- package/dist/lib/resources/aws/networking/vpcPeeringConnection.js +21 -3
- package/dist/lib/resources/aws/organisation/costAllocationTagActivator.d.ts +16 -5
- package/dist/lib/resources/aws/organisation/costAllocationTagActivator.js +17 -3
- package/dist/lib/resources/aws/organisation/index.d.ts +1 -1
- package/dist/lib/resources/aws/organisation/organisationPolicy.d.ts +2 -0
- package/dist/lib/resources/aws/organisation/organisationPolicy.js +3 -2
- package/dist/lib/resources/aws/secrets/secret.d.ts +7 -0
- package/dist/lib/resources/aws/secrets/secret.js +4 -3
- package/dist/lib/resources/aws/storage/bucketDeployment.d.ts +16 -0
- package/dist/lib/resources/aws/storage/bucketDeployment.js +17 -0
- package/dist/lib/resources/aws/storage/ecr.js +5 -5
- package/dist/lib/resources/aws/storage/index.d.ts +1 -0
- package/dist/lib/resources/aws/storage/index.js +1 -0
- package/dist/lib/resources/aws/storage/s3.js +10 -3
- package/dist/lib/resources/aws/utilities/customResource.js +18 -9
- package/dist/lib/synth_dump.d.ts +1 -0
- package/dist/lib/synth_dump.js +42 -0
- package/dist/lib/utils/cdkContext.d.ts +2 -0
- package/dist/lib/utils/cdkContext.js +4 -2
- package/dist/lib/utils/connections.js +6 -0
- package/dist/lib/utils/connector.d.ts +12 -0
- package/dist/lib/utils/costAllocationTags.d.ts +9 -0
- package/dist/lib/utils/costAllocationTags.js +11 -1
- package/dist/lib/utils/databaseTypes.d.ts +14 -0
- package/dist/lib/utils/getConfig.d.ts +2 -0
- package/dist/lib/utils/getConfig.js +2 -0
- package/dist/lib/utils/index.d.ts +1 -0
- package/dist/lib/utils/index.js +1 -0
- package/dist/lib/utils/manifestWriter.d.ts +6 -89
- package/dist/lib/utils/manifestWriter.js +36 -23
- package/dist/lib/utils/migrationVersionResolvers.d.ts +2 -0
- package/dist/lib/utils/migrationVersionResolvers.js +2 -0
- package/dist/lib/utils/orgConfigParser.js +2 -1
- package/dist/lib/utils/resolveAlertsTopic.d.ts +14 -0
- package/dist/lib/utils/resolveAlertsTopic.js +30 -0
- package/dist/lib/utils/validationLogger.js +6 -3
- package/package.json +22 -19
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { AwsLogDriver, FargateTaskDefinition, Ec2TaskDefinition, NetworkMode, CpuArchitecture, OperatingSystemFamily } from "aws-cdk-lib/aws-ecs";
|
|
1
|
+
import { AwsLogDriver, ContainerDependencyCondition, FargateTaskDefinition, Ec2TaskDefinition, NetworkMode, CpuArchitecture, OperatingSystemFamily } from "aws-cdk-lib/aws-ecs";
|
|
2
2
|
import { Duration } from "aws-cdk-lib";
|
|
3
3
|
import { Secret as EcsSecret } from "aws-cdk-lib/aws-ecs";
|
|
4
4
|
import { Secret } from "aws-cdk-lib/aws-secretsmanager";
|
|
5
5
|
import { StringParameter } from "aws-cdk-lib/aws-ssm";
|
|
6
6
|
import { resolveOrgId } from "../../../utils/cdkContext.js";
|
|
7
7
|
import { validateSsmPathComponent } from "./ecsValidation.js";
|
|
8
|
-
import { DEFAULT_LOG_RETENTION_DAYS } from "./ecsConstants.js";
|
|
8
|
+
import { DEFAULT_LOG_RETENTION_DAYS, DEFAULT_FARGATE_CPU, DEFAULT_FARGATE_MEMORY_MIB, DEFAULT_EC2_CONTAINER_MEMORY_MIB } from "./ecsConstants.js";
|
|
9
9
|
import { getContainerImage } from "./ecsImages.js";
|
|
10
10
|
import { resolveRemoteConnections } from "./ecsRemoteConnections.js";
|
|
11
11
|
// Re-export extracted functions so existing consumers are not broken
|
|
@@ -66,8 +66,8 @@ export function deriveSsmSecretsPath(props, serviceName, explicitPath) {
|
|
|
66
66
|
return `/${appName}/${props.clusterName}/${serviceName}`;
|
|
67
67
|
}
|
|
68
68
|
export function createTaskDefinition(ctx, serviceName, serviceProps, executionRole, taskRole) {
|
|
69
|
-
const cpu = serviceProps.cpu ??
|
|
70
|
-
const memoryLimitMiB = serviceProps.memoryLimitMiB ??
|
|
69
|
+
const cpu = serviceProps.cpu ?? DEFAULT_FARGATE_CPU;
|
|
70
|
+
const memoryLimitMiB = serviceProps.memoryLimitMiB ?? DEFAULT_FARGATE_MEMORY_MIB;
|
|
71
71
|
if (isServiceFargate(serviceProps)) {
|
|
72
72
|
return new FargateTaskDefinition(ctx.scope, `${serviceName}TaskDefinition`, {
|
|
73
73
|
family: `${ctx.props.clusterName}-${serviceName}`,
|
|
@@ -82,16 +82,62 @@ export function createTaskDefinition(ctx, serviceName, serviceProps, executionRo
|
|
|
82
82
|
});
|
|
83
83
|
}
|
|
84
84
|
else {
|
|
85
|
+
const networkMode = serviceProps.networkMode ??
|
|
86
|
+
(ctx.directAccessEnabled ? NetworkMode.HOST : NetworkMode.AWS_VPC);
|
|
85
87
|
return new Ec2TaskDefinition(ctx.scope, `${serviceName}TaskDefinition`, {
|
|
86
88
|
family: `${ctx.props.clusterName}-${serviceName}`,
|
|
87
89
|
executionRole,
|
|
88
90
|
taskRole,
|
|
89
|
-
...(
|
|
91
|
+
...(networkMode !== undefined && { networkMode })
|
|
90
92
|
});
|
|
91
93
|
}
|
|
92
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Routing point for `Ec2TaskDefinition`s used by EventBridge-triggered scheduled
|
|
97
|
+
* tasks (per `EcsClusterConfig.scheduledTasks`). Pattern-layer callers MUST
|
|
98
|
+
* reach `Ec2TaskDefinition` through this wrapper rather than instantiating the
|
|
99
|
+
* raw CDK class — a future SOC2-relevant default (encryption, retention,
|
|
100
|
+
* uniform tags) added here propagates to every scheduled-task task def at once.
|
|
101
|
+
*
|
|
102
|
+
* Compare with `createTaskDefinition()` above, which is the per-service path;
|
|
103
|
+
* this is the per-schedule path and intentionally kept narrow (no execution /
|
|
104
|
+
* task roles — scheduled tasks use task-definition defaults).
|
|
105
|
+
*/
|
|
106
|
+
export function createScheduledTaskDefinition(scope, id, props) {
|
|
107
|
+
return new Ec2TaskDefinition(scope, id, {
|
|
108
|
+
family: props.family,
|
|
109
|
+
...(props.networkMode !== undefined && { networkMode: props.networkMode })
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Routing point for `FargateTaskDefinition`s used by the lifecycle-hook
|
|
114
|
+
* migration runner when `migrations.separateTaskDef` is set. Synthesises a
|
|
115
|
+
* dedicated Fargate task definition with caller-supplied CPU/memory and the
|
|
116
|
+
* supplied execution + task roles. Runtime platform pinned to ARM64/Linux to
|
|
117
|
+
* match the service task def default.
|
|
118
|
+
*/
|
|
119
|
+
export function createMigrationTaskDefinition(scope, id, props) {
|
|
120
|
+
return new FargateTaskDefinition(scope, id, {
|
|
121
|
+
family: props.family,
|
|
122
|
+
cpu: props.cpu,
|
|
123
|
+
memoryLimitMiB: props.memoryLimitMiB,
|
|
124
|
+
executionRole: props.executionRole,
|
|
125
|
+
taskRole: props.taskRole,
|
|
126
|
+
runtimePlatform: {
|
|
127
|
+
cpuArchitecture: CpuArchitecture.ARM64,
|
|
128
|
+
operatingSystemFamily: OperatingSystemFamily.LINUX
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
const CONTAINER_DEPENDENCY_CONDITIONS = {
|
|
133
|
+
START: ContainerDependencyCondition.START,
|
|
134
|
+
COMPLETE: ContainerDependencyCondition.COMPLETE,
|
|
135
|
+
SUCCESS: ContainerDependencyCondition.SUCCESS,
|
|
136
|
+
HEALTHY: ContainerDependencyCondition.HEALTHY
|
|
137
|
+
};
|
|
93
138
|
export function addContainersToTask(ctx, serviceName, serviceProps, taskDefinition) {
|
|
94
139
|
const containers = [];
|
|
140
|
+
const containerByName = new Map();
|
|
95
141
|
let primaryContainer;
|
|
96
142
|
const orgId = resolveOrgId(ctx.scope.node);
|
|
97
143
|
const remoteEnvByService = resolveRemoteConnections([serviceProps], ctx.scope, orgId);
|
|
@@ -158,19 +204,69 @@ export function addContainersToTask(ctx, serviceName, serviceProps, taskDefiniti
|
|
|
158
204
|
: undefined
|
|
159
205
|
}
|
|
160
206
|
: undefined,
|
|
207
|
+
stopTimeout: containerConfig.stopTimeout !== undefined
|
|
208
|
+
? Duration.seconds(containerConfig.stopTimeout)
|
|
209
|
+
: undefined,
|
|
161
210
|
...(isServiceEc2(serviceProps) && {
|
|
162
|
-
memoryLimitMiB: serviceProps.ec2Config?.memoryLimitMiB ??
|
|
211
|
+
memoryLimitMiB: serviceProps.ec2Config?.memoryLimitMiB ??
|
|
212
|
+
DEFAULT_EC2_CONTAINER_MEMORY_MIB
|
|
163
213
|
})
|
|
164
214
|
});
|
|
215
|
+
if (containerConfig.port !== undefined &&
|
|
216
|
+
containerConfig.portMappings !== undefined &&
|
|
217
|
+
containerConfig.portMappings.length > 0) {
|
|
218
|
+
throw new Error(`Container '${containerConfig.name}' in service '${serviceName}': ` +
|
|
219
|
+
`"port" and "portMappings" are mutually exclusive on EcsContainerConfig — supply one or the other, not both.`);
|
|
220
|
+
}
|
|
165
221
|
if (containerConfig.port) {
|
|
166
222
|
container.addPortMappings({
|
|
167
223
|
containerPort: containerConfig.port
|
|
168
224
|
});
|
|
169
225
|
}
|
|
226
|
+
else if (containerConfig.portMappings &&
|
|
227
|
+
containerConfig.portMappings.length > 0) {
|
|
228
|
+
container.addPortMappings(...containerConfig.portMappings);
|
|
229
|
+
}
|
|
230
|
+
if (containerConfig.volumes && containerConfig.volumes.length > 0) {
|
|
231
|
+
for (const volume of containerConfig.volumes) {
|
|
232
|
+
taskDefinition.addVolume({
|
|
233
|
+
name: volume.name,
|
|
234
|
+
...(volume.hostSourcePath !== undefined && {
|
|
235
|
+
host: { sourcePath: volume.hostSourcePath }
|
|
236
|
+
})
|
|
237
|
+
});
|
|
238
|
+
container.addMountPoints({
|
|
239
|
+
sourceVolume: volume.name,
|
|
240
|
+
containerPath: volume.mountPath,
|
|
241
|
+
readOnly: volume.readOnly ?? false
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
170
245
|
if (isFirstWithPort) {
|
|
171
246
|
primaryContainer = container;
|
|
172
247
|
}
|
|
173
248
|
containers.push(container);
|
|
249
|
+
containerByName.set(containerConfig.name, container);
|
|
250
|
+
}
|
|
251
|
+
for (const containerConfig of serviceProps.containers) {
|
|
252
|
+
if (!containerConfig.dependsOn || containerConfig.dependsOn.length === 0) {
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
const dependent = containerByName.get(containerConfig.name);
|
|
256
|
+
if (!dependent)
|
|
257
|
+
continue;
|
|
258
|
+
for (const dep of containerConfig.dependsOn) {
|
|
259
|
+
const target = containerByName.get(dep.container);
|
|
260
|
+
if (!target) {
|
|
261
|
+
const available = [...containerByName.keys()].join(", ");
|
|
262
|
+
throw new Error(`Service '${serviceName}': container '${containerConfig.name}' dependsOn ` +
|
|
263
|
+
`unknown container '${dep.container}'. Available containers: ${available}.`);
|
|
264
|
+
}
|
|
265
|
+
dependent.addContainerDependencies({
|
|
266
|
+
container: target,
|
|
267
|
+
condition: CONTAINER_DEPENDENCY_CONDITIONS[dep.condition]
|
|
268
|
+
});
|
|
269
|
+
}
|
|
174
270
|
}
|
|
175
271
|
return { containers, primaryContainer };
|
|
176
272
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { type ContainerDefinition, type RepositoryImage } from "aws-cdk-lib/aws-ecs";
|
|
2
|
-
import { type IVpc } from "aws-cdk-lib/aws-ec2";
|
|
1
|
+
import { type ContainerDefinition, type NetworkMode, type PortMapping, type RepositoryImage } from "aws-cdk-lib/aws-ecs";
|
|
2
|
+
import { type BlockDevice, type IMachineImage, type ISecurityGroup, type IVpc, type UserData } from "aws-cdk-lib/aws-ec2";
|
|
3
|
+
import { type Monitoring } from "aws-cdk-lib/aws-autoscaling";
|
|
4
|
+
import { type IService } from "aws-cdk-lib/aws-servicediscovery";
|
|
3
5
|
import { type IManagedPolicy, type PolicyDocument } from "aws-cdk-lib/aws-iam";
|
|
6
|
+
import type { DockerBuild } from "@fjall/util/manifest/schemas";
|
|
4
7
|
import { type TargetTrackingScalingPolicy } from "aws-cdk-lib/aws-applicationautoscaling";
|
|
5
8
|
import { type GeoLocation } from "aws-cdk-lib/aws-route53";
|
|
6
9
|
import { type Repository } from "aws-cdk-lib/aws-ecr";
|
|
@@ -15,6 +18,7 @@ import { type SecretImport } from "../secrets/index.js";
|
|
|
15
18
|
import type { ManagedDomainExports } from "../../../utils/domainTypes.js";
|
|
16
19
|
import type { ITopic } from "aws-cdk-lib/aws-sns";
|
|
17
20
|
import type { EcsServiceAlarmThresholds } from "../monitoring/index.js";
|
|
21
|
+
import { type Ec2InstancePersistentDataVolumeConfig } from "./ec2.js";
|
|
18
22
|
export declare enum Protocol {
|
|
19
23
|
HTTP = 0,
|
|
20
24
|
HTTPS = 1
|
|
@@ -23,7 +27,8 @@ export declare enum ScalingType {
|
|
|
23
27
|
CPU = "ECSServiceAverageCPUUtilization",
|
|
24
28
|
MEMORY = "ECSServiceAverageMemoryUtilization"
|
|
25
29
|
}
|
|
26
|
-
|
|
30
|
+
import type { EcsCapacityProvider } from "@fjall/generator";
|
|
31
|
+
export type { EcsCapacityProvider };
|
|
27
32
|
/**
|
|
28
33
|
* EC2 capacity configuration for ECS EC2-backed clusters.
|
|
29
34
|
* Only used when capacityProvider is "EC2".
|
|
@@ -47,6 +52,52 @@ export interface Ec2CapacityConfig {
|
|
|
47
52
|
/** Return instances to the pool on scale-in instead of terminating. Default: true */
|
|
48
53
|
reuseOnScaleIn?: boolean;
|
|
49
54
|
};
|
|
55
|
+
/** CDK `AutoScalingGroupProps.desiredCapacity` — initial instance count. */
|
|
56
|
+
desiredCapacity?: number;
|
|
57
|
+
/**
|
|
58
|
+
* CDK `LaunchTemplateProps.machineImage`. When provided, overrides the
|
|
59
|
+
* default `EcsOptimizedImage.amazonLinux2023(amiHardwareType)`. Use for
|
|
60
|
+
* stateful workloads requiring a custom AMI.
|
|
61
|
+
*/
|
|
62
|
+
machineImage?: IMachineImage;
|
|
63
|
+
/**
|
|
64
|
+
* CDK `aws-cdk-lib/aws-autoscaling.Monitoring`. Routes through the
|
|
65
|
+
* LaunchTemplate's `detailedMonitoring` field. Default: `Monitoring.BASIC`.
|
|
66
|
+
*/
|
|
67
|
+
instanceMonitoring?: Monitoring;
|
|
68
|
+
/** CDK `LaunchTemplateProps.blockDevices`. Use for EBS attachments. */
|
|
69
|
+
blockDevices?: BlockDevice[];
|
|
70
|
+
/**
|
|
71
|
+
* CDK `LaunchTemplateProps.userData`. When provided, overrides the
|
|
72
|
+
* default empty `UserData.forLinux()`.
|
|
73
|
+
*/
|
|
74
|
+
userData?: UserData;
|
|
75
|
+
/** CDK `LaunchTemplateProps.associatePublicIpAddress`. */
|
|
76
|
+
associatePublicIpAddress?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Pin the ASG to a specific set of availability zones. When
|
|
79
|
+
* `persistentDataVolume` is set, MUST contain exactly one entry matching
|
|
80
|
+
* `persistentDataVolume.availabilityZone` — the standalone EBS volume is
|
|
81
|
+
* AZ-local and cannot follow a multi-AZ ASG. Merged into `vpcSubnets` at
|
|
82
|
+
* the `Ec2Instance` boundary.
|
|
83
|
+
*/
|
|
84
|
+
availabilityZones?: string[];
|
|
85
|
+
/**
|
|
86
|
+
* Pairs the EC2 capacity ASG with a standalone EBS data volume that
|
|
87
|
+
* re-attaches across instance refreshes. Forwarded to `Ec2Instance` which
|
|
88
|
+
* locates and detaches the volume via TERMINATING/LAUNCHING lifecycle
|
|
89
|
+
* hooks. Implies a singleton service — do not share an ASG across
|
|
90
|
+
* services when this is set (`getEc2ConfigKey` adds a discriminator to
|
|
91
|
+
* keep them apart).
|
|
92
|
+
*/
|
|
93
|
+
persistentDataVolume?: Ec2InstancePersistentDataVolumeConfig;
|
|
94
|
+
/**
|
|
95
|
+
* Tags applied to the underlying ASG with `applyToLaunchedInstances: true`
|
|
96
|
+
* so every launched EC2 instance carries the tags. Used for tag-based SSM
|
|
97
|
+
* `SendCommand` targeting (`Targets: [{ Key: "tag:<name>", Values: […] }]`).
|
|
98
|
+
* Empty-string keys or values are rejected at the resources layer.
|
|
99
|
+
*/
|
|
100
|
+
tags?: Record<string, string>;
|
|
50
101
|
}
|
|
51
102
|
/**
|
|
52
103
|
* Domain configuration for HTTPS and DNS.
|
|
@@ -69,6 +120,17 @@ export interface GeoLocationDomainConfig extends DomainBaseConfig {
|
|
|
69
120
|
geoLocation: GeoLocation;
|
|
70
121
|
}
|
|
71
122
|
export type DomainConfig = DomainBaseConfig | LatencyDomainConfig | WeightedDomainConfig | GeoLocationDomainConfig;
|
|
123
|
+
/**
|
|
124
|
+
* A dependency on another container in the same task definition.
|
|
125
|
+
* Maps directly to ECS `ContainerDependency`. See `ContainerDependency` in
|
|
126
|
+
* the factory layer (`computeEcsTypes.ts`) for the public-facing variant.
|
|
127
|
+
*
|
|
128
|
+
* @internal
|
|
129
|
+
*/
|
|
130
|
+
export interface EcsContainerDependency {
|
|
131
|
+
container: string;
|
|
132
|
+
condition: "START" | "COMPLETE" | "SUCCESS" | "HEALTHY";
|
|
133
|
+
}
|
|
72
134
|
/**
|
|
73
135
|
* Internal configuration for a container in a multi-container ECS task.
|
|
74
136
|
*
|
|
@@ -136,6 +198,32 @@ export interface EcsClusterContainerConfig {
|
|
|
136
198
|
retries?: number;
|
|
137
199
|
startPeriod?: number;
|
|
138
200
|
};
|
|
201
|
+
/**
|
|
202
|
+
* Containers in the same service that must reach a given state before this
|
|
203
|
+
* container starts. Resolved at synth time against the service's container names.
|
|
204
|
+
*/
|
|
205
|
+
dependsOn?: EcsContainerDependency[];
|
|
206
|
+
/**
|
|
207
|
+
* Multi-port containers (CDK `PortMapping[]`). Mutually exclusive with
|
|
208
|
+
* `port` — supplying both throws at synth (AC30).
|
|
209
|
+
*/
|
|
210
|
+
portMappings?: PortMapping[];
|
|
211
|
+
/**
|
|
212
|
+
* Host-bind volumes mounted into this container. Each entry produces a
|
|
213
|
+
* matching `taskDefinition.addVolume(...)` + `container.addMountPoints(...)`
|
|
214
|
+
* pair (AC31).
|
|
215
|
+
*/
|
|
216
|
+
volumes?: Array<{
|
|
217
|
+
name: string;
|
|
218
|
+
hostSourcePath?: string;
|
|
219
|
+
mountPath: string;
|
|
220
|
+
readOnly?: boolean;
|
|
221
|
+
}>;
|
|
222
|
+
/**
|
|
223
|
+
* Time (seconds) ECS waits for the container to exit gracefully after
|
|
224
|
+
* SIGTERM before sending SIGKILL. Range 1–120. Default: ECS default (30s).
|
|
225
|
+
*/
|
|
226
|
+
stopTimeout?: number;
|
|
139
227
|
}
|
|
140
228
|
/**
|
|
141
229
|
* Cluster-level configuration.
|
|
@@ -167,6 +255,12 @@ export interface EcsClusterClusterConfig {
|
|
|
167
255
|
* Only used when domain is specified.
|
|
168
256
|
*/
|
|
169
257
|
domainConfig?: DomainConfig;
|
|
258
|
+
/**
|
|
259
|
+
* Externally-supplied EC2 capacity security group. When provided, the ECS
|
|
260
|
+
* service factory uses this SG instead of constructing its own. Pre-resolved
|
|
261
|
+
* by the patterns layer (AC26 — `EcsClusterConfig.securityGroup`).
|
|
262
|
+
*/
|
|
263
|
+
securityGroup?: ISecurityGroup;
|
|
170
264
|
}
|
|
171
265
|
/**
|
|
172
266
|
* Routing configuration for path/host-based routing on the ALB.
|
|
@@ -206,11 +300,23 @@ export interface EcsServiceProps {
|
|
|
206
300
|
memoryLimitMiB?: number;
|
|
207
301
|
/** Desired number of tasks. Default: 2 */
|
|
208
302
|
desiredCount?: number;
|
|
209
|
-
/**
|
|
303
|
+
/**
|
|
304
|
+
* Scaling type (CPU or MEMORY). Omit to disable auto-scaling — no
|
|
305
|
+
* `ScalableTarget` is registered, and `minCapacity`/`maxCapacity` below have
|
|
306
|
+
* no effect. The `desiredCount: 0 + minCapacity > 0` validation throw still
|
|
307
|
+
* fires regardless, so operator-intent contradictions surface at synth even
|
|
308
|
+
* when scaling is disabled.
|
|
309
|
+
*/
|
|
210
310
|
scalingType?: ScalingType;
|
|
211
|
-
/**
|
|
311
|
+
/**
|
|
312
|
+
* Minimum number of tasks for auto-scaling. Default: tracks `desiredCount`.
|
|
313
|
+
* Only consulted when `scalingType` is set.
|
|
314
|
+
*/
|
|
212
315
|
minCapacity?: number;
|
|
213
|
-
/**
|
|
316
|
+
/**
|
|
317
|
+
* Maximum number of tasks for auto-scaling. Default: `Math.max(desiredCount + 1, 3)`.
|
|
318
|
+
* Only consulted when `scalingType` is set.
|
|
319
|
+
*/
|
|
214
320
|
maxCapacity?: number;
|
|
215
321
|
/**
|
|
216
322
|
* Routing rules for this service on the cluster's ALB.
|
|
@@ -277,14 +383,11 @@ export interface EcsServiceProps {
|
|
|
277
383
|
*/
|
|
278
384
|
ssmSecretsPath?: string;
|
|
279
385
|
/**
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
* @example
|
|
284
|
-
* // With dockerTarget: "api", image tag becomes: myservice-api-latest
|
|
285
|
-
* dockerTarget: "api"
|
|
386
|
+
* Dockerfile build configuration for this service. When `target` is set,
|
|
387
|
+
* the image tag suffix becomes `<service>-<target>-latest`.
|
|
388
|
+
* Mutually exclusive with `image` (pre-built URI).
|
|
286
389
|
*/
|
|
287
|
-
|
|
390
|
+
docker?: DockerBuild;
|
|
288
391
|
/**
|
|
289
392
|
* Per-service alarm configuration.
|
|
290
393
|
* - undefined: use defaults (CPU, memory, running tasks, 5xx if ALB)
|
|
@@ -292,6 +395,63 @@ export interface EcsServiceProps {
|
|
|
292
395
|
* - object: override specific thresholds
|
|
293
396
|
*/
|
|
294
397
|
alarms?: EcsServiceAlarmThresholds | false;
|
|
398
|
+
/**
|
|
399
|
+
* Deployment circuit breaker policy.
|
|
400
|
+
* - undefined (default): `{ enable: true, rollback: true }`
|
|
401
|
+
* - `false`: disabled entirely (no breaker)
|
|
402
|
+
* - `{ rollback: boolean }`: override rollback behaviour
|
|
403
|
+
*
|
|
404
|
+
* @see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/deployment-circuit-breaker.html
|
|
405
|
+
*/
|
|
406
|
+
circuitBreaker?: false | {
|
|
407
|
+
rollback?: boolean;
|
|
408
|
+
};
|
|
409
|
+
/**
|
|
410
|
+
* Rolling-deploy capacity bounds. Overrides the default
|
|
411
|
+
* `{ minHealthyPercent: 100, maxHealthyPercent: 200 }`. Singletons backed
|
|
412
|
+
* by an EBS volume that only one task can attach to (e.g. ClickHouse) need
|
|
413
|
+
* `{ minHealthyPercent: 0, maxHealthyPercent: 100 }` so the old task
|
|
414
|
+
* detaches before the new one starts.
|
|
415
|
+
*
|
|
416
|
+
* Bounds enforced by `validateEcsClusterProps`: `minHealthyPercent` must be
|
|
417
|
+
* 0–100, `maxHealthyPercent` must be 100–200, and the two cannot both be
|
|
418
|
+
* `100` (no capacity to drain or expand — deploys would never roll forward).
|
|
419
|
+
*/
|
|
420
|
+
deployment?: {
|
|
421
|
+
minHealthyPercent?: number;
|
|
422
|
+
maxHealthyPercent?: number;
|
|
423
|
+
};
|
|
424
|
+
/**
|
|
425
|
+
* Pre-registered Cloud Map service. When provided, the underlying
|
|
426
|
+
* `Ec2Service`/`FargateService` calls `associateCloudMapService(...)` after
|
|
427
|
+
* construction. The patterns layer registers the service via
|
|
428
|
+
* `app.getNamespace().registerService({ name })` and threads the resulting
|
|
429
|
+
* `IService` here — keeping the resources layer free of namespace lookup.
|
|
430
|
+
*/
|
|
431
|
+
cloudMapService?: IService;
|
|
432
|
+
/**
|
|
433
|
+
* DNS record type registered against `cloudMapService`. Default: `"A"`
|
|
434
|
+
* (matches CDK's default and works under `awsvpc`). Set to `"SRV"` when
|
|
435
|
+
* the service runs under `host` or `bridge` network mode — CDK's
|
|
436
|
+
* `Ec2Service.associateCloudMapService(...)` rejects A records there and
|
|
437
|
+
* requires `containerName` + `containerPort`, derived from the primary
|
|
438
|
+
* container.
|
|
439
|
+
*/
|
|
440
|
+
cloudMapDnsRecordType?: "A" | "SRV";
|
|
441
|
+
/**
|
|
442
|
+
* Override the task definition's `NetworkMode`. Default for EC2 services
|
|
443
|
+
* is `AWS_VPC` (or `HOST` when `cluster.directAccess`); set to `BRIDGE`
|
|
444
|
+
* for dynamic-port-mapping ALB integration or when ENI quota is a concern.
|
|
445
|
+
*/
|
|
446
|
+
networkMode?: NetworkMode;
|
|
447
|
+
/**
|
|
448
|
+
* Pre-existing security groups to attach to the service's task ENIs (AWS_VPC
|
|
449
|
+
* mode) instead of letting CDK auto-generate a default service SG. Used by
|
|
450
|
+
* stateful consumers (e.g. `ClickHouseDatabase`) that own a wrapper SG and
|
|
451
|
+
* need `this.connections.securityGroups[0]` to be the SG actually arbitrating
|
|
452
|
+
* inbound traffic to the task. Empty/omitted → CDK auto-creates one.
|
|
453
|
+
*/
|
|
454
|
+
securityGroups?: ISecurityGroup[];
|
|
295
455
|
}
|
|
296
456
|
/**
|
|
297
457
|
* Props for creating an ECS cluster with multiple services.
|
|
@@ -3,6 +3,15 @@ import type { EcsClusterProps } from "./ecsTypes.js";
|
|
|
3
3
|
* Validates ECS cluster props before construction.
|
|
4
4
|
* Pure function — does not depend on class state.
|
|
5
5
|
*
|
|
6
|
+
* Note: `service.migrations` and `service.migrations.separateTaskDef` are
|
|
7
|
+
* intentionally validated only at the patterns layer (`validateEcsProps`
|
|
8
|
+
* in `lib/patterns/aws/computeEcs.ts`). The migrations sugar is a
|
|
9
|
+
* patterns-layer concept — it is translated into `service.containers`
|
|
10
|
+
* (init-container mode) or a separate Fargate task definition + lifecycle
|
|
11
|
+
* hook (lifecycle-hook mode) BEFORE reaching `EcsClusterProps`. Resources-
|
|
12
|
+
* layer consumers never see a `migrations` field, so duplicating the
|
|
13
|
+
* validation here would be unreachable.
|
|
14
|
+
*
|
|
6
15
|
* @param props - The cluster props to validate
|
|
7
16
|
* @throws Error if validation fails
|
|
8
17
|
*/
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
import { NetworkMode } from "aws-cdk-lib/aws-ecs";
|
|
1
2
|
/**
|
|
2
3
|
* Validates ECS cluster props before construction.
|
|
3
4
|
* Pure function — does not depend on class state.
|
|
4
5
|
*
|
|
6
|
+
* Note: `service.migrations` and `service.migrations.separateTaskDef` are
|
|
7
|
+
* intentionally validated only at the patterns layer (`validateEcsProps`
|
|
8
|
+
* in `lib/patterns/aws/computeEcs.ts`). The migrations sugar is a
|
|
9
|
+
* patterns-layer concept — it is translated into `service.containers`
|
|
10
|
+
* (init-container mode) or a separate Fargate task definition + lifecycle
|
|
11
|
+
* hook (lifecycle-hook mode) BEFORE reaching `EcsClusterProps`. Resources-
|
|
12
|
+
* layer consumers never see a `migrations` field, so duplicating the
|
|
13
|
+
* validation here would be unreachable.
|
|
14
|
+
*
|
|
5
15
|
* @param props - The cluster props to validate
|
|
6
16
|
* @throws Error if validation fails
|
|
7
17
|
*/
|
|
@@ -47,6 +57,59 @@ export function validateEcsClusterProps(props) {
|
|
|
47
57
|
throw new Error(`Service '${service.name}': Duplicate container names: ` +
|
|
48
58
|
`${[...new Set(duplicateContainers)].join(", ")}`);
|
|
49
59
|
}
|
|
60
|
+
for (const container of service.containers) {
|
|
61
|
+
if (container.stopTimeout !== undefined) {
|
|
62
|
+
if (!Number.isInteger(container.stopTimeout) ||
|
|
63
|
+
container.stopTimeout < 1 ||
|
|
64
|
+
container.stopTimeout > 120) {
|
|
65
|
+
throw new Error(`Service '${service.name}', container '${container.name ?? "(default)"}': ` +
|
|
66
|
+
`stopTimeout must be an integer between 1 and 120 seconds (got ${container.stopTimeout}).`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (service.capacityProvider === "EC2" && !service.ec2Config) {
|
|
71
|
+
throw new Error(`Service '${service.name}' uses EC2 capacity provider but no ec2Config is defined. ` +
|
|
72
|
+
"Provide ec2Config on the service.");
|
|
73
|
+
}
|
|
74
|
+
if (service.deployment !== undefined) {
|
|
75
|
+
const min = service.deployment.minHealthyPercent;
|
|
76
|
+
const max = service.deployment.maxHealthyPercent;
|
|
77
|
+
if (min !== undefined && (min < 0 || min > 100)) {
|
|
78
|
+
throw new Error(`Service '${service.name}': deployment.minHealthyPercent must be between 0 and 100 (got ${min}).`);
|
|
79
|
+
}
|
|
80
|
+
if (max !== undefined && (max < 100 || max > 200)) {
|
|
81
|
+
throw new Error(`Service '${service.name}': deployment.maxHealthyPercent must be between 100 and 200 (got ${max}).`);
|
|
82
|
+
}
|
|
83
|
+
if (min === 100 && max === 100) {
|
|
84
|
+
throw new Error(`Service '${service.name}': deployment.minHealthyPercent and maxHealthyPercent cannot both be 100 ` +
|
|
85
|
+
"(no capacity to drain or expand — deploys would never roll forward).");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (service.cloudMapDnsRecordType !== undefined &&
|
|
89
|
+
service.cloudMapService === undefined) {
|
|
90
|
+
throw new Error(`Service '${service.name}': cloudMapDnsRecordType is set but cloudMapService is not. ` +
|
|
91
|
+
"Service discovery cannot be registered without a Cloud Map namespace.");
|
|
92
|
+
}
|
|
93
|
+
if (service.desiredCount === 0 &&
|
|
94
|
+
service.minCapacity !== undefined &&
|
|
95
|
+
service.minCapacity > 0) {
|
|
96
|
+
throw new Error(`Service '${service.name}': scaling.minCapacity (${service.minCapacity}) cannot exceed desiredCount when desiredCount is 0. ` +
|
|
97
|
+
"Application Auto Scaling would immediately scale the service back up, defeating the desiredCount: 0 toggle. " +
|
|
98
|
+
"Either set scaling.minCapacity to 0 (placeholder service) or raise desiredCount to match scaling.minCapacity.");
|
|
99
|
+
}
|
|
100
|
+
if (service.capacityProvider === "EC2" &&
|
|
101
|
+
service.securityGroups !== undefined &&
|
|
102
|
+
service.securityGroups.length > 0) {
|
|
103
|
+
const directAccessForceHost = props.cluster?.directAccess === true;
|
|
104
|
+
const effectiveMode = service.networkMode ??
|
|
105
|
+
(directAccessForceHost ? NetworkMode.HOST : NetworkMode.AWS_VPC);
|
|
106
|
+
if (effectiveMode !== NetworkMode.AWS_VPC) {
|
|
107
|
+
throw new Error(`Service '${service.name}': securityGroups is only valid with networkMode AWS_VPC ` +
|
|
108
|
+
`(effective networkMode is '${effectiveMode}'). HOST/BRIDGE services share ` +
|
|
109
|
+
`the EC2 instance ENI, which is governed by the cluster-level securityGroup ` +
|
|
110
|
+
`on EcsClusterConfig.`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
50
113
|
}
|
|
51
114
|
}
|
|
52
115
|
/**
|
|
@@ -2,7 +2,7 @@ import { SingletonFunction as singletonFunction, Function, Code, type Runtime, A
|
|
|
2
2
|
import { type Bucket } from "aws-cdk-lib/aws-s3";
|
|
3
3
|
import { PolicyStatement, type IRole } from "aws-cdk-lib/aws-iam";
|
|
4
4
|
import { type IVpc } from "aws-cdk-lib/aws-ec2";
|
|
5
|
-
import {
|
|
5
|
+
import { RetentionDays } from "aws-cdk-lib/aws-logs";
|
|
6
6
|
import { type IQueue } from "aws-cdk-lib/aws-sqs";
|
|
7
7
|
import { type ITable } from "aws-cdk-lib/aws-dynamodb";
|
|
8
8
|
import { type Construct } from "constructs";
|
|
@@ -23,6 +23,12 @@ export interface LambdaFunctionProps {
|
|
|
23
23
|
memorySize?: number;
|
|
24
24
|
/** Ephemeral storage size in MiB */
|
|
25
25
|
ephemeralStorageSize?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Log retention for the auto-created LogGroup. Defaults to one week.
|
|
28
|
+
* Override for Lambdas whose logs back operational debugging beyond the
|
|
29
|
+
* default window (e.g. deployment lifecycle hooks).
|
|
30
|
+
*/
|
|
31
|
+
logGroupRetention?: RetentionDays;
|
|
26
32
|
inlinePolicy: PolicyStatement[];
|
|
27
33
|
enableFunctionUrl?: boolean;
|
|
28
34
|
functionUrlAuthType?: FunctionUrlAuthType;
|
|
@@ -30,8 +36,6 @@ export interface LambdaFunctionProps {
|
|
|
30
36
|
/** Invoke mode for Function URL. Use RESPONSE_STREAM for Lambda streaming. */
|
|
31
37
|
functionUrlInvokeMode?: InvokeMode;
|
|
32
38
|
environment?: KeyValue;
|
|
33
|
-
tags?: KeyValue;
|
|
34
|
-
scheduleExpression?: string;
|
|
35
39
|
secrets?: string[];
|
|
36
40
|
ssmSecretsPath?: string;
|
|
37
41
|
secretsImport?: Record<string, SecretImport>;
|
|
@@ -100,16 +104,6 @@ export declare class LambdaFunction extends Function {
|
|
|
100
104
|
suffix?: string;
|
|
101
105
|
}>;
|
|
102
106
|
}): void;
|
|
103
|
-
/**
|
|
104
|
-
* Add an EventBridge rule as an event source for this Lambda function.
|
|
105
|
-
* This will trigger the Lambda when events matching the pattern are published.
|
|
106
|
-
* Useful for scheduled jobs, cross-service event handling, and custom event patterns.
|
|
107
|
-
*/
|
|
108
|
-
addEventBridgeEventSource(ruleId: string, options: {
|
|
109
|
-
schedule?: string;
|
|
110
|
-
eventPattern?: EventPattern;
|
|
111
|
-
description?: string;
|
|
112
|
-
}): Rule;
|
|
113
107
|
/**
|
|
114
108
|
* Add secrets support using AWS Parameters and Secrets Lambda Extension.
|
|
115
109
|
*
|