Repository: aws-cloudformation/cfn-lint

Issue:
cfn-lint prevents using SnapStart with Python 3.12 (w/SAM CLI)
### CloudFormation Lint Version

1.20.2

### What operating system are you using?

Amazon Linux 2

### Describe the bug

On Nov 18 2024, SnapStart for Python 3.12 was launched (https://aws.amazon.com/about-aws/whats-new/2024/11/aws-lambda-snapstart-python-net-functions/).  `cfn-lint` is giving lint errors about non-support when using `sam validate --lint` for templates that contain SnapStart and `python3.12` as a runtime.

```
[[E2530: SnapStart supports the configured runtime] ('python3.12' is not supported for 'SnapStart' enabled functions) matched 137]
Error: Linting failed. At least one linting rule was matched to the provided template.
```

One area of the code where it is validating this can be found here -- https://github.com/aws-cloudformation/cfn-lint/blob/700563cda182416a6c99af4bcaa96077c2412465/src/cfnlint/rules/resources/lmbd/SnapStartSupported.py#L100

### Expected behavior

For `cfn-lint` properly validate SnapStart and not return unsupported SnapStart for Python 3.12.

NOTE: SnapStart for AWS Lambda is only supported in some region, as opposed to Java. The list may need to be modified and/or checked independently for now in the code.
 
<img width="709" alt="image" src="https://github.com/user-attachments/assets/c4522c53-2297-47ce-9949-33fe3e0faaa9" />


### Reproduction template

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform:
  - AWS::LanguageExtensions
  - AWS::Serverless-2016-10-31

Description: >
  SnapStart Sample (Python 3.12)

Parameters:
  Environment:
    Type: String
    Default: local
    AllowedValues:
      - local
      - dev

Globals:
  Function:
    Timeout: 30
    MemorySize: 1024
    Runtime: python3.12
    Architectures:
      - arm64
    Tracing: Active
    AutoPublishAlias: live

  SnapStartFunc:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: "snapstat-sample-api"
      CodeUri: src/

...

```


Discussion:
Official list of runtimes that support SnapStart right now: https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html#snapstart-runtimes

> - Java 11 and later
> - Python 3.12 and later
> - .NET 8 and later. 



Patch:
diff --git a/src/cfnlint/rules/resources/lmbd/SnapStartSupported.py b/src/cfnlint/rules/resources/lmbd/SnapStartSupported.py
index b55b662a4c..9be951bc0d 100644
--- a/src/cfnlint/rules/resources/lmbd/SnapStartSupported.py
+++ b/src/cfnlint/rules/resources/lmbd/SnapStartSupported.py
@@ -51,6 +51,26 @@ def __init__(self):
             "sa-east-1",
         ]
 
+    def _is_runtime_valid(self, runtime: str) -> bool:
+        if not any(runtime.startswith(r) for r in ["python", "java", "dotnet"]):
+            return False
+
+        if runtime.startswith("dotnetcore"):
+            return False
+
+        return runtime not in [
+            "dotnet5.0",
+            "dotnet6",
+            "dotnet7",
+            "java8.al2",
+            "java8",
+            "python3.10",
+            "python3.11",
+            "python3.7",
+            "python3.8",
+            "python3.9",
+        ]
+
     def validate(
         self, validator: Validator, _, instance: Any, schema: dict[str, Any]
     ) -> ValidationResult:
@@ -94,11 +114,7 @@ def validate(
             if not isinstance(runtime, str):
                 continue
 
-            if (
-                runtime
-                and (not runtime.startswith("java"))
-                and runtime not in ["java8.al2", "java8"]
-            ):
+            if not self._is_runtime_valid(runtime):
                 yield ValidationError(
                     f"{runtime!r} is not supported for 'SnapStart' enabled functions",
                     path=deque(["SnapStart", "ApplyOn"]),


Test patch:
diff --git a/test/unit/rules/resources/lmbd/test_snapstart_supported.py b/test/unit/rules/resources/lmbd/test_snapstart_supported.py
index 8adb496c4c..16a457f9b1 100644
--- a/test/unit/rules/resources/lmbd/test_snapstart_supported.py
+++ b/test/unit/rules/resources/lmbd/test_snapstart_supported.py
@@ -66,7 +66,90 @@ def rule():
             ],
         ),
         (
-            "SnapStart not enabled on non java runtime",
+            "SnapStart enabled for python3.12 error",
+            {
+                "Runtime": "python3.12",
+                "SnapStart": {
+                    "ApplyOn": "PublishedVersions",
+                },
+            },
+            ["us-east-1"],
+            True,
+            False,
+            [],
+        ),
+        (
+            "SnapStart enabled for dotnet",
+            {
+                "Runtime": "dotnet8",
+                "SnapStart": {
+                    "ApplyOn": "PublishedVersions",
+                },
+            },
+            ["us-east-1"],
+            True,
+            False,
+            [],
+        ),
+        (
+            "SnapStart enabled for go that isn't supported",
+            {
+                "Runtime": "go1.x",
+                "SnapStart": {
+                    "ApplyOn": "PublishedVersions",
+                },
+            },
+            ["us-east-1"],
+            True,
+            False,
+            [
+                ValidationError(
+                    "'go1.x' is not supported for 'SnapStart' enabled functions",
+                    path=deque(["SnapStart", "ApplyOn"]),
+                )
+            ],
+        ),
+        (
+            "SnapStart enabled for dotnet version that isn't supported",
+            {
+                "Runtime": "dotnet5.0",
+                "SnapStart": {
+                    "ApplyOn": "PublishedVersions",
+                },
+            },
+            ["us-east-1"],
+            True,
+            False,
+            [
+                ValidationError(
+                    "'dotnet5.0' is not supported for 'SnapStart' enabled functions",
+                    path=deque(["SnapStart", "ApplyOn"]),
+                )
+            ],
+        ),
+        (
+            "SnapStart enabled for dotnetcore version that isn't supported",
+            {
+                "Runtime": "dotnetcore2.1",
+                "SnapStart": {
+                    "ApplyOn": "PublishedVersions",
+                },
+            },
+            ["us-east-1"],
+            True,
+            False,
+            [
+                ValidationError(
+                    (
+                        "'dotnetcore2.1' is not supported for "
+                        "'SnapStart' enabled functions"
+                    ),
+                    path=deque(["SnapStart", "ApplyOn"]),
+                )
+            ],
+        ),
+        (
+            "SnapStart not enabled on python non supported runtime",
             {
                 "Runtime": "python3.11",
             },
@@ -76,7 +159,7 @@ def rule():
             [],
         ),
         (
-            "SnapStart not enabled on java runtime in a bad region",
+            "SnapStart not enabled on python runtime in a bad region",
             {
                 "Runtime": "python3.11",
             },