Skip to content

Commit

Permalink
Merge in v0 fixes (#3304)
Browse files Browse the repository at this point in the history
  • Loading branch information
kddejong authored Jun 14, 2024
1 parent 091f9a7 commit efa54a5
Show file tree
Hide file tree
Showing 12 changed files with 376 additions and 169 deletions.
125 changes: 73 additions & 52 deletions src/cfnlint/data/AdditionalSpecs/LmbdRuntimeLifecycle.json
Original file line number Diff line number Diff line change
@@ -1,107 +1,128 @@
{
"dotnet6": {
"create-block": "2025-02-28",
"deprecated": "2024-11-12",
"eol": "2025-01-11",
"successor": "dotnet8"
"successor": "dotnet8",
"update-block": "2025-05-31"
},
"dotnet7": {
"create-block": "2024-05-14",
"deprecated": "2024-05-14",
"eol": "2026-10-08",
"successor": "dotnet8"
"successor": "dotnet8",
"update-block": "2024-05-14"
},
"dotnetcore1.0": {
"deprecated": "2019-07-31",
"eol": "2019-06-27",
"successor": "dotnet8"
"create-block": "2019-07-30",
"deprecated": "2019-06-27",
"successor": "dotnet8",
"update-block": "2019-07-30"
},
"dotnetcore2.0": {
"create-block": "2019-05-30",
"deprecated": "2019-05-30",
"eol": "2019-04-30",
"successor": "dotnet8"
"successor": "dotnet8",
"update-block": "2019-05-30"
},
"dotnetcore2.1": {
"deprecated": "2021-09-23",
"eol": "2021-08-23",
"successor": "dotnet8"
"create-block": "2022-01-05",
"deprecated": "2022-01-05",
"successor": "dotnet8",
"update-block": "2022-04-13"
},
"dotnetcore3.1": {
"deprecated": "2023-02-20",
"eol": "2023-01-20",
"successor": "dotnet8"
"create-block": "2023-04-03",
"deprecated": "2023-04-03",
"successor": "dotnet8",
"update-block": "2023-05-03"
},
"nodejs": {
"create-block": "2016-10-31",
"deprecated": "2016-10-31",
"eol": "2016-10-31",
"successor": "nodejs20.x"
"successor": "nodejs20.x",
"update-block": "2016-10-31"
},
"nodejs10.x": {
"deprecated": "2021-08-30",
"eol": "2021-07-30",
"successor": "nodejs20.x"
"create-block": "2021-07-30",
"deprecated": "2021-07-30",
"successor": "nodejs20.x",
"update-block": "2022-02-14"
},
"nodejs12.x": {
"deprecated": "2022-12-14",
"eol": "2022-11-14",
"successor": "nodejs20.x"
"create-block": "2023-03-31",
"deprecated": "2023-03-31",
"successor": "nodejs20.x",
"update-block": "2023-04-30"
},
"nodejs14.x": {
"create-block": "2024-07-09",
"deprecated": "2023-12-04",
"eol": "2024-01-09",
"successor": "nodejs20.x"
"successor": "nodejs20.x",
"update-block": "2025-02-28"
},
"nodejs16.x": {
"create-block": "2025-02-28",
"deprecated": "2024-06-12",
"eol": "2024-07-15",
"successor": "nodejs20.x"
"successor": "nodejs20.x",
"update-block": "2025-03-31"
},
"nodejs4.3": {
"deprecated": "2019-04-30",
"eol": "2018-04-30",
"successor": "nodejs20.x"
"create-block": "2020-03-05",
"deprecated": "2020-03-05",
"successor": "nodejs20.x",
"update-block": "2020-03-05"
},
"nodejs4.3-edge": {
"deprecated": "2019-04-30",
"eol": "2018-04-30",
"successor": "nodejs20.x"
"create-block": "2019-04-30",
"deprecated": "2020-03-05",
"successor": "nodejs20.x",
"update-block": "2019-04-30"
},
"nodejs6.10": {
"create-block": "2019-08-12",
"deprecated": "2019-08-12",
"eol": "2019-04-30",
"successor": "nodejs20.x"
"successor": "nodejs20.x",
"update-block": "2019-08-12"
},
"nodejs8.10": {
"deprecated": "2020-02-03",
"eol": "2019-12-31",
"successor": "nodejs20.x"
"create-block": "2020-03-06",
"deprecated": "2020-03-06",
"successor": "nodejs20.x",
"update-block": "2020-03-06"
},
"python2.7": {
"deprecated": "2021-09-30",
"eol": "2021-07-15",
"successor": "python3.12"
"create-block": "2021-07-15",
"deprecated": "2021-07-15",
"successor": "python3.12",
"update-block": "2022-05-30"
},
"python3.6": {
"deprecated": "2022-08-17",
"eol": "2022-07-18",
"successor": "python3.12"
"create-block": "2022-07-18",
"deprecated": "2022-07-18",
"successor": "python3.12",
"update-block": "2022-08-29"
},
"python3.7": {
"create-block": "2024-01-09",
"deprecated": "2023-12-04",
"eol": "2024-01-09",
"successor": "python3.12"
"successor": "python3.12",
"update-block": "2025-02-28"
},
"python3.8": {
"create-block": "2025-02-28",
"deprecated": "2024-10-14",
"eol": "2024-11-13",
"successor": "python3.12"
"successor": "python3.12",
"update-block": "2025-03-31"
},
"ruby2.5": {
"create-block": "2021-07-30",
"deprecated": "2021-07-30",
"eol": "2021-07-30",
"successor": "ruby3.2"
"successor": "ruby3.2",
"update-block": "2022-03-31"
},
"ruby2.7": {
"create-block": "2024-01-09",
"deprecated": "2023-12-07",
"eol": "2024-01-09",
"successor": "ruby3.2"
"successor": "ruby3.2",
"update-block": "2025-02-28"
}
}
5 changes: 4 additions & 1 deletion src/cfnlint/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ def _add_parameters(self, cfn: Any) -> None:

def _add_outputs(self, cfn: Any) -> None:
# add all outputs in the template as nodes
for output_id in cfn.template.get("Outputs", {}).keys():
outputs = cfn.template.get("Outputs", {})
if not isinstance(outputs, dict):
return
for output_id in outputs.keys():
graph_label = str.format(f'"{output_id}"')
self._add_node(output_id, settings=self.settings.output, label=graph_label)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from cfnlint.rules.jsonschema.CfnLintKeyword import CfnLintKeyword


class DeprecatedRuntimeEnd(CfnLintKeyword):
class DeprecatedRuntimeCreate(CfnLintKeyword):

id = "E2531"
shortdesc = "Validate if lambda runtime is deprecated"
Expand All @@ -25,9 +25,6 @@ class DeprecatedRuntimeEnd(CfnLintKeyword):
def __init__(self):
"""Init"""
super().__init__(["Resources/AWS::Lambda::Function/Properties/Runtime"])
self.child_rules = {
"W2531": None,
}
self.current_date = datetime.today()
self.deprecated_runtimes = load_resource(
AdditionalSpecs, "LmbdRuntimeLifecycle.json"
Expand All @@ -37,21 +34,25 @@ def __init__(self):
def validate(
self, validator: Validator, v: Any, runtime: Any, schema: dict[str, Any]
) -> ValidationResult:
if not validator.is_type(runtime, "string"):
return

runtime_data = self.deprecated_runtimes.get(runtime)

if not runtime_data:
return
if (
datetime.strptime(runtime_data["deprecated"], "%Y-%m-%d")
< self.current_date
datetime.strptime(runtime_data["create-block"], "%Y-%m-%d")
<= self.current_date
and datetime.strptime(runtime_data["update-block"], "%Y-%m-%d")
> self.current_date
):
yield ValidationError(
(
f"Deprecated runtime {runtime!r} specified. Updating "
f"disabled since {runtime_data['deprecated']!r}. "
f"Please consider updating to {runtime_data['successor']!r}"
f"Runtime {runtime!r} was deprecated on "
f"{runtime_data['deprecated']!r}. Creation was disabled on "
f"{runtime_data['create-block']!r} and update on "
f"{runtime_data['update-block']!r}. Please consider "
f"updating to {runtime_data['successor']!r}"
),
rule=self,
)

if self.child_rules["W2531"]:
yield from self.child_rules["W2531"].lambdaruntime(runtime, runtime_data) # type: ignore
48 changes: 33 additions & 15 deletions src/cfnlint/rules/resources/lmbd/DeprecatedRuntimeEol.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,60 @@
SPDX-License-Identifier: MIT-0
"""

from __future__ import annotations

from datetime import datetime
from typing import Any

from cfnlint.jsonschema import ValidationError
from cfnlint.rules import CloudFormationLintRule
from cfnlint.data import AdditionalSpecs
from cfnlint.helpers import load_resource
from cfnlint.jsonschema import ValidationError, ValidationResult, Validator
from cfnlint.rules.jsonschema.CfnLintKeyword import CfnLintKeyword


class DeprecatedRuntimeEol(CloudFormationLintRule):
class DeprecatedRuntimeEol(CfnLintKeyword):

id = "W2531"
shortdesc = "Check if EOL Lambda Function Runtimes are used"
description = (
"Check if an EOL Lambda Runtime is specified and give a warning if used"
"Check if an EOL Lambda Runtime is specified and give a warning if used. "
)
source_url = (
"https://docs.aws.amazon.com/lambda/latest/dg/runtime-support-policy.html"
)
source_url = "https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html"
tags = ["resources", "lambda", "runtime"]

def __init__(self):
"""Init"""
super().__init__()
super().__init__(["Resources/AWS::Lambda::Function/Properties/Runtime"])
self.current_date = datetime.today()
self.deprecated_runtimes = load_resource(
AdditionalSpecs, "LmbdRuntimeLifecycle.json"
)

# pylint: disable=unused-argument
def lambdaruntime(self, runtime, runtime_data):
def validate(
self, validator: Validator, v: Any, runtime: Any, schema: dict[str, Any]
) -> ValidationResult:
if not validator.is_type(runtime, "string"):
return

runtime_data = self.deprecated_runtimes.get(runtime)
if not runtime_data:
return
if (
datetime.strptime(runtime_data["eol"], "%Y-%m-%d") < self.current_date
and datetime.strptime(runtime_data["deprecated"], "%Y-%m-%d")
datetime.strptime(runtime_data["deprecated"], "%Y-%m-%d")
<= self.current_date
and datetime.strptime(runtime_data["create-block"], "%Y-%m-%d")
> self.current_date
and datetime.strptime(runtime_data["update-block"], "%Y-%m-%d")
> self.current_date
):
yield ValidationError(
(
f"EOL runtime {runtime!r} specified. Runtime is EOL since "
f"{runtime_data['eol']!r} and updating "
f"will be disabled at {runtime_data['deprecated']!r}. "
f"Please consider updating to {runtime_data['successor']!r}"
f"Runtime {runtime!r} was deprecated on "
f"{runtime_data['deprecated']!r}. Creation was disabled on "
f"{runtime_data['create-block']!r} and update on "
f"{runtime_data['update-block']!r}. Please consider "
f"updating to {runtime_data['successor']!r}"
),
rule=self,
)
57 changes: 57 additions & 0 deletions src/cfnlint/rules/resources/lmbd/DeprecatedRuntimeUpdate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from __future__ import annotations

from datetime import datetime
from typing import Any

from cfnlint.data import AdditionalSpecs
from cfnlint.helpers import load_resource
from cfnlint.jsonschema import ValidationError, ValidationResult, Validator
from cfnlint.rules.jsonschema.CfnLintKeyword import CfnLintKeyword


class DeprecatedRuntimeUpdate(CfnLintKeyword):

id = "E2533"
shortdesc = "Check if Lambda Function Runtimes are updatable"
description = (
"Check if an EOL Lambda Runtime is specified and you cannot update the function"
)
source_url = (
"https://docs.aws.amazon.com/lambda/latest/dg/runtime-support-policy.html"
)
tags = ["resources", "lambda", "runtime"]

def __init__(self):
"""Init"""
super().__init__(["Resources/AWS::Lambda::Function/Properties/Runtime"])
self.current_date = datetime.today()
self.deprecated_runtimes = load_resource(
AdditionalSpecs, "LmbdRuntimeLifecycle.json"
)

def validate(
self, validator: Validator, v: Any, runtime: Any, schema: dict[str, Any]
) -> ValidationResult:
if not validator.is_type(runtime, "string"):
return
runtime_data = self.deprecated_runtimes.get(runtime)
if not runtime_data:
return
if (
datetime.strptime(runtime_data["update-block"], "%Y-%m-%d")
<= self.current_date
):
yield ValidationError(
(
f"Runtime {runtime!r} was deprecated on "
f"{runtime_data['deprecated']!r}. Creation was disabled on "
f"{runtime_data['create-block']!r} and update on "
f"{runtime_data['update-block']!r}. Please consider "
f"updating to {runtime_data['successor']!r}"
),
)
Loading

0 comments on commit efa54a5

Please sign in to comment.