Skip to content

Commit efa54a5

Browse files
authored
Merge in v0 fixes (#3304)
1 parent 091f9a7 commit efa54a5

12 files changed

+376
-169
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,128 @@
11
{
22
"dotnet6": {
3+
"create-block": "2025-02-28",
34
"deprecated": "2024-11-12",
4-
"eol": "2025-01-11",
5-
"successor": "dotnet8"
5+
"successor": "dotnet8",
6+
"update-block": "2025-05-31"
67
},
78
"dotnet7": {
9+
"create-block": "2024-05-14",
810
"deprecated": "2024-05-14",
9-
"eol": "2026-10-08",
10-
"successor": "dotnet8"
11+
"successor": "dotnet8",
12+
"update-block": "2024-05-14"
1113
},
1214
"dotnetcore1.0": {
13-
"deprecated": "2019-07-31",
14-
"eol": "2019-06-27",
15-
"successor": "dotnet8"
15+
"create-block": "2019-07-30",
16+
"deprecated": "2019-06-27",
17+
"successor": "dotnet8",
18+
"update-block": "2019-07-30"
1619
},
1720
"dotnetcore2.0": {
21+
"create-block": "2019-05-30",
1822
"deprecated": "2019-05-30",
19-
"eol": "2019-04-30",
20-
"successor": "dotnet8"
23+
"successor": "dotnet8",
24+
"update-block": "2019-05-30"
2125
},
2226
"dotnetcore2.1": {
23-
"deprecated": "2021-09-23",
24-
"eol": "2021-08-23",
25-
"successor": "dotnet8"
27+
"create-block": "2022-01-05",
28+
"deprecated": "2022-01-05",
29+
"successor": "dotnet8",
30+
"update-block": "2022-04-13"
2631
},
2732
"dotnetcore3.1": {
28-
"deprecated": "2023-02-20",
29-
"eol": "2023-01-20",
30-
"successor": "dotnet8"
33+
"create-block": "2023-04-03",
34+
"deprecated": "2023-04-03",
35+
"successor": "dotnet8",
36+
"update-block": "2023-05-03"
3137
},
3238
"nodejs": {
39+
"create-block": "2016-10-31",
3340
"deprecated": "2016-10-31",
34-
"eol": "2016-10-31",
35-
"successor": "nodejs20.x"
41+
"successor": "nodejs20.x",
42+
"update-block": "2016-10-31"
3643
},
3744
"nodejs10.x": {
38-
"deprecated": "2021-08-30",
39-
"eol": "2021-07-30",
40-
"successor": "nodejs20.x"
45+
"create-block": "2021-07-30",
46+
"deprecated": "2021-07-30",
47+
"successor": "nodejs20.x",
48+
"update-block": "2022-02-14"
4149
},
4250
"nodejs12.x": {
43-
"deprecated": "2022-12-14",
44-
"eol": "2022-11-14",
45-
"successor": "nodejs20.x"
51+
"create-block": "2023-03-31",
52+
"deprecated": "2023-03-31",
53+
"successor": "nodejs20.x",
54+
"update-block": "2023-04-30"
4655
},
4756
"nodejs14.x": {
57+
"create-block": "2024-07-09",
4858
"deprecated": "2023-12-04",
49-
"eol": "2024-01-09",
50-
"successor": "nodejs20.x"
59+
"successor": "nodejs20.x",
60+
"update-block": "2025-02-28"
5161
},
5262
"nodejs16.x": {
63+
"create-block": "2025-02-28",
5364
"deprecated": "2024-06-12",
54-
"eol": "2024-07-15",
55-
"successor": "nodejs20.x"
65+
"successor": "nodejs20.x",
66+
"update-block": "2025-03-31"
5667
},
5768
"nodejs4.3": {
58-
"deprecated": "2019-04-30",
59-
"eol": "2018-04-30",
60-
"successor": "nodejs20.x"
69+
"create-block": "2020-03-05",
70+
"deprecated": "2020-03-05",
71+
"successor": "nodejs20.x",
72+
"update-block": "2020-03-05"
6173
},
6274
"nodejs4.3-edge": {
63-
"deprecated": "2019-04-30",
64-
"eol": "2018-04-30",
65-
"successor": "nodejs20.x"
75+
"create-block": "2019-04-30",
76+
"deprecated": "2020-03-05",
77+
"successor": "nodejs20.x",
78+
"update-block": "2019-04-30"
6679
},
6780
"nodejs6.10": {
81+
"create-block": "2019-08-12",
6882
"deprecated": "2019-08-12",
69-
"eol": "2019-04-30",
70-
"successor": "nodejs20.x"
83+
"successor": "nodejs20.x",
84+
"update-block": "2019-08-12"
7185
},
7286
"nodejs8.10": {
73-
"deprecated": "2020-02-03",
74-
"eol": "2019-12-31",
75-
"successor": "nodejs20.x"
87+
"create-block": "2020-03-06",
88+
"deprecated": "2020-03-06",
89+
"successor": "nodejs20.x",
90+
"update-block": "2020-03-06"
7691
},
7792
"python2.7": {
78-
"deprecated": "2021-09-30",
79-
"eol": "2021-07-15",
80-
"successor": "python3.12"
93+
"create-block": "2021-07-15",
94+
"deprecated": "2021-07-15",
95+
"successor": "python3.12",
96+
"update-block": "2022-05-30"
8197
},
8298
"python3.6": {
83-
"deprecated": "2022-08-17",
84-
"eol": "2022-07-18",
85-
"successor": "python3.12"
99+
"create-block": "2022-07-18",
100+
"deprecated": "2022-07-18",
101+
"successor": "python3.12",
102+
"update-block": "2022-08-29"
86103
},
87104
"python3.7": {
105+
"create-block": "2024-01-09",
88106
"deprecated": "2023-12-04",
89-
"eol": "2024-01-09",
90-
"successor": "python3.12"
107+
"successor": "python3.12",
108+
"update-block": "2025-02-28"
91109
},
92110
"python3.8": {
111+
"create-block": "2025-02-28",
93112
"deprecated": "2024-10-14",
94-
"eol": "2024-11-13",
95-
"successor": "python3.12"
113+
"successor": "python3.12",
114+
"update-block": "2025-03-31"
96115
},
97116
"ruby2.5": {
117+
"create-block": "2021-07-30",
98118
"deprecated": "2021-07-30",
99-
"eol": "2021-07-30",
100-
"successor": "ruby3.2"
119+
"successor": "ruby3.2",
120+
"update-block": "2022-03-31"
101121
},
102122
"ruby2.7": {
123+
"create-block": "2024-01-09",
103124
"deprecated": "2023-12-07",
104-
"eol": "2024-01-09",
105-
"successor": "ruby3.2"
125+
"successor": "ruby3.2",
126+
"update-block": "2025-02-28"
106127
}
107128
}

src/cfnlint/graph.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,10 @@ def _add_parameters(self, cfn: Any) -> None:
144144

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

src/cfnlint/rules/resources/lmbd/DeprecatedRuntimeEnd.py renamed to src/cfnlint/rules/resources/lmbd/DeprecatedRuntimeCreate.py

+14-13
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from cfnlint.rules.jsonschema.CfnLintKeyword import CfnLintKeyword
1515

1616

17-
class DeprecatedRuntimeEnd(CfnLintKeyword):
17+
class DeprecatedRuntimeCreate(CfnLintKeyword):
1818

1919
id = "E2531"
2020
shortdesc = "Validate if lambda runtime is deprecated"
@@ -25,9 +25,6 @@ class DeprecatedRuntimeEnd(CfnLintKeyword):
2525
def __init__(self):
2626
"""Init"""
2727
super().__init__(["Resources/AWS::Lambda::Function/Properties/Runtime"])
28-
self.child_rules = {
29-
"W2531": None,
30-
}
3128
self.current_date = datetime.today()
3229
self.deprecated_runtimes = load_resource(
3330
AdditionalSpecs, "LmbdRuntimeLifecycle.json"
@@ -37,21 +34,25 @@ def __init__(self):
3734
def validate(
3835
self, validator: Validator, v: Any, runtime: Any, schema: dict[str, Any]
3936
) -> ValidationResult:
37+
if not validator.is_type(runtime, "string"):
38+
return
39+
4040
runtime_data = self.deprecated_runtimes.get(runtime)
41+
4142
if not runtime_data:
4243
return
4344
if (
44-
datetime.strptime(runtime_data["deprecated"], "%Y-%m-%d")
45-
< self.current_date
45+
datetime.strptime(runtime_data["create-block"], "%Y-%m-%d")
46+
<= self.current_date
47+
and datetime.strptime(runtime_data["update-block"], "%Y-%m-%d")
48+
> self.current_date
4649
):
4750
yield ValidationError(
4851
(
49-
f"Deprecated runtime {runtime!r} specified. Updating "
50-
f"disabled since {runtime_data['deprecated']!r}. "
51-
f"Please consider updating to {runtime_data['successor']!r}"
52+
f"Runtime {runtime!r} was deprecated on "
53+
f"{runtime_data['deprecated']!r}. Creation was disabled on "
54+
f"{runtime_data['create-block']!r} and update on "
55+
f"{runtime_data['update-block']!r}. Please consider "
56+
f"updating to {runtime_data['successor']!r}"
5257
),
53-
rule=self,
5458
)
55-
56-
if self.child_rules["W2531"]:
57-
yield from self.child_rules["W2531"].lambdaruntime(runtime, runtime_data) # type: ignore

src/cfnlint/rules/resources/lmbd/DeprecatedRuntimeEol.py

+33-15
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,60 @@
33
SPDX-License-Identifier: MIT-0
44
"""
55

6+
from __future__ import annotations
7+
68
from datetime import datetime
9+
from typing import Any
710

8-
from cfnlint.jsonschema import ValidationError
9-
from cfnlint.rules import CloudFormationLintRule
11+
from cfnlint.data import AdditionalSpecs
12+
from cfnlint.helpers import load_resource
13+
from cfnlint.jsonschema import ValidationError, ValidationResult, Validator
14+
from cfnlint.rules.jsonschema.CfnLintKeyword import CfnLintKeyword
1015

1116

12-
class DeprecatedRuntimeEol(CloudFormationLintRule):
17+
class DeprecatedRuntimeEol(CfnLintKeyword):
1318

1419
id = "W2531"
1520
shortdesc = "Check if EOL Lambda Function Runtimes are used"
1621
description = (
17-
"Check if an EOL Lambda Runtime is specified and give a warning if used"
22+
"Check if an EOL Lambda Runtime is specified and give a warning if used. "
23+
)
24+
source_url = (
25+
"https://docs.aws.amazon.com/lambda/latest/dg/runtime-support-policy.html"
1826
)
19-
source_url = "https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html"
2027
tags = ["resources", "lambda", "runtime"]
2128

2229
def __init__(self):
2330
"""Init"""
24-
super().__init__()
31+
super().__init__(["Resources/AWS::Lambda::Function/Properties/Runtime"])
2532
self.current_date = datetime.today()
33+
self.deprecated_runtimes = load_resource(
34+
AdditionalSpecs, "LmbdRuntimeLifecycle.json"
35+
)
2636

27-
# pylint: disable=unused-argument
28-
def lambdaruntime(self, runtime, runtime_data):
37+
def validate(
38+
self, validator: Validator, v: Any, runtime: Any, schema: dict[str, Any]
39+
) -> ValidationResult:
40+
if not validator.is_type(runtime, "string"):
41+
return
42+
43+
runtime_data = self.deprecated_runtimes.get(runtime)
2944
if not runtime_data:
3045
return
3146
if (
32-
datetime.strptime(runtime_data["eol"], "%Y-%m-%d") < self.current_date
33-
and datetime.strptime(runtime_data["deprecated"], "%Y-%m-%d")
47+
datetime.strptime(runtime_data["deprecated"], "%Y-%m-%d")
48+
<= self.current_date
49+
and datetime.strptime(runtime_data["create-block"], "%Y-%m-%d")
50+
> self.current_date
51+
and datetime.strptime(runtime_data["update-block"], "%Y-%m-%d")
3452
> self.current_date
3553
):
3654
yield ValidationError(
3755
(
38-
f"EOL runtime {runtime!r} specified. Runtime is EOL since "
39-
f"{runtime_data['eol']!r} and updating "
40-
f"will be disabled at {runtime_data['deprecated']!r}. "
41-
f"Please consider updating to {runtime_data['successor']!r}"
56+
f"Runtime {runtime!r} was deprecated on "
57+
f"{runtime_data['deprecated']!r}. Creation was disabled on "
58+
f"{runtime_data['create-block']!r} and update on "
59+
f"{runtime_data['update-block']!r}. Please consider "
60+
f"updating to {runtime_data['successor']!r}"
4261
),
43-
rule=self,
4462
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
from __future__ import annotations
7+
8+
from datetime import datetime
9+
from typing import Any
10+
11+
from cfnlint.data import AdditionalSpecs
12+
from cfnlint.helpers import load_resource
13+
from cfnlint.jsonschema import ValidationError, ValidationResult, Validator
14+
from cfnlint.rules.jsonschema.CfnLintKeyword import CfnLintKeyword
15+
16+
17+
class DeprecatedRuntimeUpdate(CfnLintKeyword):
18+
19+
id = "E2533"
20+
shortdesc = "Check if Lambda Function Runtimes are updatable"
21+
description = (
22+
"Check if an EOL Lambda Runtime is specified and you cannot update the function"
23+
)
24+
source_url = (
25+
"https://docs.aws.amazon.com/lambda/latest/dg/runtime-support-policy.html"
26+
)
27+
tags = ["resources", "lambda", "runtime"]
28+
29+
def __init__(self):
30+
"""Init"""
31+
super().__init__(["Resources/AWS::Lambda::Function/Properties/Runtime"])
32+
self.current_date = datetime.today()
33+
self.deprecated_runtimes = load_resource(
34+
AdditionalSpecs, "LmbdRuntimeLifecycle.json"
35+
)
36+
37+
def validate(
38+
self, validator: Validator, v: Any, runtime: Any, schema: dict[str, Any]
39+
) -> ValidationResult:
40+
if not validator.is_type(runtime, "string"):
41+
return
42+
runtime_data = self.deprecated_runtimes.get(runtime)
43+
if not runtime_data:
44+
return
45+
if (
46+
datetime.strptime(runtime_data["update-block"], "%Y-%m-%d")
47+
<= self.current_date
48+
):
49+
yield ValidationError(
50+
(
51+
f"Runtime {runtime!r} was deprecated on "
52+
f"{runtime_data['deprecated']!r}. Creation was disabled on "
53+
f"{runtime_data['create-block']!r} and update on "
54+
f"{runtime_data['update-block']!r}. Please consider "
55+
f"updating to {runtime_data['successor']!r}"
56+
),
57+
)

0 commit comments

Comments
 (0)