diff --git a/CHANGELOG.md b/CHANGELOG.md index edd59a0..29a2428 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.1.2] - 2024-07-25 + +### Added + +- Support for new regions - China (Beijing), China (Ningxia), and GovCloud. + +### Fixed + +- Handling of case insensitivity of "Path" in ArchiveDescription Json parsing [#4](https://github.com/aws-solutions/data-transfer-from-amazon-s3-glacier-vaults-to-amazon-s3/pull/4). + ## [1.1.1] - 2024-05-13 ### Updated diff --git a/README.md b/README.md index 8ffa8b5..655a531 100644 --- a/README.md +++ b/README.md @@ -168,6 +168,10 @@ generated using AWS CDK, for further information on CDK please refer to the This solution collects anonymous operational metrics to help AWS improve the quality and features of the solution. For more information, including how to disable this capability, please see the [implementation guide](https://docs.aws.amazon.com/solutions/latest/instance-scheduler-on-aws/anonymized-data.html). + +## External Contributors +[@diegokodify](https://github.com/diegokodify) for [#4](https://github.com/aws-solutions/data-transfer-from-amazon-s3-glacier-vaults-to-amazon-s3/pull/4). + --- Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/cdk.json b/cdk.json index 08a8dfa..afaa658 100644 --- a/cdk.json +++ b/cdk.json @@ -41,7 +41,7 @@ "SOLUTION_NAME": "Data transfer from Amazon S3 Glacier vaults to Amazon S3", "APP_REGISTRY_NAME": "data_retrieval_for_amazon_glacier_s3", "SOLUTION_ID": "SO0293", - "SOLUTION_VERSION": "v1.1.1", + "SOLUTION_VERSION": "v1.1.2", "APPLICATION_TYPE": "AWS-Solutions" } } diff --git a/pyproject.toml b/pyproject.toml index 29952f7..c919412 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ package-dir = {"" = "source"} [project] name = "solution" -version = "1.1.1" +version = "1.1.2" description = "Data transfer from Amazon S3 Glacier vaults to Amazon S3" readme = "README.md" requires-python = ">=3.10" diff --git a/solution-manifest.yaml b/solution-manifest.yaml index 6e86858..d062cc7 100644 --- a/solution-manifest.yaml +++ b/solution-manifest.yaml @@ -1,7 +1,7 @@ --- id: SO0293 # Solution Id name: data-transfer-from-amazon-s3-glacier-vaults-to-amazon-s3 # trademarked name -version: v1.1.1 # current version of the solution. Used to verify template headers +version: v1.1.2 # current version of the solution. Used to verify template headers cloudformation_templates: # This list should match with AWS CloudFormation templates section of IG - template: data-transfer-from-amazon-s3-glacier-vaults-to-amazon-s3.template main_template: true diff --git a/source/solution/app.py b/source/solution/app.py index c9edf0d..797639d 100644 --- a/source/solution/app.py +++ b/source/solution/app.py @@ -9,7 +9,10 @@ import aws_cdk as cdk -from solution.infrastructure.aspects.app_registry import AppRegistry +from solution.infrastructure.aspects.app_registry import ( + AppRegistry, + AppRegistryCondition, +) from solution.infrastructure.stack import SolutionStack from solution.mocking.mock_glacier_stack import MockGlacierStack from solution.pipeline.stack import PipelineStack @@ -41,6 +44,13 @@ def _load_cdk_context() -> Any: return config.get("context", {}) +def _setup_app_registry(app: cdk.App, stack: SolutionStack) -> None: + app_registry = AppRegistry(stack, "AppRegistryAspect") + app_registry_condition = AppRegistryCondition(stack, "AppRegistryConditionAspect") + cdk.Aspects.of(app_registry).add(app_registry_condition) + cdk.Aspects.of(app).add(app_registry) + + def main() -> None: app = cdk.App(context=_load_cdk_context()) solution_stack = SolutionStack( @@ -48,7 +58,7 @@ def main() -> None: "data-transfer-from-amazon-s3-glacier-vaults-to-amazon-s3", synthesizer=synthesizer, ) - cdk.Aspects.of(app).add(AppRegistry(solution_stack, "AppRegistryAspect")) + _setup_app_registry(app, solution_stack) PipelineStack(app, "pipeline") MockGlacierStack(app, "mock-glacier") app.synth() diff --git a/source/solution/infrastructure/aspects/app_registry.py b/source/solution/infrastructure/aspects/app_registry.py index 012cadd..21b958c 100644 --- a/source/solution/infrastructure/aspects/app_registry.py +++ b/source/solution/infrastructure/aspects/app_registry.py @@ -6,12 +6,29 @@ from typing import Optional import jsii -from aws_cdk import Aws, CfnResource, Fn, IAspect, Stack, Tags +from aws_cdk import Aws, CfnCondition, CfnResource, Fn, IAspect, Stack, Tags from aws_cdk import aws_applicationinsights as applicationinsights from aws_cdk import aws_servicecatalogappregistry_alpha as appreg from constructs import Construct, IConstruct +@jsii.implements(IAspect) +class AppRegistryCondition(Construct): + def __init__(self, scope: Construct, id: str): + super().__init__(scope, id) + self.deploy_if_not_china_partition = CfnCondition( + self, + "DeployIfNotChinaPartition", + expression=Fn.condition_not(Fn.condition_equals(Aws.PARTITION, "aws-cn")), + ) + + def visit(self, node: IConstruct) -> None: + if isinstance(node, CfnResource): + node.add_override( + "Condition", self.deploy_if_not_china_partition.logical_id + ) + + @jsii.implements(IAspect) class AppRegistry(Construct): """This construct creates the resources required for AppRegistry and injects them as Aspects""" diff --git a/source/solution/infrastructure/glue_helper/scripts/archive_naming.py b/source/solution/infrastructure/glue_helper/scripts/archive_naming.py index d993eb4..909c005 100644 --- a/source/solution/infrastructure/glue_helper/scripts/archive_naming.py +++ b/source/solution/infrastructure/glue_helper/scripts/archive_naming.py @@ -47,7 +47,7 @@ def parse_description(archive_description: str) -> str: if re.search(r"{\s*\\*\".*}\s*", archive_description): try: json_object = json.loads(archive_description) - path = json_object.get("Path") + path = json_object.get("Path") or json_object.get("path") if isinstance(path, str): return path except Exception as _: diff --git a/source/solution/infrastructure/glue_helper/scripts/metric_collection_script.py b/source/solution/infrastructure/glue_helper/scripts/metric_collection_script.py index 3825bfa..eeff2c9 100644 --- a/source/solution/infrastructure/glue_helper/scripts/metric_collection_script.py +++ b/source/solution/infrastructure/glue_helper/scripts/metric_collection_script.py @@ -8,7 +8,7 @@ import boto3 from botocore.config import Config -__boto_config__ = Config(user_agent_extra="AwsSolution/SO0293/v1.1.1") +__boto_config__ = Config(user_agent_extra="AwsSolution/SO0293/v1.1.2") def update_metric_table( diff --git a/source/solution/infrastructure/helpers/solutions_function.py b/source/solution/infrastructure/helpers/solutions_function.py index 25eabc0..e4634a2 100644 --- a/source/solution/infrastructure/helpers/solutions_function.py +++ b/source/solution/infrastructure/helpers/solutions_function.py @@ -4,7 +4,7 @@ """ import logging -from typing import Any +from typing import Any, Optional import aws_cdk.aws_iam as iam from aws_cdk import Aws, CfnCondition, Fn @@ -14,7 +14,8 @@ from solution.application.util.exceptions import ResourceNotFound -DEFAULT_RUNTIME = Runtime.PYTHON_3_12 +DEFAULT_RUNTIME = "python3.12" +GOV_CN_RUNTIME = "python3.11" class SolutionsPythonFunction(Function): @@ -22,6 +23,7 @@ def __init__( self, scope: Construct, construct_id: str, + is_gov_cn_partition_condition: Optional[CfnCondition], enable_x_ray_tracing: str, **kwargs: Any, ): @@ -33,8 +35,16 @@ def __init__( kwargs["role"] = self._create_role() # set runtime to Python 3.12 unless a runtime is passed + # GCR and GovCloud regions do not support Python 3.12 + runtime = DEFAULT_RUNTIME + if is_gov_cn_partition_condition: + runtime = Fn.condition_if( + is_gov_cn_partition_condition.logical_id, + GOV_CN_RUNTIME, + DEFAULT_RUNTIME, + ).to_string() if not kwargs.get("runtime"): - kwargs["runtime"] = DEFAULT_RUNTIME + kwargs["runtime"] = Runtime(runtime) # create default environment variable LOGGING_LEVEL kwargs.setdefault("environment", {})["LOGGING_LEVEL"] = str(logging.INFO) @@ -42,6 +52,18 @@ def __init__( # initialize the parent Function super().__init__(scope, construct_id, **kwargs) + # TODO: Remove the suppression once Python 3.12 is supported in GovCloud and GCD + # AwsSolutions-L1 threw an error during validation because the parameter references an intrinsic function. + NagSuppressions.add_resource_suppressions( + self, + [ + { + "id": "CdkNagValidationFailure", + "reason": "Suppressing validation failure caused by intrinsic function in runtime.", + }, + ], + ) + self._configure_x_ray_tracing(enable_x_ray_tracing) def _create_role(self) -> iam.Role: diff --git a/source/solution/infrastructure/ssm_automation_docs/scripts/orchestration_doc_script.py b/source/solution/infrastructure/ssm_automation_docs/scripts/orchestration_doc_script.py index a5eb3f9..7b4f77a 100644 --- a/source/solution/infrastructure/ssm_automation_docs/scripts/orchestration_doc_script.py +++ b/source/solution/infrastructure/ssm_automation_docs/scripts/orchestration_doc_script.py @@ -10,7 +10,7 @@ import boto3 from botocore.config import Config -__boto_config__ = Config(user_agent_extra="AwsSolution/SO0293/v1.1.1") +__boto_config__ = Config(user_agent_extra="AwsSolution/SO0293/v1.1.2") s3_storage_class_mapping: Dict[str, str] = { "S3 Glacier Deep Archive": "DEEP_ARCHIVE", diff --git a/source/solution/infrastructure/stack.py b/source/solution/infrastructure/stack.py index 8d829de..407ab80 100644 --- a/source/solution/infrastructure/stack.py +++ b/source/solution/infrastructure/stack.py @@ -7,10 +7,12 @@ from aws_cdk import ( Aws, + CfnCondition, CfnElement, CfnOutput, CfnParameter, Duration, + Fn, RemovalPolicy, Stack, StackSynthesizer, @@ -90,6 +92,16 @@ def __init__( default_retry=TaskRetry(), ) + # TODO: Remove this condition once Python 3.12 is supported in GovCloud and GCD + stack_info.cfn_conditions.is_gov_cn_partition_condition = CfnCondition( + self, + "GovCnCondition", + expression=Fn.condition_or( + Fn.condition_equals(Aws.PARTITION, "aws-us-gov"), + Fn.condition_equals(Aws.PARTITION, "aws-cn"), + ), + ) + notifications_dlq = sqs.DeadLetterQueue( max_receive_count=10, queue=sqs.Queue( @@ -344,6 +356,7 @@ def __init__( stack_info.lambdas.notifications_processor_lambda = SolutionsPythonFunction( self, "NotificationsProcessor", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.notifications_processor", code=lambda_source, @@ -368,6 +381,7 @@ def __init__( stack_info.lambdas.completion_checker_lambda = SolutionsPythonFunction( self, "CompletionChecker", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.completion_checker", code=lambda_source, @@ -426,6 +440,7 @@ def __init__( stack_info.lambdas.async_facilitator_lambda = SolutionsPythonFunction( self, "AsyncFacilitator", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.async_facilitator", code=lambda_source, @@ -476,6 +491,7 @@ def __init__( stack_info.lambdas.metric_update_on_status_change_lambda = SolutionsPythonFunction( self, "MetricsProcessor", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.update_metric_on_status_change", code=lambda_source, diff --git a/source/solution/infrastructure/workflows/archives_status_cleanup.py b/source/solution/infrastructure/workflows/archives_status_cleanup.py index a1088c7..437dab5 100644 --- a/source/solution/infrastructure/workflows/archives_status_cleanup.py +++ b/source/solution/infrastructure/workflows/archives_status_cleanup.py @@ -35,6 +35,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.archives_needing_status_cleanup_lambda = SolutionsPythonFunction( stack_info.scope, "ArchivesNeedingStatusCleanup", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.archives_needing_status_cleanup", code=stack_info.lambda_source, @@ -69,6 +70,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.cleanup_archives_status_lambda = SolutionsPythonFunction( stack_info.scope, "CleanupArchivesStatus", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.cleanup_archives_status_batch", code=stack_info.lambda_source, diff --git a/source/solution/infrastructure/workflows/cleanup.py b/source/solution/infrastructure/workflows/cleanup.py index 1980516..28fad9d 100644 --- a/source/solution/infrastructure/workflows/cleanup.py +++ b/source/solution/infrastructure/workflows/cleanup.py @@ -57,6 +57,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.post_workflow_dashboard_update = SolutionsPythonFunction( stack_info.scope, "PostWorkflowDashboardUpdate", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.post_workflow_dashboard_update", code=stack_info.lambda_source, @@ -178,6 +179,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.cleanup_incomplete_multipart_uploads_lambda = SolutionsPythonFunction( stack_info.scope, "CleanupIncompleteMultipartUploads", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.cleanup_incomplete_multipart_uploads", code=stack_info.lambda_source, diff --git a/source/solution/infrastructure/workflows/extend_download_window.py b/source/solution/infrastructure/workflows/extend_download_window.py index 40cde8d..8215469 100644 --- a/source/solution/infrastructure/workflows/extend_download_window.py +++ b/source/solution/infrastructure/workflows/extend_download_window.py @@ -70,6 +70,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.archives_needing_window_extension_lambda = SolutionsPythonFunction( stack_info.scope, "ArchivesNeedingWindowExtension", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.archives_needing_window_extension", code=stack_info.lambda_source, @@ -106,6 +107,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.extend_download_window_initiate_retrieval_lambda = SolutionsPythonFunction( stack_info.scope, "ExtendDownloadInitiateRetrieval", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.extend_archive_retrieval_batch", code=stack_info.lambda_source, diff --git a/source/solution/infrastructure/workflows/get_inventory.py b/source/solution/infrastructure/workflows/get_inventory.py index b4f5f67..306ef66 100644 --- a/source/solution/infrastructure/workflows/get_inventory.py +++ b/source/solution/infrastructure/workflows/get_inventory.py @@ -63,6 +63,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.archive_naming_override_lambda = SolutionsPythonFunction( stack_info.scope, "ArchiveNamingOverride", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.archive_naming_overrides", code=stack_info.lambda_source, @@ -80,6 +81,7 @@ def __init__(self, stack_info: StackInfo): SolutionsPythonFunction( stack_info.scope, "InitiateInventoryRetrieval", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.initiate_inventory_retrieval", code=stack_info.lambda_source, @@ -248,6 +250,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.inventory_chunk_determination_lambda = SolutionsPythonFunction( stack_info.scope, "InventoryChunkDetermination", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.inventory_chunking", code=stack_info.lambda_source, @@ -347,6 +350,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.inventory_retrieval_lambda_function = SolutionsPythonFunction( stack_info.scope, "InventoryChunkDownload", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.inventory_retrieval", code=stack_info.lambda_source, @@ -448,6 +452,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.inventory_validation_lambda = SolutionsPythonFunction( stack_info.scope, "InventoryValidation", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.inventory_validation", code=stack_info.lambda_source, @@ -517,6 +522,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.send_anonymized_stats_lambda = SolutionsPythonFunction( stack_info.scope, "SendAnonymizedStats", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.anonymized_stats", code=stack_info.lambda_source, @@ -528,7 +534,7 @@ def __init__(self, stack_info: StackInfo): "ACCOUNT_ID": Aws.ACCOUNT_ID, "REGION": Aws.REGION, "VERSION": stack_info.scope.node.try_get_context("SOLUTION_VERSION") - or "v1.1.1", + or "v1.1.2", "SOLUTION_ID": stack_info.scope.node.try_get_context("SOLUTION_ID") or "SO0293", "SEND_ANONYMIZED_STATISTICS": "Yes", diff --git a/source/solution/infrastructure/workflows/initiate_retrieval.py b/source/solution/infrastructure/workflows/initiate_retrieval.py index 60a249a..e61eea4 100644 --- a/source/solution/infrastructure/workflows/initiate_retrieval.py +++ b/source/solution/infrastructure/workflows/initiate_retrieval.py @@ -43,6 +43,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.initiate_archive_retrieval_lambda = SolutionsPythonFunction( stack_info.scope, "InitiateArchiveRetrieval", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.initiate_archive_retrieval_batch", code=stack_info.lambda_source, @@ -178,6 +179,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.calculate_timeout_lambda = SolutionsPythonFunction( stack_info.scope, "CalculateTimeout", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.initiation_timeout", code=stack_info.lambda_source, diff --git a/source/solution/infrastructure/workflows/retrieve_archive.py b/source/solution/infrastructure/workflows/retrieve_archive.py index ed59234..3f39a45 100644 --- a/source/solution/infrastructure/workflows/retrieve_archive.py +++ b/source/solution/infrastructure/workflows/retrieve_archive.py @@ -33,6 +33,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.chunk_retrieval_lambda = SolutionsPythonFunction( stack_info.scope, "ChunkRetrieval", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.archive_retrieval", code=stack_info.lambda_source, @@ -89,6 +90,7 @@ def __init__(self, stack_info: StackInfo): stack_info.lambdas.archive_validation_lambda = SolutionsPythonFunction( stack_info.scope, "ArchiveValidation", + stack_info.cfn_conditions.is_gov_cn_partition_condition, stack_info.parameters.enable_lambda_tracing_parameter.value_as_string, handler="solution.application.handlers.archive_validation", code=stack_info.lambda_source, diff --git a/source/solution/infrastructure/workflows/stack_info.py b/source/solution/infrastructure/workflows/stack_info.py index 6bd0676..89daa84 100644 --- a/source/solution/infrastructure/workflows/stack_info.py +++ b/source/solution/infrastructure/workflows/stack_info.py @@ -6,7 +6,7 @@ from dataclasses import dataclass, field from typing import Dict, Optional -from aws_cdk import CfnOutput, CfnParameter, Stack +from aws_cdk import CfnCondition, CfnOutput, CfnParameter, Stack from aws_cdk import aws_dynamodb as dynamodb from aws_cdk import aws_events as eventbridge from aws_cdk import aws_iam as iam @@ -84,6 +84,11 @@ class Parameters: enable_step_function_tracing_parameter: CfnParameter | None = field(default=None) +@dataclass +class CfNConditions: + is_gov_cn_partition_condition: CfnCondition | None = field(default=None) + + @dataclass class Tables: glacier_retrieval_table: dynamodb.Table | None = field(default=None) @@ -119,6 +124,7 @@ class StackInfo: default_retry: TaskRetry queues: Queues = field(default_factory=lambda: Queues()) parameters: Parameters = field(default_factory=lambda: Parameters()) + cfn_conditions: CfNConditions = field(default_factory=lambda: CfNConditions()) tables: Tables = field(default_factory=lambda: Tables()) buckets: Buckets = field(default_factory=lambda: Buckets()) lambdas: Lambdas = field(default_factory=lambda: Lambdas()) diff --git a/source/tests/unit/conftest.py b/source/tests/unit/conftest.py index c8af842..2c2590f 100644 --- a/source/tests/unit/conftest.py +++ b/source/tests/unit/conftest.py @@ -49,7 +49,7 @@ def aws_credentials() -> None: @pytest.fixture(scope="module") def solution_user_agent() -> str: - return "AwsSolution/SO0293/v1.1.1" + return "AwsSolution/SO0293/v1.1.2" @pytest.fixture(scope="module") diff --git a/source/tests/unit/infrastructure/glue_helper/scripts/test_archive_naming.py b/source/tests/unit/infrastructure/glue_helper/scripts/test_archive_naming.py index 47a483f..d217998 100644 --- a/source/tests/unit/infrastructure/glue_helper/scripts/test_archive_naming.py +++ b/source/tests/unit/infrastructure/glue_helper/scripts/test_archive_naming.py @@ -58,6 +58,12 @@ def test_cloudberry_json_format() -> None: ) == "CB+F8-M5/B:/c01/q004/s0010/c01+AF8-s00+A8-s0010+F8/h01.1094.dpx" ) + assert ( + parse_description( + '{"path":"CB+F8-M5/B:/c01/q004/s0010/c01+AF8-s00+A8-s0010+F8/h01.1094.dpx","UTCDateModified":"20100310T110623Z"}' + ) + == "CB+F8-M5/B:/c01/q004/s0010/c01+AF8-s00+A8-s0010+F8/h01.1094.dpx" + ) def test_empty_file_name_from_json() -> None: @@ -65,6 +71,10 @@ def test_empty_file_name_from_json() -> None: parse_filename("AAAQQQ", '{"Path":" ","UTCDateModified":"20100310T110623Z"}') == "00undefined/AAAQQQ" ) + assert ( + parse_filename("AAAQQQ", '{"path":" ","UTCDateModified":"20100310T110623Z"}') + == "00undefined/AAAQQQ" + ) def test_empty_archive_description() -> None: diff --git a/source/tests/unit/infrastructure/test_stack.py b/source/tests/unit/infrastructure/test_stack.py index 00db5ae..3c62a17 100644 --- a/source/tests/unit/infrastructure/test_stack.py +++ b/source/tests/unit/infrastructure/test_stack.py @@ -231,13 +231,12 @@ def test_chunk_retrieval_lambda_created( props={ "Properties": { "Handler": "solution.application.handlers.archive_retrieval", - "Runtime": "python3.12", + "Runtime": {"Fn::If": ["GovCnCondition", "python3.11", "python3.12"]}, "MemorySize": 1536, "Timeout": 900, }, }, ) - template.has_output( OutputKeys.CHUNK_RETRIEVAL_LAMBDA_ARN, {"Value": {"Ref": logical_id}}, @@ -257,7 +256,7 @@ def test_archive_validation_lambda_created( props={ "Properties": { "Handler": "solution.application.handlers.archive_validation", - "Runtime": "python3.12", + "Runtime": {"Fn::If": ["GovCnCondition", "python3.11", "python3.12"]}, "MemorySize": 256, "Timeout": 900, }, @@ -283,7 +282,7 @@ def test_inventory_chunk_determination_created( props={ "Properties": { "Handler": "solution.application.handlers.inventory_chunking", - "Runtime": "python3.12", + "Runtime": {"Fn::If": ["GovCnCondition", "python3.11", "python3.12"]}, }, }, ) @@ -314,7 +313,7 @@ def test_facilitator_lambda_created( }, "Handler": "solution.application.handlers.async_facilitator", "MemorySize": 256, - "Runtime": "python3.12", + "Runtime": {"Fn::If": ["GovCnCondition", "python3.11", "python3.12"]}, }, )