cdk-factory 0.15.10__py3-none-any.whl → 0.18.9__py3-none-any.whl
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.
Potentially problematic release.
This version of cdk-factory might be problematic. Click here for more details.
- cdk_factory/configurations/base_config.py +23 -24
- cdk_factory/configurations/cdk_config.py +6 -4
- cdk_factory/configurations/deployment.py +12 -0
- cdk_factory/configurations/devops.py +1 -1
- cdk_factory/configurations/pipeline_stage.py +29 -5
- cdk_factory/configurations/resources/acm.py +85 -0
- cdk_factory/configurations/resources/auto_scaling.py +7 -5
- cdk_factory/configurations/resources/cloudfront.py +7 -2
- cdk_factory/configurations/resources/ecr.py +1 -1
- cdk_factory/configurations/resources/ecs_cluster.py +108 -0
- cdk_factory/configurations/resources/ecs_service.py +17 -2
- cdk_factory/configurations/resources/load_balancer.py +17 -4
- cdk_factory/configurations/resources/monitoring.py +8 -3
- cdk_factory/configurations/resources/rds.py +305 -19
- cdk_factory/configurations/resources/rum.py +7 -2
- cdk_factory/configurations/resources/s3.py +1 -1
- cdk_factory/configurations/resources/security_group_full_stack.py +7 -8
- cdk_factory/configurations/resources/vpc.py +19 -0
- cdk_factory/configurations/workload.py +32 -2
- cdk_factory/constructs/ecr/ecr_construct.py +9 -2
- cdk_factory/constructs/lambdas/policies/policy_docs.py +4 -4
- cdk_factory/interfaces/istack.py +6 -3
- cdk_factory/interfaces/networked_stack_mixin.py +75 -0
- cdk_factory/interfaces/standardized_ssm_mixin.py +657 -0
- cdk_factory/interfaces/vpc_provider_mixin.py +210 -0
- cdk_factory/lambdas/edge/ip_gate/handler.py +42 -40
- cdk_factory/pipeline/pipeline_factory.py +222 -27
- cdk_factory/stack/stack_factory.py +34 -0
- cdk_factory/stack_library/__init__.py +3 -2
- cdk_factory/stack_library/acm/__init__.py +6 -0
- cdk_factory/stack_library/acm/acm_stack.py +169 -0
- cdk_factory/stack_library/api_gateway/api_gateway_stack.py +84 -59
- cdk_factory/stack_library/auto_scaling/auto_scaling_stack.py +366 -408
- cdk_factory/stack_library/code_artifact/code_artifact_stack.py +2 -2
- cdk_factory/stack_library/cognito/cognito_stack.py +152 -92
- cdk_factory/stack_library/dynamodb/dynamodb_stack.py +19 -15
- cdk_factory/stack_library/ecr/ecr_stack.py +2 -2
- cdk_factory/stack_library/ecs/__init__.py +12 -0
- cdk_factory/stack_library/ecs/ecs_cluster_stack.py +316 -0
- cdk_factory/stack_library/ecs/ecs_service_stack.py +20 -39
- cdk_factory/stack_library/lambda_edge/lambda_edge_stack.py +2 -2
- cdk_factory/stack_library/load_balancer/load_balancer_stack.py +151 -118
- cdk_factory/stack_library/rds/rds_stack.py +85 -74
- cdk_factory/stack_library/route53/route53_stack.py +8 -3
- cdk_factory/stack_library/rum/rum_stack.py +108 -91
- cdk_factory/stack_library/security_group/security_group_full_stack.py +9 -22
- cdk_factory/stack_library/security_group/security_group_stack.py +11 -11
- cdk_factory/stack_library/stack_base.py +5 -0
- cdk_factory/stack_library/vpc/vpc_stack.py +272 -124
- cdk_factory/stack_library/websites/static_website_stack.py +1 -1
- cdk_factory/utilities/api_gateway_integration_utility.py +24 -16
- cdk_factory/utilities/environment_services.py +5 -5
- cdk_factory/utilities/json_loading_utility.py +12 -3
- cdk_factory/validation/config_validator.py +483 -0
- cdk_factory/version.py +1 -1
- cdk_factory/workload/workload_factory.py +1 -0
- {cdk_factory-0.15.10.dist-info → cdk_factory-0.18.9.dist-info}/METADATA +1 -1
- {cdk_factory-0.15.10.dist-info → cdk_factory-0.18.9.dist-info}/RECORD +61 -54
- cdk_factory/interfaces/enhanced_ssm_parameter_mixin.py +0 -321
- cdk_factory/interfaces/ssm_parameter_mixin.py +0 -329
- {cdk_factory-0.15.10.dist-info → cdk_factory-0.18.9.dist-info}/WHEEL +0 -0
- {cdk_factory-0.15.10.dist-info → cdk_factory-0.18.9.dist-info}/entry_points.txt +0 -0
- {cdk_factory-0.15.10.dist-info → cdk_factory-0.18.9.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ECS Cluster Stack Module (Standardized SSM Version)
|
|
3
|
+
|
|
4
|
+
Provides a dedicated stack for creating and configuring ECS clusters
|
|
5
|
+
with proper configurability, explicit resource management, and standardized SSM integration.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Optional, Dict, Any
|
|
10
|
+
|
|
11
|
+
from aws_cdk import (
|
|
12
|
+
aws_ecs as ecs,
|
|
13
|
+
aws_ec2 as ec2,
|
|
14
|
+
aws_iam as iam,
|
|
15
|
+
CfnOutput,
|
|
16
|
+
)
|
|
17
|
+
from constructs import Construct
|
|
18
|
+
|
|
19
|
+
from cdk_factory.configurations.stack import StackConfig
|
|
20
|
+
from cdk_factory.configurations.deployment import DeploymentConfig
|
|
21
|
+
from cdk_factory.configurations.workload import WorkloadConfig
|
|
22
|
+
from cdk_factory.interfaces.vpc_provider_mixin import VPCProviderMixin
|
|
23
|
+
from cdk_factory.interfaces.standardized_ssm_mixin import StandardizedSsmMixin
|
|
24
|
+
from cdk_factory.configurations.resources.ecs_cluster import EcsClusterConfig
|
|
25
|
+
from cdk_factory.stack.stack_module_registry import register_stack
|
|
26
|
+
from cdk_factory.interfaces.istack import IStack
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@register_stack("ecs_cluster_stack")
|
|
32
|
+
class EcsClusterStack(IStack, VPCProviderMixin, StandardizedSsmMixin):
|
|
33
|
+
"""
|
|
34
|
+
A dedicated stack for creating and managing ECS clusters with standardized SSM integration.
|
|
35
|
+
|
|
36
|
+
This stack provides explicit configuration of ECS clusters including:
|
|
37
|
+
- Cluster naming
|
|
38
|
+
- Container insights
|
|
39
|
+
- Cluster settings
|
|
40
|
+
- Standardized SSM parameter exports
|
|
41
|
+
- IAM role configurations
|
|
42
|
+
- Template variable resolution
|
|
43
|
+
- Comprehensive validation
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(self, scope: Construct, id: str, **kwargs) -> None:
|
|
47
|
+
"""
|
|
48
|
+
Initialize the ECS Cluster stack.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
scope: The CDK construct scope
|
|
52
|
+
id: The construct ID
|
|
53
|
+
"""
|
|
54
|
+
super().__init__(scope, id, **kwargs)
|
|
55
|
+
|
|
56
|
+
self._initialize_vpc_cache()
|
|
57
|
+
|
|
58
|
+
self.ecs_config: Optional[EcsClusterConfig] = None
|
|
59
|
+
self.stack_config: Optional[StackConfig] = None
|
|
60
|
+
self.deployment: Optional[DeploymentConfig] = None
|
|
61
|
+
self.workload: Optional[WorkloadConfig] = None
|
|
62
|
+
self.ecs_cluster: Optional[ecs.Cluster] = None
|
|
63
|
+
self.instance_role: Optional[iam.Role] = None
|
|
64
|
+
self.instance_profile: Optional[iam.CfnInstanceProfile] = None
|
|
65
|
+
|
|
66
|
+
def build(
|
|
67
|
+
self,
|
|
68
|
+
stack_config: StackConfig,
|
|
69
|
+
deployment: DeploymentConfig,
|
|
70
|
+
workload: WorkloadConfig,
|
|
71
|
+
) -> None:
|
|
72
|
+
"""Build the ECS Cluster stack"""
|
|
73
|
+
self._build(stack_config, deployment, workload)
|
|
74
|
+
|
|
75
|
+
def _build(
|
|
76
|
+
self,
|
|
77
|
+
stack_config: StackConfig,
|
|
78
|
+
deployment: DeploymentConfig,
|
|
79
|
+
workload: WorkloadConfig,
|
|
80
|
+
) -> None:
|
|
81
|
+
"""Internal build method for the ECS Cluster stack"""
|
|
82
|
+
self.stack_config = stack_config
|
|
83
|
+
self.deployment = deployment
|
|
84
|
+
self.workload = workload
|
|
85
|
+
|
|
86
|
+
# Initialize VPC cache from mixin
|
|
87
|
+
self._initialize_vpc_cache()
|
|
88
|
+
|
|
89
|
+
# Load ECS cluster configuration with full stack config for SSM access
|
|
90
|
+
ecs_cluster_dict = stack_config.dictionary.get("ecs_cluster", {})
|
|
91
|
+
# Merge SSM config from root level into ECS config for VPC resolution
|
|
92
|
+
if "ssm" in stack_config.dictionary:
|
|
93
|
+
ecs_cluster_dict["ssm"] = stack_config.dictionary["ssm"]
|
|
94
|
+
|
|
95
|
+
self.ecs_config: EcsClusterConfig = EcsClusterConfig(ecs_cluster_dict)
|
|
96
|
+
|
|
97
|
+
cluster_name = deployment.build_resource_name(self.ecs_config.name)
|
|
98
|
+
|
|
99
|
+
logger.info(f"Creating ECS Cluster stack: {cluster_name}")
|
|
100
|
+
|
|
101
|
+
# Setup standardized SSM integration
|
|
102
|
+
self.setup_ssm_integration(
|
|
103
|
+
scope=self,
|
|
104
|
+
config=self.ecs_config,
|
|
105
|
+
resource_type="ecs_cluster",
|
|
106
|
+
resource_name=cluster_name,
|
|
107
|
+
deployment=deployment,
|
|
108
|
+
workload=workload
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
# Process SSM imports using standardized method
|
|
112
|
+
self.process_ssm_imports()
|
|
113
|
+
|
|
114
|
+
# Create the ECS cluster
|
|
115
|
+
self._create_ecs_cluster()
|
|
116
|
+
|
|
117
|
+
# Create IAM roles if needed
|
|
118
|
+
self._create_iam_roles()
|
|
119
|
+
|
|
120
|
+
# Export cluster information
|
|
121
|
+
self._export_cluster_info()
|
|
122
|
+
|
|
123
|
+
# Export SSM parameters
|
|
124
|
+
logger.info("Starting SSM parameter export for ECS cluster")
|
|
125
|
+
self._export_ssm_parameters()
|
|
126
|
+
logger.info("Completed SSM parameter export for ECS cluster")
|
|
127
|
+
|
|
128
|
+
logger.info(f"ECS Cluster stack created: {cluster_name}")
|
|
129
|
+
|
|
130
|
+
def _create_ecs_cluster(self):
|
|
131
|
+
"""Create the ECS cluster with explicit configuration."""
|
|
132
|
+
logger.info(f"Creating ECS cluster: {self.ecs_config.name}")
|
|
133
|
+
|
|
134
|
+
# Build cluster settings
|
|
135
|
+
cluster_settings = []
|
|
136
|
+
|
|
137
|
+
# Add container insights if enabled
|
|
138
|
+
if self.ecs_config.container_insights:
|
|
139
|
+
cluster_settings.append({"name": "containerInsights", "value": "enabled"})
|
|
140
|
+
|
|
141
|
+
# Add custom cluster settings
|
|
142
|
+
if self.ecs_config.cluster_settings:
|
|
143
|
+
cluster_settings.extend(self.ecs_config.cluster_settings)
|
|
144
|
+
|
|
145
|
+
# Get VPC using standardized approach
|
|
146
|
+
self.vpc = self._get_vpc()
|
|
147
|
+
|
|
148
|
+
# Create the ECS cluster
|
|
149
|
+
self.ecs_cluster = ecs.Cluster(
|
|
150
|
+
self,
|
|
151
|
+
"ECSCluster",
|
|
152
|
+
cluster_name=self.ecs_config.name,
|
|
153
|
+
vpc=self.vpc,
|
|
154
|
+
container_insights=self.ecs_config.container_insights,
|
|
155
|
+
default_cloud_map_namespace=(
|
|
156
|
+
self.ecs_config.cloud_map_namespace
|
|
157
|
+
if self.ecs_config.cloud_map_namespace
|
|
158
|
+
else None
|
|
159
|
+
),
|
|
160
|
+
execute_command_configuration=(
|
|
161
|
+
self.ecs_config.execute_command_configuration
|
|
162
|
+
if self.ecs_config.execute_command_configuration
|
|
163
|
+
else None
|
|
164
|
+
),
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
logger.info(f"ECS cluster created: {self.ecs_config.name}")
|
|
168
|
+
|
|
169
|
+
def _get_vpc(self):
|
|
170
|
+
"""
|
|
171
|
+
Get VPC using the centralized VPC provider mixin.
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
# Use the stack_config (not ecs_config) to ensure SSM imports are available
|
|
175
|
+
return self.resolve_vpc(
|
|
176
|
+
config=self.ecs_config,
|
|
177
|
+
deployment=self.deployment,
|
|
178
|
+
workload=self.workload
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
def _create_iam_roles(self):
|
|
182
|
+
"""Create IAM roles for the ECS cluster if configured."""
|
|
183
|
+
logger.info(f"create_instance_role setting: {self.ecs_config.create_instance_role}")
|
|
184
|
+
|
|
185
|
+
if not self.ecs_config.create_instance_role:
|
|
186
|
+
logger.info("Skipping instance role creation (disabled in config)")
|
|
187
|
+
return
|
|
188
|
+
|
|
189
|
+
logger.info("Creating ECS instance role")
|
|
190
|
+
|
|
191
|
+
# Create the instance role
|
|
192
|
+
self.instance_role = iam.Role(
|
|
193
|
+
self,
|
|
194
|
+
"ECSInstanceRole",
|
|
195
|
+
assumed_by=iam.ServicePrincipal("ec2.amazonaws.com"),
|
|
196
|
+
managed_policies=[
|
|
197
|
+
iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AmazonEC2ContainerServiceforEC2Role"),
|
|
198
|
+
iam.ManagedPolicy.from_aws_managed_policy_name("AmazonEC2ContainerRegistryReadOnly"),
|
|
199
|
+
iam.ManagedPolicy.from_aws_managed_policy_name("AmazonSSMManagedInstanceCore"),
|
|
200
|
+
],
|
|
201
|
+
role_name=f"{self.ecs_config.name}-ecs-instance-role",
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
logger.info(f"Created ECS instance role: {self.instance_role.role_name}")
|
|
205
|
+
|
|
206
|
+
# Create instance profile
|
|
207
|
+
self.instance_profile = iam.CfnInstanceProfile(
|
|
208
|
+
self,
|
|
209
|
+
"ECSInstanceProfile",
|
|
210
|
+
instance_profile_name=f"{self.ecs_config.name}-ecs-instance-profile",
|
|
211
|
+
roles=[self.instance_role.role_name],
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
logger.info(f"Created ECS instance profile: {self.instance_profile.instance_profile_name}")
|
|
215
|
+
|
|
216
|
+
logger.info("ECS instance role and profile created")
|
|
217
|
+
|
|
218
|
+
def _export_cluster_info(self):
|
|
219
|
+
"""Export cluster information as CloudFormation outputs."""
|
|
220
|
+
if not self.ecs_cluster:
|
|
221
|
+
return
|
|
222
|
+
|
|
223
|
+
cluster_name = self.deployment.build_resource_name(self.ecs_config.name)
|
|
224
|
+
|
|
225
|
+
# Export cluster name
|
|
226
|
+
CfnOutput(
|
|
227
|
+
self,
|
|
228
|
+
f"{cluster_name}-ClusterName",
|
|
229
|
+
value=self.ecs_cluster.cluster_name,
|
|
230
|
+
description=f"ECS Cluster Name for {cluster_name}",
|
|
231
|
+
export_name=f"{self.deployment.workload_name}-{self.deployment.environment}-ecs-cluster-name",
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# Export cluster ARN
|
|
235
|
+
CfnOutput(
|
|
236
|
+
self,
|
|
237
|
+
f"{cluster_name}-ClusterArn",
|
|
238
|
+
value=self.ecs_cluster.cluster_arn,
|
|
239
|
+
description=f"ECS Cluster ARN for {cluster_name}",
|
|
240
|
+
export_name=f"{self.deployment.workload_name}-{self.deployment.environment}-ecs-cluster-arn",
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# Export security group if available
|
|
244
|
+
if hasattr(self.ecs_cluster, 'connections') and self.ecs_cluster.connections:
|
|
245
|
+
security_groups = self.ecs_cluster.connections.security_groups
|
|
246
|
+
if security_groups:
|
|
247
|
+
CfnOutput(
|
|
248
|
+
self,
|
|
249
|
+
f"{cluster_name}-SecurityGroupId",
|
|
250
|
+
value=security_groups[0].security_group_id,
|
|
251
|
+
description=f"ECS Cluster Security Group ID for {cluster_name}",
|
|
252
|
+
export_name=f"{self.deployment.workload_name}-{self.deployment.environment}-ecs-cluster-sg-id",
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
# Export instance profile if created
|
|
256
|
+
if self.instance_profile:
|
|
257
|
+
CfnOutput(
|
|
258
|
+
self,
|
|
259
|
+
f"{cluster_name}-InstanceProfileArn",
|
|
260
|
+
value=self.instance_profile.attr_arn,
|
|
261
|
+
description=f"ECS Instance Profile ARN for {cluster_name}",
|
|
262
|
+
export_name=f"{self.deployment.workload_name}-{self.deployment.environment}-ecs-instance-profile-arn",
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
logger.info("ECS cluster information exported as outputs")
|
|
266
|
+
|
|
267
|
+
def _export_ssm_parameters(self) -> None:
|
|
268
|
+
"""Export SSM parameters using standardized approach"""
|
|
269
|
+
logger.info("=== Starting SSM Parameter Export ===")
|
|
270
|
+
|
|
271
|
+
if not self.ecs_cluster:
|
|
272
|
+
logger.warning("No ECS cluster to export")
|
|
273
|
+
return
|
|
274
|
+
|
|
275
|
+
logger.info(f"ECS cluster found: {self.ecs_cluster.cluster_name}")
|
|
276
|
+
logger.info(f"SSM exports configured: {self.ssm_config.get('exports', {})}")
|
|
277
|
+
|
|
278
|
+
# Prepare resource values for export
|
|
279
|
+
resource_values = {
|
|
280
|
+
"cluster_name": self.ecs_cluster.cluster_name,
|
|
281
|
+
"cluster_arn": self.ecs_cluster.cluster_arn,
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
# Add instance role ARN if created
|
|
285
|
+
if self.instance_role:
|
|
286
|
+
resource_values["instance_role_arn"] = self.instance_role.role_arn
|
|
287
|
+
logger.info(f"Instance role ARN added: {self.instance_role.role_name}")
|
|
288
|
+
else:
|
|
289
|
+
logger.info("No instance role to export")
|
|
290
|
+
|
|
291
|
+
# Add security group ID if available
|
|
292
|
+
if hasattr(self.ecs_cluster, 'connections') and self.ecs_cluster.connections:
|
|
293
|
+
security_groups = self.ecs_cluster.connections.security_groups
|
|
294
|
+
if security_groups:
|
|
295
|
+
resource_values["security_group_id"] = security_groups[0].security_group_id
|
|
296
|
+
logger.info(f"Security group ID added: {security_groups[0].security_group_id}")
|
|
297
|
+
|
|
298
|
+
# Add instance profile ARN if created
|
|
299
|
+
if self.instance_profile:
|
|
300
|
+
resource_values["instance_profile_arn"] = self.instance_profile.attr_arn
|
|
301
|
+
logger.info(f"Instance profile ARN added: {self.instance_profile.instance_profile_name}")
|
|
302
|
+
|
|
303
|
+
# Export using standardized SSM mixin
|
|
304
|
+
logger.info(f"Resource values available for export: {list(resource_values.keys())}")
|
|
305
|
+
for key, value in resource_values.items():
|
|
306
|
+
logger.info(f" {key}: {value}")
|
|
307
|
+
|
|
308
|
+
try:
|
|
309
|
+
exported_params = self.export_ssm_parameters(resource_values)
|
|
310
|
+
logger.info(f"Successfully exported SSM parameters: {exported_params}")
|
|
311
|
+
except Exception as e:
|
|
312
|
+
logger.error(f"Failed to export SSM parameters: {str(e)}")
|
|
313
|
+
raise
|
|
314
|
+
|
|
315
|
+
# Backward compatibility alias
|
|
316
|
+
EcsClusterStackStandardized = EcsClusterStack
|
|
@@ -23,7 +23,8 @@ from cdk_factory.configurations.deployment import DeploymentConfig
|
|
|
23
23
|
from cdk_factory.configurations.stack import StackConfig
|
|
24
24
|
from cdk_factory.configurations.resources.ecs_service import EcsServiceConfig
|
|
25
25
|
from cdk_factory.interfaces.istack import IStack
|
|
26
|
-
from cdk_factory.interfaces.
|
|
26
|
+
from cdk_factory.interfaces.vpc_provider_mixin import VPCProviderMixin
|
|
27
|
+
from cdk_factory.interfaces.standardized_ssm_mixin import StandardizedSsmMixin
|
|
27
28
|
from cdk_factory.stack.stack_module_registry import register_stack
|
|
28
29
|
from cdk_factory.workload.workload_factory import WorkloadConfig
|
|
29
30
|
|
|
@@ -33,7 +34,7 @@ logger = Logger(service="EcsServiceStack")
|
|
|
33
34
|
@register_stack("ecs_service_library_module")
|
|
34
35
|
@register_stack("ecs_service_stack")
|
|
35
36
|
@register_stack("fargate_service_stack")
|
|
36
|
-
class EcsServiceStack(IStack,
|
|
37
|
+
class EcsServiceStack(IStack, VPCProviderMixin, StandardizedSsmMixin):
|
|
37
38
|
"""
|
|
38
39
|
Reusable stack for ECS/Fargate services with Docker container support.
|
|
39
40
|
Supports blue-green deployments, maintenance mode, and auto-scaling.
|
|
@@ -47,7 +48,7 @@ class EcsServiceStack(IStack, EnhancedSsmParameterMixin):
|
|
|
47
48
|
self.workload: Optional[WorkloadConfig] = None
|
|
48
49
|
self.cluster: Optional[ecs.ICluster] = None
|
|
49
50
|
self.service: Optional[ecs.FargateService] = None
|
|
50
|
-
self.task_definition: Optional[ecs.FargateTaskDefinition] = None
|
|
51
|
+
self.task_definition: Optional[ecs.FargateTaskDefinition] | Optional[ecs.EcsTaskDefinition] = None
|
|
51
52
|
self._vpc: Optional[ec2.IVpc] = None
|
|
52
53
|
# SSM imported values
|
|
53
54
|
self.ssm_imported_values: Dict[str, Any] = {}
|
|
@@ -74,7 +75,7 @@ class EcsServiceStack(IStack, EnhancedSsmParameterMixin):
|
|
|
74
75
|
|
|
75
76
|
# Load ECS configuration
|
|
76
77
|
self.ecs_config = EcsServiceConfig(
|
|
77
|
-
stack_config.dictionary.get("ecs_service", {})
|
|
78
|
+
stack_config.dictionary.get("ecs_service") or stack_config.dictionary.get("ecs", {})
|
|
78
79
|
)
|
|
79
80
|
|
|
80
81
|
service_name = deployment.build_resource_name(self.ecs_config.name)
|
|
@@ -102,30 +103,13 @@ class EcsServiceStack(IStack, EnhancedSsmParameterMixin):
|
|
|
102
103
|
self._add_outputs(service_name)
|
|
103
104
|
|
|
104
105
|
def _load_vpc(self) -> None:
|
|
105
|
-
"""Load VPC
|
|
106
|
-
#
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
"vpc_id": vpc_id,
|
|
113
|
-
"availability_zones": ["us-east-1a", "us-east-1b"]
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
# Use from_vpc_attributes() for SSM tokens
|
|
117
|
-
self._vpc = ec2.Vpc.from_vpc_attributes(self, "VPC", **vpc_attrs)
|
|
118
|
-
else:
|
|
119
|
-
vpc_id = self.ecs_config.vpc_id or self.workload.vpc_id
|
|
120
|
-
|
|
121
|
-
if not vpc_id:
|
|
122
|
-
raise ValueError("VPC ID is required for ECS service")
|
|
123
|
-
|
|
124
|
-
self._vpc = ec2.Vpc.from_lookup(
|
|
125
|
-
self,
|
|
126
|
-
"VPC",
|
|
127
|
-
vpc_id=vpc_id
|
|
128
|
-
)
|
|
106
|
+
"""Load VPC using the centralized VPC provider mixin."""
|
|
107
|
+
# Use the centralized VPC resolution from VPCProviderMixin
|
|
108
|
+
self._vpc = self.resolve_vpc(
|
|
109
|
+
config=self.ecs_config,
|
|
110
|
+
deployment=self.deployment,
|
|
111
|
+
workload=self.workload
|
|
112
|
+
)
|
|
129
113
|
|
|
130
114
|
def _process_ssm_imports(self) -> None:
|
|
131
115
|
"""
|
|
@@ -450,7 +434,10 @@ class EcsServiceStack(IStack, EnhancedSsmParameterMixin):
|
|
|
450
434
|
health_check_grace_period=cdk.Duration.seconds(
|
|
451
435
|
self.ecs_config.health_check_grace_period
|
|
452
436
|
) if self.ecs_config.target_group_arns else None,
|
|
453
|
-
circuit_breaker=ecs.DeploymentCircuitBreaker(
|
|
437
|
+
circuit_breaker=ecs.DeploymentCircuitBreaker(
|
|
438
|
+
enable=self.ecs_config.deployment_circuit_breaker.get("enable", True),
|
|
439
|
+
rollback=self.ecs_config.deployment_circuit_breaker.get("rollback", True)
|
|
440
|
+
) if self.ecs_config.deployment_circuit_breaker else None,
|
|
454
441
|
placement_strategies=self._get_placement_strategies(),
|
|
455
442
|
placement_constraints=self._get_placement_constraints(),
|
|
456
443
|
)
|
|
@@ -470,7 +457,10 @@ class EcsServiceStack(IStack, EnhancedSsmParameterMixin):
|
|
|
470
457
|
health_check_grace_period=cdk.Duration.seconds(
|
|
471
458
|
self.ecs_config.health_check_grace_period
|
|
472
459
|
) if self.ecs_config.target_group_arns else None,
|
|
473
|
-
circuit_breaker=ecs.DeploymentCircuitBreaker(
|
|
460
|
+
circuit_breaker=ecs.DeploymentCircuitBreaker(
|
|
461
|
+
enable=self.ecs_config.deployment_circuit_breaker.get("enable", True),
|
|
462
|
+
rollback=self.ecs_config.deployment_circuit_breaker.get("rollback", True)
|
|
463
|
+
) if self.ecs_config.deployment_circuit_breaker else None,
|
|
474
464
|
)
|
|
475
465
|
|
|
476
466
|
# Attach to load balancer target groups
|
|
@@ -662,15 +652,6 @@ class EcsServiceStack(IStack, EnhancedSsmParameterMixin):
|
|
|
662
652
|
description=f"ECS Service ARN: {service_name}",
|
|
663
653
|
)
|
|
664
654
|
|
|
665
|
-
# Cluster name
|
|
666
|
-
if "cluster_name" in ssm_exports:
|
|
667
|
-
self.export_ssm_parameter(
|
|
668
|
-
scope=self,
|
|
669
|
-
id="ClusterNameParam",
|
|
670
|
-
value=self.cluster.cluster_name,
|
|
671
|
-
parameter_name=ssm_exports["cluster_name"],
|
|
672
|
-
description=f"ECS Cluster Name for {service_name}",
|
|
673
|
-
)
|
|
674
655
|
|
|
675
656
|
# Task definition ARN
|
|
676
657
|
if "task_definition_arn" in ssm_exports:
|
|
@@ -25,7 +25,7 @@ from cdk_factory.configurations.deployment import DeploymentConfig
|
|
|
25
25
|
from cdk_factory.configurations.stack import StackConfig
|
|
26
26
|
from cdk_factory.configurations.resources.lambda_edge import LambdaEdgeConfig
|
|
27
27
|
from cdk_factory.interfaces.istack import IStack
|
|
28
|
-
from cdk_factory.interfaces.
|
|
28
|
+
from cdk_factory.interfaces.standardized_ssm_mixin import StandardizedSsmMixin
|
|
29
29
|
from cdk_factory.stack.stack_module_registry import register_stack
|
|
30
30
|
from cdk_factory.workload.workload_factory import WorkloadConfig
|
|
31
31
|
|
|
@@ -34,7 +34,7 @@ logger = Logger(service="LambdaEdgeStack")
|
|
|
34
34
|
|
|
35
35
|
@register_stack("lambda_edge_library_module")
|
|
36
36
|
@register_stack("lambda_edge_stack")
|
|
37
|
-
class LambdaEdgeStack(IStack,
|
|
37
|
+
class LambdaEdgeStack(IStack, StandardizedSsmMixin):
|
|
38
38
|
"""
|
|
39
39
|
Reusable stack for Lambda@Edge functions.
|
|
40
40
|
|