diff --git a/ecs_composex/acm/acm_stack.py b/ecs_composex/acm/acm_stack.py index 99d206bd..b28c2e92 100644 --- a/ecs_composex/acm/acm_stack.py +++ b/ecs_composex/acm/acm_stack.py @@ -158,6 +158,8 @@ def __init__( stack_template = build_template("ACM Certificates created from x-acm") super().__init__(name, stack_template, module=module, **kwargs) define_acm_certs(module.new_resources, self) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True if module.lookup_resources: diff --git a/ecs_composex/alarms/alarms_stack.py b/ecs_composex/alarms/alarms_stack.py index f8888a0b..a9026a96 100644 --- a/ecs_composex/alarms/alarms_stack.py +++ b/ecs_composex/alarms/alarms_stack.py @@ -122,6 +122,8 @@ def __init__( ) super().__init__(name, stack_template=template, **kwargs) create_alarms(template, self, module.new_resources, settings) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True if module.lookup_resources: diff --git a/ecs_composex/aps/aps_stack.py b/ecs_composex/aps/aps_stack.py index 97c529e6..12e8e0e4 100644 --- a/ecs_composex/aps/aps_stack.py +++ b/ecs_composex/aps/aps_stack.py @@ -193,6 +193,8 @@ def __init__( ) super().__init__(title, stack_template, **kwargs) set_new_aps(module.new_resources, stack_template, self) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True if module.lookup_resources: diff --git a/ecs_composex/codeguru_profiler/codeguru_profiler_stack.py b/ecs_composex/codeguru_profiler/codeguru_profiler_stack.py index c93f5dbd..80343cf6 100644 --- a/ecs_composex/codeguru_profiler/codeguru_profiler_stack.py +++ b/ecs_composex/codeguru_profiler/codeguru_profiler_stack.py @@ -141,6 +141,8 @@ def __init__( if module.new_resources: stack_template = create_root_template(module.new_resources, module.res_key) super().__init__(title, stack_template, **kwargs) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True diff --git a/ecs_composex/common/stacks/__init__.py b/ecs_composex/common/stacks/__init__.py index a365d28a..6b43e66b 100644 --- a/ecs_composex/common/stacks/__init__.py +++ b/ecs_composex/common/stacks/__init__.py @@ -99,6 +99,7 @@ def __init__( :param kwargs: kwargs from composex along with the kwargs for the stack """ self.name = name + self._deletion_policy: str = "Delete" self.parent_stack = None if module_name is None: self.module_name = path.basename(path.dirname(path.abspath(__file__))) diff --git a/ecs_composex/efs/efs_stack.py b/ecs_composex/efs/efs_stack.py index 5f2bb7f0..3d916092 100644 --- a/ecs_composex/efs/efs_stack.py +++ b/ecs_composex/efs/efs_stack.py @@ -151,6 +151,8 @@ def __init__( if module.new_resources: stack_template = create_efs_stack(settings, module.new_resources) super().__init__(name, stack_template, **kwargs) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True if module.lookup_resources: diff --git a/ecs_composex/elasticache/elasticache_stack.py b/ecs_composex/elasticache/elasticache_stack.py index 8ec9f2d8..f0d2cac4 100644 --- a/ecs_composex/elasticache/elasticache_stack.py +++ b/ecs_composex/elasticache/elasticache_stack.py @@ -20,11 +20,6 @@ from troposphere.ssm import Parameter as SSMParameter from ecs_composex.common.stacks import ComposeXStack -from ecs_composex.compose.x_resources.helpers import ( - set_lookup_resources, - set_new_resources, - set_resources, -) from ecs_composex.compose.x_resources.network_x_resources import NetworkXResource from ecs_composex.elasticache.elasticache_ecs import create_lookup_mappings from ecs_composex.elasticache.elasticache_params import ( @@ -242,6 +237,8 @@ def __init__( if module.new_resources: stack_template = create_root_template(module.new_resources) super().__init__(title, stack_template, **kwargs) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True diff --git a/ecs_composex/elbv2/elbv2_stack/__init__.py b/ecs_composex/elbv2/elbv2_stack/__init__.py index 2371c40e..490b0b37 100644 --- a/ecs_composex/elbv2/elbv2_stack/__init__.py +++ b/ecs_composex/elbv2/elbv2_stack/__init__.py @@ -63,5 +63,7 @@ def __init__( resource.sort_alb_ingress(settings, stack_template) super().__init__(title, stack_template, stack_parameters=lb_input, **kwargs) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) for resource in module.resources_list: resource.stack = self diff --git a/ecs_composex/events/events_stack.py b/ecs_composex/events/events_stack.py index a47ffa7b..c91ab8c0 100644 --- a/ecs_composex/events/events_stack.py +++ b/ecs_composex/events/events_stack.py @@ -176,6 +176,9 @@ def __init__( ) super().__init__(title, stack_template, **kwargs) create_events_template(self, settings, module.new_resources) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) + else: self.is_void = True diff --git a/ecs_composex/kinesis/kinesis_stack.py b/ecs_composex/kinesis/kinesis_stack.py index 75e74ae2..ebb5967e 100644 --- a/ecs_composex/kinesis/kinesis_stack.py +++ b/ecs_composex/kinesis/kinesis_stack.py @@ -204,6 +204,8 @@ def __init__( if module.new_resources: stack_template = create_streams_template(module.new_resources, settings) super().__init__(title, stack_template, **kwargs) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True for resource in module.resources_list: diff --git a/ecs_composex/kinesis_firehose/kinesis_firehose_stack.py b/ecs_composex/kinesis_firehose/kinesis_firehose_stack.py index 0549f9d2..616cccad 100644 --- a/ecs_composex/kinesis_firehose/kinesis_firehose_stack.py +++ b/ecs_composex/kinesis_firehose/kinesis_firehose_stack.py @@ -25,11 +25,6 @@ from ecs_composex.compose.x_resources.environment_x_resources import ( AwsEnvironmentResource, ) -from ecs_composex.compose.x_resources.helpers import ( - set_lookup_resources, - set_new_resources, - set_resources, -) from ecs_composex.iam.iam_stack import ResourceIamManager from ecs_composex.kinesis_firehose.kinesis_firehose_params import ( FIREHOSE_ARN, @@ -187,6 +182,8 @@ def __init__( if module.new_resources: stack_template = create_streams_template(module.new_resources) super().__init__(title, stack_template, **kwargs) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True for resource in module.resources_list: diff --git a/ecs_composex/kms/kms_stack.py b/ecs_composex/kms/kms_stack.py index b4342f86..3ed5ba70 100644 --- a/ecs_composex/kms/kms_stack.py +++ b/ecs_composex/kms/kms_stack.py @@ -27,11 +27,6 @@ from ecs_composex.compose.x_resources.environment_x_resources import ( AwsEnvironmentResource, ) -from ecs_composex.compose.x_resources.helpers import ( - set_lookup_resources, - set_new_resources, - set_resources, -) from ecs_composex.kinesis_firehose.kinesis_firehose_stack import DeliveryStream from ecs_composex.kms import metadata from ecs_composex.kms.kms_ecs_cluster import handle_ecs_cluster @@ -239,6 +234,8 @@ def __init__( stack_template = build_template("Root template for KMS") super().__init__(title, stack_template, **kwargs) create_kms_template(stack_template, module.new_resources, self) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True if module.lookup_resources: diff --git a/ecs_composex/mods_manager.py b/ecs_composex/mods_manager.py index f8c8daba..20c83150 100644 --- a/ecs_composex/mods_manager.py +++ b/ecs_composex/mods_manager.py @@ -32,13 +32,14 @@ NetworkXResource, DatabaseXResource, ) + import re from collections import OrderedDict from copy import deepcopy from importlib import import_module from json import loads -from compose_x_common.compose_x_common import keyisset +from compose_x_common.compose_x_common import keyisset, set_else_none from ecs_composex.common import NONALPHANUM from ecs_composex.common.ecs_composex import X_KEY @@ -80,6 +81,7 @@ def __init__( if definition: self.definition = definition self._original_definition = deepcopy(definition) + self.module_deletion_policy: str = "Delete" def __del__(self): if hasattr(self, "_resources") and self._resources: @@ -255,6 +257,9 @@ def set_resources(self, settings: ComposeXSettings): key=lambda item: item[0], ) ) + if keyisset("DeletionPolicy", _resources): + self.module_deletion_policy = _resources["DeletionPolicy"] + del _resources["DeletionPolicy"] if not self._original_definition: self._original_definition = {self.res_key: dict(_resources)} for resource_name, resource_definition in _resources.items(): diff --git a/ecs_composex/neptune/neptune_stack.py b/ecs_composex/neptune/neptune_stack.py index d8558d11..3f33e919 100644 --- a/ecs_composex/neptune/neptune_stack.py +++ b/ecs_composex/neptune/neptune_stack.py @@ -20,11 +20,6 @@ from ecs_composex.common.logging import LOG from ecs_composex.common.stacks import ComposeXStack from ecs_composex.common.troposphere_tools import build_template -from ecs_composex.compose.x_resources.helpers import ( - set_lookup_resources, - set_new_resources, - set_resources, -) from ecs_composex.compose.x_resources.network_x_resources import DatabaseXResource from ecs_composex.neptune.neptune_params import ( DB_CLUSTER_RESOURCES_ARN, @@ -33,7 +28,6 @@ DB_READ_ENDPOINT, DB_RESOURCE_ID, ) -from ecs_composex.neptune.neptune_template import create_neptune_template from ecs_composex.rds.rds_params import DB_CLUSTER_ARN, DB_CLUSTER_NAME, DB_SG from ecs_composex.rds_resources_settings import ( handle_new_tcp_resource, @@ -260,6 +254,8 @@ def __init__( create_neptune_template( stack_template, module.new_resources, settings, self ) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True diff --git a/ecs_composex/opensearch/opensearch_stack.py b/ecs_composex/opensearch/opensearch_stack.py index d2f054d7..67422832 100644 --- a/ecs_composex/opensearch/opensearch_stack.py +++ b/ecs_composex/opensearch/opensearch_stack.py @@ -14,11 +14,6 @@ from ecs_composex.common.stacks import ComposeXStack from ecs_composex.common.troposphere_tools import build_template -from ecs_composex.compose.x_resources.helpers import ( - set_lookup_resources, - set_new_resources, - set_resources, -) from ecs_composex.compose.x_resources.network_x_resources import DatabaseXResource from ecs_composex.opensearch.opensearch_aws import create_opensearch_mappings from ecs_composex.opensearch.opensearch_params import ( @@ -178,6 +173,8 @@ def __init__( ) super().__init__(title, stack_template, **kwargs) create_new_domains(module.new_resources, self) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True diff --git a/ecs_composex/rds/rds_stack.py b/ecs_composex/rds/rds_stack.py index 6d89abbb..469d33ce 100644 --- a/ecs_composex/rds/rds_stack.py +++ b/ecs_composex/rds/rds_stack.py @@ -265,7 +265,8 @@ def __init__( super().__init__(title, stack_template, **kwargs) generate_rds_templates(self, stack_template, module.new_resources, settings) self.parent_stack = settings.root_stack - # self.mark_nested_stacks() + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True if module.lookup_resources and module.mapping_key not in settings.mappings: diff --git a/ecs_composex/rds/rds_template.py b/ecs_composex/rds/rds_template.py index 72b4c8bb..94b644a1 100644 --- a/ecs_composex/rds/rds_template.py +++ b/ecs_composex/rds/rds_template.py @@ -36,6 +36,8 @@ def __init__(self, name, stack_template, db, rds_stack, **kwargs): super().__init__(name, stack_template, **kwargs) self.parent_stack = rds_stack db.stack = self + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", db.module.module_deletion_policy) def add_db_stack(root_template, db, settings, rds_stack): diff --git a/ecs_composex/route53/route53_stack.py b/ecs_composex/route53/route53_stack.py index 2289cde0..64cb5a7a 100644 --- a/ecs_composex/route53/route53_stack.py +++ b/ecs_composex/route53/route53_stack.py @@ -211,5 +211,7 @@ def __init__( self.is_void = True stack_template = build_template(module.res_key) super().__init__(module.mapping_key, stack_template, **kwargs) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) for resource in module.resources_list: resource.stack = self diff --git a/ecs_composex/s3/s3_stack.py b/ecs_composex/s3/s3_stack.py index f4603c7d..5a3fea77 100644 --- a/ecs_composex/s3/s3_stack.py +++ b/ecs_composex/s3/s3_stack.py @@ -139,6 +139,8 @@ def __init__( super().__init__(module.mapping_key, stack_template, **kwargs) create_s3_template(module.new_resources, stack_template) self.parent_stack = settings.root_stack + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True for resource in module.resources_list: diff --git a/ecs_composex/sns/sns_stack.py b/ecs_composex/sns/sns_stack.py index 50923426..2a919aec 100644 --- a/ecs_composex/sns/sns_stack.py +++ b/ecs_composex/sns/sns_stack.py @@ -66,5 +66,7 @@ def __init__( template = build_template(f"{module.res_key} - stack") import_sns_topics_to_template(module.new_resources, template) super().__init__(module.mapping_key, stack_template=template, **kwargs) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) for resource in module.resources_list: resource.stack = self diff --git a/ecs_composex/sqs/sqs_stack.py b/ecs_composex/sqs/sqs_stack.py index 942be949..873fd9df 100644 --- a/ecs_composex/sqs/sqs_stack.py +++ b/ecs_composex/sqs/sqs_stack.py @@ -119,6 +119,8 @@ def __init__( ) super().__init__(title, stack_template=template, **kwargs) render_new_queues(settings, module.new_resources, self, template) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True for resource in module.resources_list: diff --git a/ecs_composex/ssm_parameter/ssm_parameter_stack.py b/ecs_composex/ssm_parameter/ssm_parameter_stack.py index 0f2b5327..29db44f7 100644 --- a/ecs_composex/ssm_parameter/ssm_parameter_stack.py +++ b/ecs_composex/ssm_parameter/ssm_parameter_stack.py @@ -110,6 +110,8 @@ def __init__( template = build_template("Parent template for SSM in ECS Compose-X") super().__init__(module.mapping_key, stack_template=template, **kwargs) render_new_parameters(module.new_resources, self) + if not hasattr(self, "DeletionPolicy"): + setattr(self, "DeletionPolicy", module.module_deletion_policy) else: self.is_void = True for resource in module.resources_list: diff --git a/use-cases/s3/simple_s3_bucket.yml b/use-cases/s3/simple_s3_bucket.yml index 8aeab395..19a38dc3 100644 --- a/use-cases/s3/simple_s3_bucket.yml +++ b/use-cases/s3/simple_s3_bucket.yml @@ -1,6 +1,7 @@ version: "3.8" x-s3: + DeletionPolicy: Retain bucket-01: Properties: BucketName: bucket-01