cdk-factory 0.18.21__py3-none-any.whl → 0.19.13__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.
- cdk_factory/configurations/resources/lambda_edge.py +18 -4
- cdk_factory/configurations/resources/rds.py +1 -1
- cdk_factory/configurations/resources/s3.py +9 -1
- cdk_factory/constructs/cloudfront/cloudfront_distribution_construct.py +1 -1
- cdk_factory/stack_library/acm/acm_stack.py +5 -15
- cdk_factory/stack_library/auto_scaling/auto_scaling_stack.py +51 -32
- cdk_factory/stack_library/cloudfront/cloudfront_stack.py +48 -23
- cdk_factory/stack_library/code_artifact/code_artifact_stack.py +3 -25
- cdk_factory/stack_library/ecs/ecs_service_stack.py +38 -25
- cdk_factory/stack_library/lambda_edge/lambda_edge_stack.py +119 -28
- cdk_factory/stack_library/load_balancer/load_balancer_stack.py +2 -59
- cdk_factory/stack_library/rds/rds_stack.py +1 -25
- cdk_factory/stack_library/route53/route53_stack.py +1 -34
- cdk_factory/stack_library/security_group/security_group_full_stack.py +1 -31
- cdk_factory/stack_library/security_group/security_group_stack.py +1 -8
- cdk_factory/stack_library/simple_queue_service/sqs_stack.py +1 -34
- cdk_factory/stack_library/vpc/vpc_stack.py +2 -109
- cdk_factory/stack_library/websites/static_website_stack.py +6 -2
- cdk_factory/version.py +1 -1
- {cdk_factory-0.18.21.dist-info → cdk_factory-0.19.13.dist-info}/METADATA +1 -1
- {cdk_factory-0.18.21.dist-info → cdk_factory-0.19.13.dist-info}/RECORD +24 -24
- {cdk_factory-0.18.21.dist-info → cdk_factory-0.19.13.dist-info}/WHEEL +0 -0
- {cdk_factory-0.18.21.dist-info → cdk_factory-0.19.13.dist-info}/entry_points.txt +0 -0
- {cdk_factory-0.18.21.dist-info → cdk_factory-0.19.13.dist-info}/licenses/LICENSE +0 -0
|
@@ -49,16 +49,30 @@ class LambdaEdgeConfig(EnhancedBaseConfig):
|
|
|
49
49
|
|
|
50
50
|
@property
|
|
51
51
|
def timeout(self) -> int:
|
|
52
|
-
"""Timeout in seconds
|
|
52
|
+
"""Timeout in seconds
|
|
53
|
+
viewer-request: 5s
|
|
54
|
+
viewer-response: 5s
|
|
55
|
+
---
|
|
56
|
+
origin-request: 30s
|
|
57
|
+
origin-response: 30s
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
"""
|
|
53
61
|
timeout = int(self._config.get("timeout", 5))
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
|
|
63
|
+
event_type = self.event_type
|
|
64
|
+
if event_type == "viewer-request" or event_type == "viewer-response":
|
|
65
|
+
if timeout > 5:
|
|
66
|
+
raise ValueError("Lambda@Edge viewer timeout cannot exceed 5 seconds. Value was set to {}".format(timeout))
|
|
67
|
+
else:
|
|
68
|
+
if timeout > 30:
|
|
69
|
+
raise ValueError("Lambda@Edge origin timeout cannot exceed 30 seconds. Value was set to {}".format(timeout))
|
|
56
70
|
return timeout
|
|
57
71
|
|
|
58
72
|
@property
|
|
59
73
|
def code_path(self) -> str:
|
|
60
74
|
"""Path to Lambda function code directory"""
|
|
61
|
-
return self._config.get("code_path", "./lambdas/
|
|
75
|
+
return self._config.get("code_path", "./lambdas/cloudfront/ip_gate")
|
|
62
76
|
|
|
63
77
|
@property
|
|
64
78
|
def environment(self) -> Dict[str, str]:
|
|
@@ -158,7 +158,15 @@ class S3BucketConfig(EnhancedBaseConfig):
|
|
|
158
158
|
value = self.__config.get("block_public_access")
|
|
159
159
|
|
|
160
160
|
if value and isinstance(value, str):
|
|
161
|
-
if value.lower() == "
|
|
161
|
+
if value.lower() == "disabled":
|
|
162
|
+
# For public website hosting, disable block public access
|
|
163
|
+
return s3.BlockPublicAccess(
|
|
164
|
+
block_public_acls=False,
|
|
165
|
+
block_public_policy=False,
|
|
166
|
+
ignore_public_acls=False,
|
|
167
|
+
restrict_public_buckets=False
|
|
168
|
+
)
|
|
169
|
+
elif value.lower() == "block_acls":
|
|
162
170
|
return s3.BlockPublicAccess.BLOCK_ACLS
|
|
163
171
|
# elif value.lower() == "block_public_acls":
|
|
164
172
|
# return s3.BlockPublicAccess.block_public_acls
|
|
@@ -25,6 +25,7 @@ logger = Logger(service="AcmStack")
|
|
|
25
25
|
|
|
26
26
|
@register_stack("acm_stack")
|
|
27
27
|
@register_stack("certificate_stack")
|
|
28
|
+
@register_stack("certificate_library_module")
|
|
28
29
|
class AcmStack(IStack, StandardizedSsmMixin):
|
|
29
30
|
"""
|
|
30
31
|
Reusable stack for AWS Certificate Manager.
|
|
@@ -152,18 +153,7 @@ class AcmStack(IStack, StandardizedSsmMixin):
|
|
|
152
153
|
|
|
153
154
|
def _add_outputs(self, cert_name: str) -> None:
|
|
154
155
|
"""Add CloudFormation outputs"""
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
description=f"Certificate ARN for {self.acm_config.domain_name}",
|
|
160
|
-
export_name=f"{cert_name}-arn",
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
cdk.CfnOutput(
|
|
164
|
-
self,
|
|
165
|
-
"DomainName",
|
|
166
|
-
value=self.acm_config.domain_name,
|
|
167
|
-
description="Primary domain name for the certificate",
|
|
168
|
-
export_name=f"{cert_name}-domain",
|
|
169
|
-
)
|
|
156
|
+
|
|
157
|
+
return
|
|
158
|
+
|
|
159
|
+
|
|
@@ -13,7 +13,7 @@ from aws_cdk import aws_cloudwatch as cloudwatch
|
|
|
13
13
|
from aws_cdk import aws_iam as iam
|
|
14
14
|
from aws_cdk import aws_ssm as ssm
|
|
15
15
|
from aws_cdk import aws_ecs as ecs
|
|
16
|
-
from aws_cdk import Duration, Stack
|
|
16
|
+
from aws_cdk import Duration, Stack, CfnUpdatePolicy
|
|
17
17
|
from aws_lambda_powertools import Logger
|
|
18
18
|
from constructs import Construct
|
|
19
19
|
|
|
@@ -539,43 +539,62 @@ class AutoScalingStack(IStack, VPCProviderMixin, StandardizedSsmMixin):
|
|
|
539
539
|
|
|
540
540
|
if not instance_refresh_config.get("enabled", False):
|
|
541
541
|
return
|
|
542
|
+
|
|
543
|
+
logger.warning("Instance refresh is not supported in this version of the CDK")
|
|
544
|
+
return
|
|
542
545
|
|
|
543
546
|
# Get the CloudFormation ASG resource
|
|
544
547
|
cfn_asg = asg.node.default_child
|
|
545
548
|
|
|
546
|
-
# Configure instance refresh
|
|
547
|
-
|
|
549
|
+
# Configure instance refresh using CloudFormation UpdatePolicy
|
|
550
|
+
# UpdatePolicy is added at the resource level, not as a property
|
|
551
|
+
update_policy = {
|
|
552
|
+
"AutoScalingRollingUpdate": {
|
|
553
|
+
"PauseTime": "PT300S", # 5 minutes pause
|
|
554
|
+
"MinInstancesInService": "1",
|
|
555
|
+
"MaxBatchSize": "1",
|
|
556
|
+
"WaitOnResourceSignals": True,
|
|
557
|
+
"SuspendProcesses": [
|
|
558
|
+
"HealthCheck",
|
|
559
|
+
"ReplaceUnhealthy",
|
|
560
|
+
"AZRebalance",
|
|
561
|
+
"AlarmNotification",
|
|
562
|
+
"ScheduledActions"
|
|
563
|
+
]
|
|
564
|
+
}
|
|
565
|
+
}
|
|
548
566
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
567
|
+
# # Apply instance refresh using CloudFormation's cfn_options.update_policy
|
|
568
|
+
# cfn_asg.cfn_options.update_policy = cdk.CfnUpdatePolicy.from_rolling_update(
|
|
569
|
+
# pause_time=cdk.Duration.seconds(300),
|
|
570
|
+
# min_instances_in_service=1,
|
|
571
|
+
# max_batch_size=1,
|
|
572
|
+
# wait_on_resource_signals=True
|
|
573
|
+
# )
|
|
574
|
+
|
|
575
|
+
# Grab the L1 to attach UpdatePolicy.InstanceRefresh
|
|
576
|
+
cfn_asg: autoscaling.CfnAutoScalingGroup = asg.node.default_child
|
|
577
|
+
|
|
578
|
+
# cfn_asg.cfn_options.update_policy = CfnUpdatePolicy.from_auto_scaling_instance_refresh(
|
|
579
|
+
# # Triggers tell CFN *what* changes should start a refresh
|
|
580
|
+
# triggers=[CfnUpdatePolicy.InstanceRefreshTrigger.LAUNCH_TEMPLATE],
|
|
581
|
+
# preferences=CfnUpdatePolicy.InstanceRefreshPreferences(
|
|
582
|
+
# # warmup is like “grace” before counting a new instance healthy
|
|
583
|
+
# instance_warmup=Duration.minutes(5),
|
|
584
|
+
# # how aggressive the refresh is; 90 keeps capacity high
|
|
585
|
+
# min_healthy_percentage=90,
|
|
586
|
+
# # skip instances that already match the new LT (fast when only userdata/env tweaked)
|
|
587
|
+
# skip_matching=True,
|
|
588
|
+
# # optional: put instances in Standby first; default is rolling terminate/launch
|
|
589
|
+
# # standby_instances=CfnUpdatePolicy.StandbyInstances.TERMINATE,
|
|
590
|
+
# # checkpoint_percentages=[25, 50, 75], # optional: progressive checkpoints
|
|
591
|
+
# # checkpoint_delay=Duration.minutes(2), # optional delay at checkpoints
|
|
592
|
+
# ),
|
|
593
|
+
# )
|
|
594
|
+
logger.info(f"Configured instance refresh via CDK CfnUpdatePolicy")
|
|
575
595
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
logger.info(f"Configured instance refresh: {refresh_props}")
|
|
596
|
+
# Note: This provides rolling update functionality similar to instance refresh
|
|
597
|
+
# For true instance refresh with preferences, we would need CDK v2.80+ or custom CloudFormation
|
|
579
598
|
|
|
580
599
|
|
|
581
600
|
# Backward compatibility alias
|
|
@@ -14,6 +14,7 @@ from aws_cdk import (
|
|
|
14
14
|
aws_cloudfront_origins as origins,
|
|
15
15
|
aws_certificatemanager as acm,
|
|
16
16
|
aws_route53 as route53,
|
|
17
|
+
aws_s3 as s3,
|
|
17
18
|
aws_lambda as _lambda,
|
|
18
19
|
aws_ssm as ssm,
|
|
19
20
|
CfnOutput,
|
|
@@ -144,7 +145,7 @@ class CloudFrontStack(IStack):
|
|
|
144
145
|
return
|
|
145
146
|
|
|
146
147
|
# Check if certificate ARN is provided
|
|
147
|
-
cert_arn = cert_config.get("arn")
|
|
148
|
+
cert_arn = self.resolve_ssm_value(self, cert_config.get("arn"), "CertificateARN")
|
|
148
149
|
if cert_arn:
|
|
149
150
|
self.certificate = acm.Certificate.from_certificate_arn(
|
|
150
151
|
self, "Certificate", certificate_arn=cert_arn
|
|
@@ -172,14 +173,14 @@ class CloudFrontStack(IStack):
|
|
|
172
173
|
"CloudFront certificates must be created in us-east-1"
|
|
173
174
|
)
|
|
174
175
|
return
|
|
175
|
-
|
|
176
|
+
|
|
176
177
|
# Create the certificate
|
|
177
178
|
# Get hosted zone from SSM imports
|
|
178
179
|
hosted_zone_id = cert_config.get("hosted_zone_id")
|
|
179
180
|
hosted_zone = route53.HostedZone.from_hosted_zone_id(
|
|
180
181
|
self, "HostedZone", hosted_zone_id
|
|
181
182
|
)
|
|
182
|
-
|
|
183
|
+
|
|
183
184
|
self.certificate = acm.Certificate(
|
|
184
185
|
self,
|
|
185
186
|
"Certificate",
|
|
@@ -222,27 +223,29 @@ class CloudFrontStack(IStack):
|
|
|
222
223
|
|
|
223
224
|
def _create_custom_origin(self, config: Dict[str, Any]) -> cloudfront.IOrigin:
|
|
224
225
|
"""Create custom origin (ALB, API Gateway, etc.)"""
|
|
225
|
-
domain_name =
|
|
226
|
+
domain_name = self.resolve_ssm_value(
|
|
227
|
+
self, config.get("domain_name"), config.get("domain_name")
|
|
228
|
+
)
|
|
226
229
|
origin_id = config.get("id")
|
|
227
230
|
|
|
228
231
|
if not domain_name:
|
|
229
232
|
raise ValueError("domain_name is required for custom origin")
|
|
230
233
|
|
|
231
|
-
# Check if domain name is a placeholder from ssm_imports
|
|
232
|
-
if domain_name.startswith("{{") and domain_name.endswith("}}"):
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
# Legacy support: Check if domain name is an SSM parameter reference
|
|
241
|
-
elif domain_name.startswith("{{ssm:") and domain_name.endswith("}}"):
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
234
|
+
# # Check if domain name is a placeholder from ssm_imports
|
|
235
|
+
# if domain_name.startswith("{{") and domain_name.endswith("}}"):
|
|
236
|
+
# placeholder_key = domain_name[2:-2] # Remove {{ and }}
|
|
237
|
+
# if placeholder_key in self.ssm_imported_values:
|
|
238
|
+
# domain_name = self.ssm_imported_values[placeholder_key]
|
|
239
|
+
# logger.info(f"Resolved domain from SSM import: {placeholder_key}")
|
|
240
|
+
# else:
|
|
241
|
+
# logger.warning(f"Placeholder {domain_name} not found in SSM imports")
|
|
242
|
+
|
|
243
|
+
# # Legacy support: Check if domain name is an SSM parameter reference
|
|
244
|
+
# elif domain_name.startswith("{{ssm:") and domain_name.endswith("}}"):
|
|
245
|
+
# # Extract SSM parameter name
|
|
246
|
+
# ssm_param = domain_name[6:-2] # Remove {{ssm: and }}
|
|
247
|
+
# domain_name = ssm.StringParameter.value_from_lookup(self, ssm_param)
|
|
248
|
+
# logger.info(f"Resolved domain from SSM lookup {ssm_param}: {domain_name}")
|
|
246
249
|
|
|
247
250
|
# Build custom headers (e.g., X-Origin-Secret)
|
|
248
251
|
custom_headers = {}
|
|
@@ -296,12 +299,34 @@ class CloudFrontStack(IStack):
|
|
|
296
299
|
|
|
297
300
|
def _create_s3_origin(self, config: Dict[str, Any]) -> cloudfront.IOrigin:
|
|
298
301
|
"""Create S3 origin"""
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
raise NotImplementedError(
|
|
302
|
-
"S3 origin support - use existing static_website_stack for S3"
|
|
302
|
+
bucket_name = self.resolve_ssm_value(
|
|
303
|
+
self, config.get("bucket_name"), config.get("bucket_name")
|
|
303
304
|
)
|
|
304
305
|
|
|
306
|
+
origin_path = config.get("origin_path", "")
|
|
307
|
+
|
|
308
|
+
if not bucket_name:
|
|
309
|
+
raise ValueError("S3 origin requires 'bucket_name' configuration")
|
|
310
|
+
|
|
311
|
+
# For S3 origins, we need to import the bucket by name
|
|
312
|
+
bucket = s3.Bucket.from_bucket_name(
|
|
313
|
+
self,
|
|
314
|
+
id=f"S3OriginBucket-{config.get('id', 'unknown')}",
|
|
315
|
+
bucket_name=bucket_name,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
# Create S3 origin with OAC (Origin Access Control) for security
|
|
319
|
+
origin = origins.S3BucketOrigin.with_origin_access_control(
|
|
320
|
+
bucket,
|
|
321
|
+
origin_path=origin_path,
|
|
322
|
+
origin_access_levels=[
|
|
323
|
+
cloudfront.AccessLevel.READ,
|
|
324
|
+
cloudfront.AccessLevel.LIST,
|
|
325
|
+
],
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
return origin
|
|
329
|
+
|
|
305
330
|
def _create_distribution(self) -> None:
|
|
306
331
|
"""Create CloudFront distribution"""
|
|
307
332
|
|
|
@@ -140,32 +140,10 @@ class CodeArtifactStack(IStack, StandardizedSsmMixin):
|
|
|
140
140
|
|
|
141
141
|
def _add_outputs(self) -> None:
|
|
142
142
|
"""Add CloudFormation outputs for the CodeArtifact resources"""
|
|
143
|
+
|
|
144
|
+
|
|
143
145
|
# Domain outputs
|
|
144
146
|
if self.domain:
|
|
145
147
|
domain_name = self.code_artifact_config.domain_name
|
|
146
148
|
|
|
147
|
-
|
|
148
|
-
cdk.CfnOutput(
|
|
149
|
-
self,
|
|
150
|
-
f"{domain_name}-domain-arn",
|
|
151
|
-
value=self.domain.attr_arn,
|
|
152
|
-
export_name=f"{self.deployment.build_resource_name(domain_name)}-domain-arn"
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
# Domain URL
|
|
156
|
-
cdk.CfnOutput(
|
|
157
|
-
self,
|
|
158
|
-
f"{domain_name}-domain-url",
|
|
159
|
-
value=f"https://{self.code_artifact_config.account}.d.codeartifact.{self.code_artifact_config.region}.amazonaws.com/",
|
|
160
|
-
export_name=f"{self.deployment.build_resource_name(domain_name)}-domain-url"
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
# Repository outputs
|
|
164
|
-
for repo_name, repo in self.repositories.items():
|
|
165
|
-
# Repository ARN
|
|
166
|
-
cdk.CfnOutput(
|
|
167
|
-
self,
|
|
168
|
-
f"{repo_name}-repo-arn",
|
|
169
|
-
value=repo.attr_arn,
|
|
170
|
-
export_name=f"{self.deployment.build_resource_name(repo_name)}-repo-arn"
|
|
171
|
-
)
|
|
149
|
+
|
|
@@ -101,6 +101,7 @@ class EcsServiceStack(IStack, VPCProviderMixin, StandardizedSsmMixin):
|
|
|
101
101
|
|
|
102
102
|
# Add outputs
|
|
103
103
|
self._add_outputs(service_name)
|
|
104
|
+
self._export_to_ssm(service_name)
|
|
104
105
|
|
|
105
106
|
def _load_vpc(self) -> None:
|
|
106
107
|
"""Load VPC using the centralized VPC provider mixin."""
|
|
@@ -225,6 +226,9 @@ class EcsServiceStack(IStack, VPCProviderMixin, StandardizedSsmMixin):
|
|
|
225
226
|
"CloudWatchAgentServerPolicy"
|
|
226
227
|
)
|
|
227
228
|
)
|
|
229
|
+
|
|
230
|
+
# add any custom policies
|
|
231
|
+
self._add_custom_task_policies(task_role)
|
|
228
232
|
|
|
229
233
|
# Create task definition based on launch type
|
|
230
234
|
if self.ecs_config.launch_type == "EC2":
|
|
@@ -256,6 +260,37 @@ class EcsServiceStack(IStack, VPCProviderMixin, StandardizedSsmMixin):
|
|
|
256
260
|
# Add containers
|
|
257
261
|
self._add_containers_to_task()
|
|
258
262
|
|
|
263
|
+
def _add_custom_task_policies(self, task_role: iam.Role) -> None:
|
|
264
|
+
"""
|
|
265
|
+
Add custom task policies to the task definition.
|
|
266
|
+
"""
|
|
267
|
+
for policy in self.ecs_config.task_definition.get("policies", []):
|
|
268
|
+
|
|
269
|
+
effect = policy.get("effect", "Allow")
|
|
270
|
+
action = policy.get("action", None)
|
|
271
|
+
actions = policy.get("actions", [])
|
|
272
|
+
if action:
|
|
273
|
+
actions.append(action)
|
|
274
|
+
resources = policy.get("resources", [])
|
|
275
|
+
resource = policy.get("resource", None)
|
|
276
|
+
if resource:
|
|
277
|
+
resources.append(resource)
|
|
278
|
+
|
|
279
|
+
if effect == "Allow" and actions:
|
|
280
|
+
effect = iam.Effect.ALLOW
|
|
281
|
+
if effect == "Deny" and actions:
|
|
282
|
+
effect = iam.Effect.DENY
|
|
283
|
+
|
|
284
|
+
sid = policy.get("sid", None)
|
|
285
|
+
task_role.add_to_policy(
|
|
286
|
+
iam.PolicyStatement(
|
|
287
|
+
effect=effect,
|
|
288
|
+
actions=actions,
|
|
289
|
+
resources=resources,
|
|
290
|
+
sid=sid,
|
|
291
|
+
)
|
|
292
|
+
)
|
|
293
|
+
|
|
259
294
|
def _add_volumes_to_task(self) -> None:
|
|
260
295
|
"""
|
|
261
296
|
Add volumes to the task definition.
|
|
@@ -603,35 +638,13 @@ class EcsServiceStack(IStack, VPCProviderMixin, StandardizedSsmMixin):
|
|
|
603
638
|
scale_out_cooldown=cdk.Duration.seconds(60),
|
|
604
639
|
)
|
|
605
640
|
|
|
641
|
+
|
|
642
|
+
|
|
606
643
|
def _add_outputs(self, service_name: str) -> None:
|
|
607
644
|
"""Add CloudFormation outputs"""
|
|
645
|
+
return
|
|
608
646
|
|
|
609
|
-
# Service name output
|
|
610
|
-
cdk.CfnOutput(
|
|
611
|
-
self,
|
|
612
|
-
"ServiceName",
|
|
613
|
-
value=self.service.service_name,
|
|
614
|
-
description=f"ECS Service Name: {service_name}",
|
|
615
|
-
)
|
|
616
|
-
|
|
617
|
-
# Service ARN output
|
|
618
|
-
cdk.CfnOutput(
|
|
619
|
-
self,
|
|
620
|
-
"ServiceArn",
|
|
621
|
-
value=self.service.service_arn,
|
|
622
|
-
description=f"ECS Service ARN: {service_name}",
|
|
623
|
-
)
|
|
624
|
-
|
|
625
|
-
# Cluster name output
|
|
626
|
-
cdk.CfnOutput(
|
|
627
|
-
self,
|
|
628
|
-
"ClusterName",
|
|
629
|
-
value=self.cluster.cluster_name,
|
|
630
|
-
description=f"ECS Cluster Name for {service_name}",
|
|
631
|
-
)
|
|
632
647
|
|
|
633
|
-
# Export to SSM if configured
|
|
634
|
-
self._export_to_ssm(service_name)
|
|
635
648
|
|
|
636
649
|
def _export_to_ssm(self, service_name: str) -> None:
|
|
637
650
|
"""Export resource ARNs and names to SSM Parameter Store"""
|
|
@@ -53,6 +53,8 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
|
|
|
53
53
|
self.workload: Optional[WorkloadConfig] = None
|
|
54
54
|
self.function: Optional[_lambda.Function] = None
|
|
55
55
|
self.function_version: Optional[_lambda.Version] = None
|
|
56
|
+
# Cache for resolved environment variables to prevent duplicate construct creation
|
|
57
|
+
self._resolved_env_cache: Optional[Dict[str, str]] = None
|
|
56
58
|
|
|
57
59
|
def build(
|
|
58
60
|
self,
|
|
@@ -98,15 +100,38 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
|
|
|
98
100
|
# Create version (required for Lambda@Edge)
|
|
99
101
|
self._create_function_version(function_name)
|
|
100
102
|
|
|
103
|
+
# Configure edge log retention for regional logs
|
|
104
|
+
self._configure_edge_log_retention(function_name)
|
|
105
|
+
|
|
101
106
|
# Add outputs
|
|
102
107
|
self._add_outputs(function_name)
|
|
103
108
|
|
|
109
|
+
def _sanitize_construct_name(self, name: str) -> str:
|
|
110
|
+
"""
|
|
111
|
+
Create a deterministic, valid CDK construct name from any string.
|
|
112
|
+
Replaces non-alphanumeric characters with dashes and limits length.
|
|
113
|
+
"""
|
|
114
|
+
# Replace non-alphanumeric characters with dashes
|
|
115
|
+
sanitized = ''.join(c if c.isalnum() else '-' for c in name)
|
|
116
|
+
# Remove consecutive dashes
|
|
117
|
+
while '--' in sanitized:
|
|
118
|
+
sanitized = sanitized.replace('--', '-')
|
|
119
|
+
# Remove leading/trailing dashes
|
|
120
|
+
sanitized = sanitized.strip('-')
|
|
121
|
+
# Limit to 255 characters (CDK limit)
|
|
122
|
+
return sanitized[:255]
|
|
123
|
+
|
|
104
124
|
def _resolve_environment_variables(self) -> Dict[str, str]:
|
|
105
125
|
"""
|
|
106
126
|
Resolve environment variables, including SSM parameter references.
|
|
107
127
|
Supports {{ssm:parameter-path}} syntax for dynamic SSM lookups.
|
|
108
128
|
Uses CDK tokens that resolve at deployment time, not synthesis time.
|
|
129
|
+
Caches results to prevent duplicate construct creation.
|
|
109
130
|
"""
|
|
131
|
+
# Return cached result if available
|
|
132
|
+
if self._resolved_env_cache is not None:
|
|
133
|
+
return self._resolved_env_cache
|
|
134
|
+
|
|
110
135
|
resolved_env = {}
|
|
111
136
|
|
|
112
137
|
for key, value in self.edge_config.environment.items():
|
|
@@ -115,24 +140,29 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
|
|
|
115
140
|
# Extract SSM parameter path
|
|
116
141
|
ssm_param_path = value[6:-2] # Remove {{ssm: and }}
|
|
117
142
|
|
|
143
|
+
# Create deterministic construct name from parameter path
|
|
144
|
+
construct_name = self._sanitize_construct_name(f"env-{key}-{ssm_param_path}")
|
|
145
|
+
|
|
118
146
|
# Import SSM parameter - this creates a token that resolves at deployment time
|
|
119
147
|
param = ssm.StringParameter.from_string_parameter_name(
|
|
120
148
|
self,
|
|
121
|
-
|
|
149
|
+
construct_name,
|
|
122
150
|
ssm_param_path
|
|
123
151
|
)
|
|
124
152
|
resolved_value = param.string_value
|
|
125
|
-
logger.info(f"Resolved environment variable {key} from SSM {ssm_param_path}")
|
|
153
|
+
logger.info(f"Resolved environment variable {key} from SSM {ssm_param_path} as {construct_name}")
|
|
126
154
|
resolved_env[key] = resolved_value
|
|
127
155
|
else:
|
|
128
156
|
resolved_env[key] = value
|
|
129
157
|
|
|
158
|
+
# Cache the result
|
|
159
|
+
self._resolved_env_cache = resolved_env
|
|
130
160
|
return resolved_env
|
|
131
161
|
|
|
132
162
|
def _create_lambda_function(self, function_name: str) -> None:
|
|
133
163
|
"""Create the Lambda function"""
|
|
134
164
|
|
|
135
|
-
# Resolve code path - support package references (e.g., "cdk_factory:lambdas/
|
|
165
|
+
# Resolve code path - support package references (e.g., "cdk_factory:lambdas/cloudfront/ip_gate")
|
|
136
166
|
code_path_str = self.edge_config.code_path
|
|
137
167
|
|
|
138
168
|
if ':' in code_path_str:
|
|
@@ -185,10 +215,12 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
|
|
|
185
215
|
# Create runtime configuration file for Lambda@Edge
|
|
186
216
|
# Since Lambda@Edge doesn't support environment variables, we bundle a config file
|
|
187
217
|
# Use the full function_name (e.g., "tech-talk-dev-ip-gate") not just the base name
|
|
218
|
+
resolved_env = self._resolve_environment_variables()
|
|
188
219
|
runtime_config = {
|
|
189
220
|
'environment': self.deployment.environment,
|
|
190
221
|
'function_name': function_name,
|
|
191
|
-
'region': self.deployment.region
|
|
222
|
+
'region': self.deployment.region,
|
|
223
|
+
'environment_variables': resolved_env # Add actual environment variables
|
|
192
224
|
}
|
|
193
225
|
|
|
194
226
|
runtime_config_path = temp_code_dir / 'runtime_config.json'
|
|
@@ -239,7 +271,8 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
|
|
|
239
271
|
f"{function_name}-Role",
|
|
240
272
|
assumed_by=iam.CompositePrincipal(
|
|
241
273
|
iam.ServicePrincipal("lambda.amazonaws.com"),
|
|
242
|
-
iam.ServicePrincipal("edgelambda.amazonaws.com")
|
|
274
|
+
iam.ServicePrincipal("edgelambda.amazonaws.com"),
|
|
275
|
+
iam.ServicePrincipal("cloudfront.amazonaws.com") # Add CloudFront service principal
|
|
243
276
|
),
|
|
244
277
|
description=f"Execution role for Lambda@Edge function {function_name}",
|
|
245
278
|
managed_policies=[
|
|
@@ -285,6 +318,36 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
|
|
|
285
318
|
for key, value in self.edge_config.tags.items():
|
|
286
319
|
cdk.Tags.of(self.function).add(key, value)
|
|
287
320
|
|
|
321
|
+
# Add resource-based policy allowing CloudFront to invoke the Lambda function
|
|
322
|
+
# This is REQUIRED for Lambda@Edge to work properly
|
|
323
|
+
permission_kwargs = {
|
|
324
|
+
"principal": iam.ServicePrincipal("cloudfront.amazonaws.com"),
|
|
325
|
+
"action": "lambda:InvokeFunction",
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
# Optional: Add source ARN restriction if CloudFront distribution ARN is available
|
|
329
|
+
# This provides more secure permission scoping
|
|
330
|
+
distribution_arn_path = f"/{self.deployment.environment}/{self.workload.name}/cloudfront/arn"
|
|
331
|
+
try:
|
|
332
|
+
distribution_arn = ssm.StringParameter.from_string_parameter_name(
|
|
333
|
+
self,
|
|
334
|
+
"cloudfront-distribution-arn",
|
|
335
|
+
distribution_arn_path
|
|
336
|
+
).string_value
|
|
337
|
+
|
|
338
|
+
# Add source ARN condition for more secure permission scoping
|
|
339
|
+
permission_kwargs["source_arn"] = distribution_arn
|
|
340
|
+
logger.info(f"Adding CloudFront permission with source ARN restriction: {distribution_arn}")
|
|
341
|
+
except Exception:
|
|
342
|
+
# Distribution ARN not available (common during initial deployment)
|
|
343
|
+
# CloudFront will scope the permission appropriately when it associates the Lambda
|
|
344
|
+
logger.warning(f"CloudFront distribution ARN not found at {distribution_arn_path}, using open permission")
|
|
345
|
+
|
|
346
|
+
self.function.add_permission(
|
|
347
|
+
"CloudFrontInvokePermission",
|
|
348
|
+
**permission_kwargs
|
|
349
|
+
)
|
|
350
|
+
|
|
288
351
|
def _create_function_version(self, function_name: str) -> None:
|
|
289
352
|
"""
|
|
290
353
|
Create a version of the Lambda function.
|
|
@@ -300,33 +363,61 @@ class LambdaEdgeStack(IStack, StandardizedSsmMixin):
|
|
|
300
363
|
f"Version for Lambda@Edge deployment - {self.edge_config.description}"
|
|
301
364
|
)
|
|
302
365
|
|
|
366
|
+
def _configure_edge_log_retention(self, function_name: str) -> None:
|
|
367
|
+
"""
|
|
368
|
+
Configure log retention for Lambda@Edge regional logs.
|
|
369
|
+
|
|
370
|
+
Lambda@Edge creates log groups in multiple regions that need
|
|
371
|
+
separate retention configuration from the primary log group.
|
|
372
|
+
"""
|
|
373
|
+
from aws_cdk import custom_resources as cr
|
|
374
|
+
|
|
375
|
+
# Get edge log retention from config (default to same as primary logs)
|
|
376
|
+
edge_retention_days = self.edge_config.dictionary.get("edge_log_retention_days", 7)
|
|
377
|
+
|
|
378
|
+
# List of common Lambda@Edge regions
|
|
379
|
+
edge_regions = [
|
|
380
|
+
'us-east-1', 'us-east-2', 'us-west-1', 'us-west-2',
|
|
381
|
+
'eu-west-1', 'eu-west-2', 'eu-central-1',
|
|
382
|
+
'ap-southeast-1', 'ap-southeast-2', 'ap-northeast-1',
|
|
383
|
+
'ca-central-1', 'sa-east-1'
|
|
384
|
+
]
|
|
385
|
+
|
|
386
|
+
# Create custom resource to set log retention for each region
|
|
387
|
+
for region in edge_regions:
|
|
388
|
+
log_group_name = f"/aws/lambda/{region}.{function_name}"
|
|
389
|
+
|
|
390
|
+
# Use AwsCustomResource to set log retention
|
|
391
|
+
cr.AwsCustomResource(
|
|
392
|
+
self, f"EdgeLogRetention-{region}",
|
|
393
|
+
on_update={
|
|
394
|
+
"service": "Logs",
|
|
395
|
+
"action": "putRetentionPolicy",
|
|
396
|
+
"parameters": {
|
|
397
|
+
"logGroupName": log_group_name,
|
|
398
|
+
"retentionInDays": edge_retention_days
|
|
399
|
+
},
|
|
400
|
+
"physical_resource_id": cr.PhysicalResourceId.from_response("logGroupName")
|
|
401
|
+
},
|
|
402
|
+
on_delete={
|
|
403
|
+
"service": "Logs",
|
|
404
|
+
"action": "deleteRetentionPolicy",
|
|
405
|
+
"parameters": {
|
|
406
|
+
"logGroupName": log_group_name
|
|
407
|
+
},
|
|
408
|
+
"physical_resource_id": cr.PhysicalResourceId.from_response("logGroupName")
|
|
409
|
+
},
|
|
410
|
+
policy=cr.AwsCustomResourcePolicy.from_sdk_calls(
|
|
411
|
+
resources=[f"arn:aws:logs:{region}:*:log-group:{log_group_name}*"]
|
|
412
|
+
)
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
logger.info(f"Configured edge log retention to {edge_retention_days} days for {len(edge_regions)} regions")
|
|
416
|
+
|
|
303
417
|
def _add_outputs(self, function_name: str) -> None:
|
|
304
418
|
"""Add CloudFormation outputs and SSM exports"""
|
|
305
419
|
|
|
306
|
-
# CloudFormation outputs
|
|
307
|
-
cdk.CfnOutput(
|
|
308
|
-
self,
|
|
309
|
-
"FunctionName",
|
|
310
|
-
value=self.function.function_name,
|
|
311
|
-
description="Lambda function name",
|
|
312
|
-
export_name=f"{function_name}-name"
|
|
313
|
-
)
|
|
314
|
-
|
|
315
|
-
cdk.CfnOutput(
|
|
316
|
-
self,
|
|
317
|
-
"FunctionArn",
|
|
318
|
-
value=self.function.function_arn,
|
|
319
|
-
description="Lambda function ARN (unversioned)",
|
|
320
|
-
export_name=f"{function_name}-arn"
|
|
321
|
-
)
|
|
322
420
|
|
|
323
|
-
cdk.CfnOutput(
|
|
324
|
-
self,
|
|
325
|
-
"FunctionVersionArn",
|
|
326
|
-
value=self.function_version.function_arn,
|
|
327
|
-
description="Lambda function version ARN (use this for Lambda@Edge)",
|
|
328
|
-
export_name=f"{function_name}-version-arn"
|
|
329
|
-
)
|
|
330
421
|
|
|
331
422
|
# SSM Parameter Store exports (if configured)
|
|
332
423
|
ssm_exports = self.edge_config.dictionary.get("ssm", {}).get("exports", {})
|
|
@@ -656,36 +656,7 @@ class LoadBalancerStack(IStack, VPCProviderMixin, StandardizedSsmMixin):
|
|
|
656
656
|
|
|
657
657
|
def _export_cfn_outputs(self, lb_name: str) -> None:
|
|
658
658
|
"""Add CloudFormation outputs for the Load Balancer"""
|
|
659
|
-
|
|
660
|
-
# Load Balancer DNS Name
|
|
661
|
-
cdk.CfnOutput(
|
|
662
|
-
self,
|
|
663
|
-
f"{lb_name}-dns-name",
|
|
664
|
-
value=self.load_balancer.load_balancer_dns_name,
|
|
665
|
-
export_name=f"{self.deployment.build_resource_name(lb_name)}-dns-name",
|
|
666
|
-
)
|
|
667
|
-
|
|
668
|
-
# Load Balancer ARN
|
|
669
|
-
cdk.CfnOutput(
|
|
670
|
-
self,
|
|
671
|
-
f"{lb_name}-arn",
|
|
672
|
-
value=self.load_balancer.load_balancer_arn,
|
|
673
|
-
export_name=f"{self.deployment.build_resource_name(lb_name)}-arn",
|
|
674
|
-
)
|
|
675
|
-
|
|
676
|
-
# Target Group ARNs
|
|
677
|
-
for tg_name, target_group in self.target_groups.items():
|
|
678
|
-
# Normalize target group name for consistent CloudFormation export naming
|
|
679
|
-
normalized_tg_name = self.normalize_resource_name(
|
|
680
|
-
tg_name, for_export=True
|
|
681
|
-
)
|
|
682
|
-
cdk.CfnOutput(
|
|
683
|
-
self,
|
|
684
|
-
f"{lb_name}-{normalized_tg_name}-arn",
|
|
685
|
-
value=target_group.target_group_arn,
|
|
686
|
-
export_name=f"{self.deployment.build_resource_name(lb_name)}-{normalized_tg_name}-arn",
|
|
687
|
-
)
|
|
688
|
-
|
|
659
|
+
return
|
|
689
660
|
def _export_ssm_parameters(self, lb_name: str) -> None:
|
|
690
661
|
"""Export Load Balancer resources to SSM Parameter Store if configured"""
|
|
691
662
|
if not self.load_balancer:
|
|
@@ -716,32 +687,4 @@ class LoadBalancerStack(IStack, VPCProviderMixin, StandardizedSsmMixin):
|
|
|
716
687
|
|
|
717
688
|
def _export_cfn_outputs(self, lb_name: str) -> None:
|
|
718
689
|
"""Add CloudFormation outputs for the Load Balancer"""
|
|
719
|
-
|
|
720
|
-
# Load Balancer DNS Name
|
|
721
|
-
cdk.CfnOutput(
|
|
722
|
-
self,
|
|
723
|
-
f"{lb_name}-dns-name",
|
|
724
|
-
value=self.load_balancer.load_balancer_dns_name,
|
|
725
|
-
export_name=f"{self.deployment.build_resource_name(lb_name)}-dns-name",
|
|
726
|
-
)
|
|
727
|
-
|
|
728
|
-
# Load Balancer ARN
|
|
729
|
-
cdk.CfnOutput(
|
|
730
|
-
self,
|
|
731
|
-
f"{lb_name}-arn",
|
|
732
|
-
value=self.load_balancer.load_balancer_arn,
|
|
733
|
-
export_name=f"{self.deployment.build_resource_name(lb_name)}-arn",
|
|
734
|
-
)
|
|
735
|
-
|
|
736
|
-
# Target Group ARNs
|
|
737
|
-
for tg_name, target_group in self.target_groups.items():
|
|
738
|
-
# Normalize target group name for consistent CloudFormation export naming
|
|
739
|
-
normalized_tg_name = self.normalize_resource_name(
|
|
740
|
-
tg_name, for_export=True
|
|
741
|
-
)
|
|
742
|
-
cdk.CfnOutput(
|
|
743
|
-
self,
|
|
744
|
-
f"{lb_name}-{normalized_tg_name}-arn",
|
|
745
|
-
value=target_group.target_group_arn,
|
|
746
|
-
export_name=f"{self.deployment.build_resource_name(lb_name)}-{normalized_tg_name}-arn",
|
|
747
|
-
)
|
|
690
|
+
return
|
|
@@ -285,31 +285,7 @@ class RdsStack(IStack, VPCProviderMixin, StandardizedSsmMixin):
|
|
|
285
285
|
|
|
286
286
|
def _add_outputs(self, db_name: str) -> None:
|
|
287
287
|
"""Add CloudFormation outputs for the RDS instance"""
|
|
288
|
-
|
|
289
|
-
# Database endpoint
|
|
290
|
-
cdk.CfnOutput(
|
|
291
|
-
self,
|
|
292
|
-
f"{db_name}-endpoint",
|
|
293
|
-
value=self.db_instance.db_instance_endpoint_address,
|
|
294
|
-
export_name=f"{self.deployment.build_resource_name(db_name)}-endpoint",
|
|
295
|
-
)
|
|
296
|
-
|
|
297
|
-
# Database port
|
|
298
|
-
cdk.CfnOutput(
|
|
299
|
-
self,
|
|
300
|
-
f"{db_name}-port",
|
|
301
|
-
value=self.db_instance.db_instance_endpoint_port,
|
|
302
|
-
export_name=f"{self.deployment.build_resource_name(db_name)}-port",
|
|
303
|
-
)
|
|
304
|
-
|
|
305
|
-
# Secret ARN (if available)
|
|
306
|
-
if hasattr(self.db_instance, "secret") and self.db_instance.secret:
|
|
307
|
-
cdk.CfnOutput(
|
|
308
|
-
self,
|
|
309
|
-
f"{db_name}-secret-arn",
|
|
310
|
-
value=self.db_instance.secret.secret_arn,
|
|
311
|
-
export_name=f"{self.deployment.build_resource_name(db_name)}-secret-arn",
|
|
312
|
-
)
|
|
288
|
+
return
|
|
313
289
|
|
|
314
290
|
def _export_ssm_parameters(self, db_name: str) -> None:
|
|
315
291
|
"""Export RDS connection info and credentials to SSM Parameter Store"""
|
|
@@ -413,37 +413,4 @@ class Route53Stack(IStack, StandardizedSsmMixin):
|
|
|
413
413
|
def _add_outputs(self) -> None:
|
|
414
414
|
"""Add CloudFormation outputs for the Route53 resources"""
|
|
415
415
|
# Hosted Zone ID
|
|
416
|
-
|
|
417
|
-
cdk.CfnOutput(
|
|
418
|
-
self,
|
|
419
|
-
"HostedZoneId",
|
|
420
|
-
value=self.hosted_zone.hosted_zone_id,
|
|
421
|
-
export_name=f"{self.deployment.build_resource_name('hosted-zone')}-id"
|
|
422
|
-
)
|
|
423
|
-
|
|
424
|
-
# Hosted Zone Name Servers
|
|
425
|
-
if hasattr(self.hosted_zone, "name_servers") and self.hosted_zone.name_servers:
|
|
426
|
-
cdk.CfnOutput(
|
|
427
|
-
self,
|
|
428
|
-
"NameServers",
|
|
429
|
-
value=",".join(self.hosted_zone.name_servers),
|
|
430
|
-
export_name=f"{self.deployment.build_resource_name('hosted-zone')}-name-servers"
|
|
431
|
-
)
|
|
432
|
-
|
|
433
|
-
# Certificate ARN
|
|
434
|
-
if self.certificate:
|
|
435
|
-
cdk.CfnOutput(
|
|
436
|
-
self,
|
|
437
|
-
"CertificateArn",
|
|
438
|
-
value=self.certificate.certificate_arn,
|
|
439
|
-
export_name=f"{self.deployment.build_resource_name('certificate')}-arn"
|
|
440
|
-
)
|
|
441
|
-
|
|
442
|
-
# Record names
|
|
443
|
-
for name, record in self.records.items():
|
|
444
|
-
cdk.CfnOutput(
|
|
445
|
-
self,
|
|
446
|
-
f"Record-{name}",
|
|
447
|
-
value=name,
|
|
448
|
-
export_name=f"{self.deployment.build_resource_name('record')}-{name}"
|
|
449
|
-
)
|
|
416
|
+
return
|
|
@@ -194,37 +194,7 @@ class SecurityGroupsStack(IStack, VPCProviderMixin):
|
|
|
194
194
|
description="Uptime Robot",
|
|
195
195
|
)
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
# Outputs (exports)
|
|
199
|
-
# =========================================================
|
|
200
|
-
cdk.CfnOutput(
|
|
201
|
-
self,
|
|
202
|
-
"WebFleetAlbSecurityGroupOut",
|
|
203
|
-
value=alb_sg.ref,
|
|
204
|
-
description="Web Fleet Application Load Balancer Security Group",
|
|
205
|
-
export_name=f"{self.deployment.environment}-{self.workload.name}-WebFleetAlbSecurityGroup",
|
|
206
|
-
)
|
|
207
|
-
cdk.CfnOutput(
|
|
208
|
-
self,
|
|
209
|
-
"WebFleetInstancesSecurityGroupOut",
|
|
210
|
-
value=web_fleet_sg.ref,
|
|
211
|
-
description="Web Fleet Instances Security Group",
|
|
212
|
-
export_name=f"{self.deployment.environment}-{self.workload.name}-WebFleetInstancesSecurityGroup",
|
|
213
|
-
)
|
|
214
|
-
cdk.CfnOutput(
|
|
215
|
-
self,
|
|
216
|
-
"MySqlDbSecurityGroupOut",
|
|
217
|
-
value=mysql_sg.ref,
|
|
218
|
-
description="MySql Security Group",
|
|
219
|
-
export_name=f"{self.deployment.environment}-{self.workload.name}-MySqlDbSecurityGroup",
|
|
220
|
-
)
|
|
221
|
-
cdk.CfnOutput(
|
|
222
|
-
self,
|
|
223
|
-
"WebMonitoringSecurityGroupOut",
|
|
224
|
-
value=monitoring_sg.ref,
|
|
225
|
-
description="Web Fleet Application Load Balancer Security Group",
|
|
226
|
-
export_name=f"{self.deployment.environment}-{self.workload.name}-WebMonitoringSecurityGroup",
|
|
227
|
-
)
|
|
197
|
+
|
|
228
198
|
|
|
229
199
|
# =========================================================
|
|
230
200
|
# SSM Parameter Store Exports
|
|
@@ -337,14 +337,7 @@ class SecurityGroupStack(IStack, VPCProviderMixin, StandardizedSsmMixin):
|
|
|
337
337
|
|
|
338
338
|
def _export_cfn_outputs(self, sg_name: str) -> None:
|
|
339
339
|
"""Add CloudFormation outputs for the Security Group"""
|
|
340
|
-
|
|
341
|
-
# Security Group ID
|
|
342
|
-
cdk.CfnOutput(
|
|
343
|
-
self,
|
|
344
|
-
f"{sg_name}-id",
|
|
345
|
-
value=self.security_group.security_group_id,
|
|
346
|
-
export_name=f"{self.deployment.build_resource_name(sg_name)}-id",
|
|
347
|
-
)
|
|
340
|
+
return
|
|
348
341
|
|
|
349
342
|
def _export_ssm_parameters(self, sg_name: str) -> None:
|
|
350
343
|
"""Add SSM parameters for the Security Group"""
|
|
@@ -131,37 +131,4 @@ class SQSStack(IStack):
|
|
|
131
131
|
|
|
132
132
|
def _add_outputs(self) -> None:
|
|
133
133
|
"""Add CloudFormation outputs for the SQS queues"""
|
|
134
|
-
|
|
135
|
-
# Queue ARN
|
|
136
|
-
cdk.CfnOutput(
|
|
137
|
-
self,
|
|
138
|
-
f"{queue_name}-arn",
|
|
139
|
-
value=queue.queue_arn,
|
|
140
|
-
export_name=f"{self.deployment.build_resource_name(queue_name)}-arn"
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
# Queue URL
|
|
144
|
-
cdk.CfnOutput(
|
|
145
|
-
self,
|
|
146
|
-
f"{queue_name}-url",
|
|
147
|
-
value=queue.queue_url,
|
|
148
|
-
export_name=f"{self.deployment.build_resource_name(queue_name)}-url"
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
# Also add outputs for DLQs
|
|
152
|
-
for dlq_name, dlq in self.dead_letter_queues.items():
|
|
153
|
-
# DLQ ARN
|
|
154
|
-
cdk.CfnOutput(
|
|
155
|
-
self,
|
|
156
|
-
f"{dlq_name}-arn",
|
|
157
|
-
value=dlq.queue_arn,
|
|
158
|
-
export_name=f"{self.deployment.build_resource_name(dlq_name)}-arn"
|
|
159
|
-
)
|
|
160
|
-
|
|
161
|
-
# DLQ URL
|
|
162
|
-
cdk.CfnOutput(
|
|
163
|
-
self,
|
|
164
|
-
f"{dlq_name}-url",
|
|
165
|
-
value=dlq.queue_url,
|
|
166
|
-
export_name=f"{self.deployment.build_resource_name(dlq_name)}-url"
|
|
167
|
-
)
|
|
134
|
+
return
|
|
@@ -241,115 +241,8 @@ class VpcStack(IStack, StandardizedSsmMixin):
|
|
|
241
241
|
|
|
242
242
|
def _add_outputs(self, vpc_name: str) -> None:
|
|
243
243
|
"""Add CloudFormation outputs for the VPC"""
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
# VPC outputs
|
|
248
|
-
# Use workload environment for consistency
|
|
249
|
-
workload_env = self.workload.dictionary.get("environment", self.deployment.environment)
|
|
250
|
-
workload_name = self.workload.dictionary.get("name", self.deployment.workload_name)
|
|
251
|
-
|
|
252
|
-
cdk.CfnOutput(
|
|
253
|
-
self,
|
|
254
|
-
f"{vpc_name}-VpcId",
|
|
255
|
-
value=self.vpc.vpc_id,
|
|
256
|
-
description=f"VPC ID for {vpc_name}",
|
|
257
|
-
export_name=f"{workload_name}-{workload_env}-vpc-id",
|
|
258
|
-
)
|
|
259
|
-
|
|
260
|
-
# Subnet outputs
|
|
261
|
-
public_subnet_ids = [subnet.subnet_id for subnet in self.vpc.public_subnets]
|
|
262
|
-
if public_subnet_ids:
|
|
263
|
-
cdk.CfnOutput(
|
|
264
|
-
self,
|
|
265
|
-
f"{vpc_name}-PublicSubnetIds",
|
|
266
|
-
value=",".join(public_subnet_ids),
|
|
267
|
-
description=f"Public subnet IDs for {vpc_name}",
|
|
268
|
-
export_name=f"{workload_name}-{workload_env}-public-subnet-ids",
|
|
269
|
-
)
|
|
270
|
-
|
|
271
|
-
private_subnet_ids = [subnet.subnet_id for subnet in self.vpc.private_subnets]
|
|
272
|
-
if private_subnet_ids:
|
|
273
|
-
cdk.CfnOutput(
|
|
274
|
-
self,
|
|
275
|
-
f"{vpc_name}-PrivateSubnetIds",
|
|
276
|
-
value=",".join(private_subnet_ids),
|
|
277
|
-
description=f"Private subnet IDs for {vpc_name}",
|
|
278
|
-
export_name=f"{workload_name}-{workload_env}-private-subnet-ids",
|
|
279
|
-
)
|
|
280
|
-
|
|
281
|
-
isolated_subnet_ids = [subnet.subnet_id for subnet in self.vpc.isolated_subnets]
|
|
282
|
-
if isolated_subnet_ids:
|
|
283
|
-
cdk.CfnOutput(
|
|
284
|
-
self,
|
|
285
|
-
f"{vpc_name}-IsolatedSubnetIds",
|
|
286
|
-
value=",".join(isolated_subnet_ids),
|
|
287
|
-
description=f"Isolated subnet IDs for {vpc_name}",
|
|
288
|
-
export_name=f"{workload_name}-{workload_env}-isolated-subnet-ids",
|
|
289
|
-
)
|
|
290
|
-
|
|
291
|
-
# Route table outputs - simplified to avoid route table access issues
|
|
292
|
-
# Skip route table outputs for now as they're causing CDK API issues
|
|
293
|
-
# public_route_table_ids = []
|
|
294
|
-
# if self.vpc.public_subnets:
|
|
295
|
-
# for subnet in self.vpc.public_subnets:
|
|
296
|
-
# # Access route table through the subnet's route table association
|
|
297
|
-
# for association in subnet.node.children:
|
|
298
|
-
# if hasattr(association, 'route_table_id') and association.route_table_id:
|
|
299
|
-
# public_route_table_ids.append(association.route_table_id)
|
|
300
|
-
#
|
|
301
|
-
# if public_route_table_ids:
|
|
302
|
-
# cdk.CfnOutput(
|
|
303
|
-
# self,
|
|
304
|
-
# f"{vpc_name}-PublicRouteTableIds",
|
|
305
|
-
# value=",".join(public_route_table_ids),
|
|
306
|
-
# description=f"Public route table IDs for {vpc_name}",
|
|
307
|
-
# export_name=f"{self.deployment.workload_name}-{self.deployment.environment}-public-route-table-ids",
|
|
308
|
-
# )
|
|
309
|
-
#
|
|
310
|
-
# private_route_table_ids = []
|
|
311
|
-
# if self.vpc.private_subnets:
|
|
312
|
-
# for subnet in self.vpc.private_subnets:
|
|
313
|
-
# # Access route table through the subnet's route table association
|
|
314
|
-
# for association in subnet.node.children:
|
|
315
|
-
# if hasattr(association, 'route_table_id') and association.route_table_id:
|
|
316
|
-
# private_route_table_ids.append(association.route_table_id)
|
|
317
|
-
#
|
|
318
|
-
# if private_route_table_ids:
|
|
319
|
-
# cdk.CfnOutput(
|
|
320
|
-
# self,
|
|
321
|
-
# f"{vpc_name}-PrivateRouteTableIds",
|
|
322
|
-
# value=",".join(private_route_table_ids),
|
|
323
|
-
# description=f"Private route table IDs for {vpc_name}",
|
|
324
|
-
# export_name=f"{self.deployment.workload_name}-{self.deployment.environment}-private-route-table-ids",
|
|
325
|
-
# )
|
|
326
|
-
|
|
327
|
-
# Internet Gateway output
|
|
328
|
-
if hasattr(self.vpc, 'internet_gateway_id') and self.vpc.internet_gateway_id:
|
|
329
|
-
cdk.CfnOutput(
|
|
330
|
-
self,
|
|
331
|
-
f"{vpc_name}-InternetGatewayId",
|
|
332
|
-
value=self.vpc.internet_gateway_id,
|
|
333
|
-
description=f"Internet Gateway ID for {vpc_name}",
|
|
334
|
-
export_name=f"{workload_name}-{workload_env}-internet-gateway-id",
|
|
335
|
-
)
|
|
336
|
-
|
|
337
|
-
# NAT Gateway outputs - simplified to avoid None values
|
|
338
|
-
nat_gateway_ids = []
|
|
339
|
-
for subnet in self.vpc.public_subnets:
|
|
340
|
-
if hasattr(subnet, 'node') and subnet.node:
|
|
341
|
-
for child in subnet.node.children:
|
|
342
|
-
if hasattr(child, 'nat_gateway_id') and child.nat_gateway_id:
|
|
343
|
-
nat_gateway_ids.append(child.nat_gateway_id)
|
|
344
|
-
|
|
345
|
-
if nat_gateway_ids:
|
|
346
|
-
cdk.CfnOutput(
|
|
347
|
-
self,
|
|
348
|
-
f"{vpc_name}-NatGatewayIds",
|
|
349
|
-
value=",".join(nat_gateway_ids),
|
|
350
|
-
description=f"NAT Gateway IDs for {vpc_name}",
|
|
351
|
-
export_name=f"{workload_name}-{workload_env}-nat-gateway-ids",
|
|
352
|
-
)
|
|
244
|
+
return
|
|
245
|
+
|
|
353
246
|
|
|
354
247
|
def _export_ssm_parameters(self) -> None:
|
|
355
248
|
"""Export SSM parameters using standardized approach"""
|
|
@@ -113,12 +113,16 @@ class StaticWebSiteStack(IStack):
|
|
|
113
113
|
self, stack_config: StackConfig, workload: WorkloadConfig
|
|
114
114
|
) -> str:
|
|
115
115
|
source = stack_config.dictionary.get("src", {}).get("path")
|
|
116
|
+
if not source:
|
|
117
|
+
raise ValueError("Source path is required for static website stack")
|
|
116
118
|
for base in workload.paths:
|
|
117
|
-
|
|
119
|
+
if base is None:
|
|
120
|
+
continue
|
|
121
|
+
candidate = Path(os.path.join(str(Path(base)), source)).resolve()
|
|
118
122
|
|
|
119
123
|
if candidate.exists():
|
|
120
124
|
return str(candidate)
|
|
121
|
-
raise ValueError(f"Could not find the source path: {source}")
|
|
125
|
+
raise ValueError(f"Could not find the source path for static site: {source}")
|
|
122
126
|
|
|
123
127
|
def __setup_cloudfront_distribution(
|
|
124
128
|
self,
|
cdk_factory/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.
|
|
1
|
+
__version__ = "0.19.13"
|
|
@@ -2,7 +2,7 @@ cdk_factory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
2
2
|
cdk_factory/app.py,sha256=RnX0-pwdTAPAdKJK_j13Zl8anf9zYKBwboR0KA8K8xM,10346
|
|
3
3
|
cdk_factory/cdk.json,sha256=SKZKhJ2PBpFH78j-F8S3VDYW-lf76--Q2I3ON-ZIQfw,3106
|
|
4
4
|
cdk_factory/cli.py,sha256=FGbCTS5dYCNsfp-etshzvFlGDCjC28r6rtzYbe7KoHI,6407
|
|
5
|
-
cdk_factory/version.py,sha256=
|
|
5
|
+
cdk_factory/version.py,sha256=qfLAZUWz8ZIxPUsFWlqQCfCwTNmUwrL2jNL4w6ZRFi0,24
|
|
6
6
|
cdk_factory/builds/README.md,sha256=9BBWd7bXpyKdMU_g2UljhQwrC9i5O_Tvkb6oPvndoZk,90
|
|
7
7
|
cdk_factory/commands/command_loader.py,sha256=QbLquuP_AdxtlxlDy-2IWCQ6D-7qa58aphnDPtp_uTs,3744
|
|
8
8
|
cdk_factory/configurations/base_config.py,sha256=eJ3Pl3GWk1jVr_bYQaaWlw4_-ZiFGaiXllI_fOOX1i0,9323
|
|
@@ -34,25 +34,25 @@ cdk_factory/configurations/resources/ecr.py,sha256=iJEtKqBT7vQU0LU4urIglraIR7cPZ
|
|
|
34
34
|
cdk_factory/configurations/resources/ecs_cluster.py,sha256=mQYJu7SUPDl5E4dMR6HCPFoWvFA3RGIb0iMNn-K7LX8,3635
|
|
35
35
|
cdk_factory/configurations/resources/ecs_service.py,sha256=bOWjVECd6Kbc5NGGSnDaopnKrjRsUfmaZ6-qrsmTs3Q,6468
|
|
36
36
|
cdk_factory/configurations/resources/exisiting.py,sha256=EVOLnkB-DGfTlmDgyQ5DD5k2zYfpFxqI3gugDR7mifI,478
|
|
37
|
-
cdk_factory/configurations/resources/lambda_edge.py,sha256=
|
|
37
|
+
cdk_factory/configurations/resources/lambda_edge.py,sha256=C0S6HrQe2QPfmhj1PhZ7FEnT2EidOg5t-pUFUsOzaDc,3855
|
|
38
38
|
cdk_factory/configurations/resources/lambda_function.py,sha256=VENZ9-ABJ5mjcN8J8wdLH4KHDYr1kWO0iFDH0B2mJXA,14659
|
|
39
39
|
cdk_factory/configurations/resources/lambda_layers.py,sha256=gVeP_-LC3Eq0lkPaG_JfFUwboM5evRPr99SfKj53m7A,633
|
|
40
40
|
cdk_factory/configurations/resources/lambda_triggers.py,sha256=MD7cdMNKEulNBhtMLIFnWJuJ5R-yyIqa0LHUgbSQerA,834
|
|
41
41
|
cdk_factory/configurations/resources/load_balancer.py,sha256=P-jKemIjIWWqScmQKspmRy1m3BrwNkRtTNHDStOAJds,5617
|
|
42
42
|
cdk_factory/configurations/resources/monitoring.py,sha256=CPYWbUbWQzoPqDhdPiB4Vahq-pPi6BEkavkVohadSIo,2422
|
|
43
|
-
cdk_factory/configurations/resources/rds.py,sha256=
|
|
43
|
+
cdk_factory/configurations/resources/rds.py,sha256=pX6uihguv1apYH93obcE4RloQDP48q5JHnYTnO39Pn0,15935
|
|
44
44
|
cdk_factory/configurations/resources/resource_mapping.py,sha256=cwv3n63RJ6E59ErsmSTdkW4i-g8huhHtKI0ExbRhJxA,2182
|
|
45
45
|
cdk_factory/configurations/resources/resource_naming.py,sha256=VE9S2cpzp11qqPL2z1sX79wXH0o1SntO2OG74nEmWC8,5508
|
|
46
46
|
cdk_factory/configurations/resources/resource_types.py,sha256=1WQHyDoErb-M-tETZZzyLDtbq_jdC85-I403dM48pgE,2317
|
|
47
47
|
cdk_factory/configurations/resources/route53.py,sha256=u63kw9cLBdOQrvxnULmopFqiArIYNvoWhrILNWvhD7w,3599
|
|
48
48
|
cdk_factory/configurations/resources/route53_hosted_zone.py,sha256=qjEYPCSxSOx5blr9EULv892ezxkCs--yrLa1ngWbyXM,880
|
|
49
49
|
cdk_factory/configurations/resources/rum.py,sha256=KgC2Mxhtr5XrICVXdgOXmxYp0GKu9lBs7izfG-Re9Ck,5294
|
|
50
|
-
cdk_factory/configurations/resources/s3.py,sha256=
|
|
50
|
+
cdk_factory/configurations/resources/s3.py,sha256=3RVGvHLEnxa-hCgDXsqZ9nq8Aic0zW0JVgMdybl95is,6407
|
|
51
51
|
cdk_factory/configurations/resources/security_group.py,sha256=8kQtaaRVEn2aDm8XoC7QFh2mDOFbPbgobmssIuqU8MA,2259
|
|
52
52
|
cdk_factory/configurations/resources/security_group_full_stack.py,sha256=CujSl6mfPlVO0Dxso8fDjwW5VZB0vbeP9HqbcTaM8H4,2657
|
|
53
53
|
cdk_factory/configurations/resources/sqs.py,sha256=fAh2dqttJ6PX46enFRULuiLEu3TEj0Vb2xntAOgUpYE,4346
|
|
54
54
|
cdk_factory/configurations/resources/vpc.py,sha256=_W77du9wf8SJM64JbEAxEOQYerOm6aw4YaSsE7A_kKE,4453
|
|
55
|
-
cdk_factory/constructs/cloudfront/cloudfront_distribution_construct.py,sha256=
|
|
55
|
+
cdk_factory/constructs/cloudfront/cloudfront_distribution_construct.py,sha256=WbbI37Ez262kffJNNpvyjXtFwOQlNfRql0NGBCLjpgE,25775
|
|
56
56
|
cdk_factory/constructs/ecr/ecr_construct.py,sha256=jEimLwLvO5ERuFEn_L2q2pyPKgkdHQ6Oi7Sy990ttSg,11002
|
|
57
57
|
cdk_factory/constructs/lambdas/lambda_function_construct.py,sha256=SQ5SEXn4kezVAzXuv_A_JB3o_svyBXOMi-htvfB9HQs,4516
|
|
58
58
|
cdk_factory/constructs/lambdas/lambda_function_docker_construct.py,sha256=O8aiHpNQ59eE3qEttEHVxbvp06v4byXOeYCVTAOI_Cg,9993
|
|
@@ -83,42 +83,42 @@ cdk_factory/stack/stack_modules.py,sha256=kgEK-j0smZPozVwTCfM1g1V17EyTBT0TXAQZq4
|
|
|
83
83
|
cdk_factory/stack_library/__init__.py,sha256=_v4kz9EYAjox6strrTK_4fb9GloJ2Kyhf63VRPivl2U,638
|
|
84
84
|
cdk_factory/stack_library/stack_base.py,sha256=Cu3qeqPQf33QaaXoxk_EaziNCIXcyspOo5AU3eX_wyM,5140
|
|
85
85
|
cdk_factory/stack_library/acm/__init__.py,sha256=4FNRLykblcKZvq_wieYwvv9N_jgrZnJ7ECH9xKh-0Ls,81
|
|
86
|
-
cdk_factory/stack_library/acm/acm_stack.py,sha256=
|
|
86
|
+
cdk_factory/stack_library/acm/acm_stack.py,sha256=LW4QgzcMDvtSpqwfc4ykgpzDGvXe4udvWVE_DtBN4Zg,5414
|
|
87
87
|
cdk_factory/stack_library/api_gateway/api_gateway_stack.py,sha256=PvLdGvcopGpLP0FwpfUcfXNiTIfYLTXqrG-TniE38yc,39643
|
|
88
88
|
cdk_factory/stack_library/auto_scaling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
89
|
-
cdk_factory/stack_library/auto_scaling/auto_scaling_stack.py,sha256=
|
|
89
|
+
cdk_factory/stack_library/auto_scaling/auto_scaling_stack.py,sha256=G8OOgTAfsTDVArvuDfzuNpuGHzqz8kREHnnkMtjulAQ,25334
|
|
90
90
|
cdk_factory/stack_library/aws_lambdas/lambda_stack.py,sha256=SFbBPvvCopbyiuYtq-O5sQkFCf94Wzua6aDUXiFDSB4,26161
|
|
91
91
|
cdk_factory/stack_library/buckets/README.md,sha256=XkK3UNVtRLE7NtUvbhCOBBYUYi8hlrrSaI1s3GJVrqI,78
|
|
92
92
|
cdk_factory/stack_library/buckets/bucket_stack.py,sha256=SLoZqSffAqmeBBEVUQg54D_8Ad5UKdkjEAmKAVgAqQo,1778
|
|
93
93
|
cdk_factory/stack_library/cloudfront/__init__.py,sha256=Zfx50q4xIJ4ZEoVIzUBDTKbRE9DKDM6iyVIFhtQXvww,153
|
|
94
|
-
cdk_factory/stack_library/cloudfront/cloudfront_stack.py,sha256=
|
|
95
|
-
cdk_factory/stack_library/code_artifact/code_artifact_stack.py,sha256=
|
|
94
|
+
cdk_factory/stack_library/cloudfront/cloudfront_stack.py,sha256=7cYPqoQyiXH6r3j9jp9oLXv1ZDixeCYPAXJtTOmagPc,32309
|
|
95
|
+
cdk_factory/stack_library/code_artifact/code_artifact_stack.py,sha256=o86cmC_ZV82z-K7DoAR0u1nAieoTi-vxRF01tyJn-9M,5297
|
|
96
96
|
cdk_factory/stack_library/cognito/cognito_stack.py,sha256=3tjKCNcIwXZn7fd4EDQdY6H9m6CnZohI4uTQ4TpacRQ,25327
|
|
97
97
|
cdk_factory/stack_library/dynamodb/dynamodb_stack.py,sha256=-_Ij1zXIxUuZIWgdevam_1vD3LEJ6pFs9U0hmw0KwIw,6743
|
|
98
98
|
cdk_factory/stack_library/ecr/README.md,sha256=xw2wPx9WN03Y4BBwqvbi9lAFGNyaD1FUNpqxVJX14Oo,179
|
|
99
99
|
cdk_factory/stack_library/ecr/ecr_stack.py,sha256=KLbd5WN5-ZiojsS5wJ4PX-tIL0cCylCSvXjO6sVrgWY,2102
|
|
100
100
|
cdk_factory/stack_library/ecs/__init__.py,sha256=o5vGDtD_h-gVXb3-Ysr8xUNpEcMsnmMVgZv2Pupcdow,219
|
|
101
101
|
cdk_factory/stack_library/ecs/ecs_cluster_stack.py,sha256=sAPTLU5CAwMoLTW_pNy_cd0OtVkfDR7IxxsSq5AE0yo,12091
|
|
102
|
-
cdk_factory/stack_library/ecs/ecs_service_stack.py,sha256=
|
|
102
|
+
cdk_factory/stack_library/ecs/ecs_service_stack.py,sha256=KB4YCIsMm5JIGM9Bm-bKcr3eX5xXFgnoA7jST_ekK44,28209
|
|
103
103
|
cdk_factory/stack_library/lambda_edge/__init__.py,sha256=ByBJ_CWdc4UtTmFBZH-6pzBMNkjkdtE65AmnB0Fs6lM,156
|
|
104
|
-
cdk_factory/stack_library/lambda_edge/lambda_edge_stack.py,sha256=
|
|
104
|
+
cdk_factory/stack_library/lambda_edge/lambda_edge_stack.py,sha256=eHh_k4mbNp1prEnNvKqfK82lLNrMZS-7HAaUYzFEoOU,21040
|
|
105
105
|
cdk_factory/stack_library/load_balancer/__init__.py,sha256=wZpKw2OecLJGdF5mPayCYAEhu2H3c2gJFFIxwXftGDU,52
|
|
106
|
-
cdk_factory/stack_library/load_balancer/load_balancer_stack.py,sha256=
|
|
106
|
+
cdk_factory/stack_library/load_balancer/load_balancer_stack.py,sha256=ApW5q3SAvSJtiK0RInNljmubqXqKZU5QBAaUoeIW-pM,28287
|
|
107
107
|
cdk_factory/stack_library/monitoring/__init__.py,sha256=k1G_KDx47Aw0UugaL99PN_TKlyLK4nkJVApCaAK7GJg,153
|
|
108
108
|
cdk_factory/stack_library/monitoring/monitoring_stack.py,sha256=N_1YvEXE7fboH_S3kv_dSKZsufxMuPdFMjGzlNFpuSo,19283
|
|
109
109
|
cdk_factory/stack_library/rds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
110
|
-
cdk_factory/stack_library/rds/rds_stack.py,sha256=
|
|
110
|
+
cdk_factory/stack_library/rds/rds_stack.py,sha256=VToW-uFKAfilyhN4T8-TXaFW8f_VuXEIuUoBHvDN0Ns,14398
|
|
111
111
|
cdk_factory/stack_library/route53/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
112
|
-
cdk_factory/stack_library/route53/route53_stack.py,sha256=
|
|
112
|
+
cdk_factory/stack_library/route53/route53_stack.py,sha256=taREOw-s7i1NZcdR-za1lKkj-Cj8UPmr4BO5txS18fI,18348
|
|
113
113
|
cdk_factory/stack_library/rum/__init__.py,sha256=gUrWQdzd4rZ2J0YzAQC8PsEGAS7QgyYjB2ZCUKWasy4,90
|
|
114
114
|
cdk_factory/stack_library/rum/rum_stack.py,sha256=c67m0Jbyx8hx9TTx9TBBhZMDqtSK7QCqKx_Ec1t8LgY,14067
|
|
115
115
|
cdk_factory/stack_library/security_group/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
116
|
-
cdk_factory/stack_library/security_group/security_group_full_stack.py,sha256=
|
|
117
|
-
cdk_factory/stack_library/security_group/security_group_stack.py,sha256=
|
|
118
|
-
cdk_factory/stack_library/simple_queue_service/sqs_stack.py,sha256=
|
|
116
|
+
cdk_factory/stack_library/security_group/security_group_full_stack.py,sha256=Y9JYD0QpKNe11fuCPjWlV1rucX1DMm7bs8Eu4t4XDqw,12204
|
|
117
|
+
cdk_factory/stack_library/security_group/security_group_stack.py,sha256=uthk_MX2gNfA6a7gR7PjEfjov4WgTTtJ09G0cJOFWko,14168
|
|
118
|
+
cdk_factory/stack_library/simple_queue_service/sqs_stack.py,sha256=HSJgWo4Wl6nQ5rJFQXOkDTyd_6PuHhx5VyaZLVvmYM8,4891
|
|
119
119
|
cdk_factory/stack_library/vpc/__init__.py,sha256=7pIqP97Gf2AJbv9Ebp1WbQGHYhgEbWJ52L1MzeXBybA,42
|
|
120
|
-
cdk_factory/stack_library/vpc/vpc_stack.py,sha256=
|
|
121
|
-
cdk_factory/stack_library/websites/static_website_stack.py,sha256=
|
|
120
|
+
cdk_factory/stack_library/vpc/vpc_stack.py,sha256=8uFyPIhAu-4A3iclTFlOiJrEZuYu67gI5UtiDSzmFF4,14461
|
|
121
|
+
cdk_factory/stack_library/websites/static_website_stack.py,sha256=twpR9y4bxDx2GcEn0uP8PFNbsrgb8G9juZfeuHj7VqE,11433
|
|
122
122
|
cdk_factory/stages/websites/static_website_stage.py,sha256=X4fpKXkhb0zIbSHx3QyddBhVSLBryb1vf1Cg2fMTqog,755
|
|
123
123
|
cdk_factory/templates/README.md,sha256=ATBEjG6beYvbEAdLtZ_8xnxgFD5X0cgZoI_6pToqH90,2679
|
|
124
124
|
cdk_factory/templates/app.py.template,sha256=aM60x0nNV80idtCL8jm1EddY63F5tDITYOlavg-BPMU,1069
|
|
@@ -136,8 +136,8 @@ cdk_factory/utilities/os_execute.py,sha256=5Op0LY_8Y-pUm04y1k8MTpNrmQvcLmQHPQITE
|
|
|
136
136
|
cdk_factory/utils/api_gateway_utilities.py,sha256=If7Xu5s_UxmuV-kL3JkXxPLBdSVUKoLtohm0IUFoiV8,4378
|
|
137
137
|
cdk_factory/validation/config_validator.py,sha256=Pb0TkLiPFzUplBOgMorhRCVm08vEzZhRU5xXCDTa5CA,17602
|
|
138
138
|
cdk_factory/workload/workload_factory.py,sha256=yDI3cRhVI5ELNDcJPLpk9UY54Uind1xQoV3spzT4z7E,6068
|
|
139
|
-
cdk_factory-0.
|
|
140
|
-
cdk_factory-0.
|
|
141
|
-
cdk_factory-0.
|
|
142
|
-
cdk_factory-0.
|
|
143
|
-
cdk_factory-0.
|
|
139
|
+
cdk_factory-0.19.13.dist-info/METADATA,sha256=Rw6GGM7Hl5-md3ntKrGRfX2u1ppfZRfIextBHMW-FsE,2452
|
|
140
|
+
cdk_factory-0.19.13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
141
|
+
cdk_factory-0.19.13.dist-info/entry_points.txt,sha256=S1DPe0ORcdiwEALMN_WIo3UQrW_g4YdQCLEsc_b0Swg,53
|
|
142
|
+
cdk_factory-0.19.13.dist-info/licenses/LICENSE,sha256=NOtdOeLwg2il_XBJdXUPFPX8JlV4dqTdDGAd2-khxT8,1066
|
|
143
|
+
cdk_factory-0.19.13.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|