Skip to content

Commit 6c99760

Browse files
authored
Convert resolver errors to warnings (#3493)
1 parent b56947d commit 6c99760

24 files changed

+219
-60
lines changed

src/cfnlint/rules/functions/FindInMap.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ class FindInMap(BaseFn):
2121
tags = ["functions", "findinmap"]
2222

2323
def __init__(self) -> None:
24-
super().__init__("Fn::FindInMap", ("array",) + singular_types)
24+
super().__init__(
25+
"Fn::FindInMap", ("array",) + singular_types, resolved_rule="W1034"
26+
)
2527

2628
def schema(self, validator: Validator, instance: Any) -> dict[str, Any]:
2729
scalar_schema = {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
from cfnlint.rules import CloudFormationLintRule
7+
8+
9+
class FindInMapResolved(CloudFormationLintRule):
10+
id = "W1034"
11+
shortdesc = "Validate the values that come from a Fn::FindInMap function"
12+
description = (
13+
"Resolve the Fn::FindInMap and then validate the values against the schema"
14+
)
15+
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-findinmap.html"
16+
tags = ["functions", "findinmap"]

src/cfnlint/rules/functions/GetAz.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class GetAz(BaseFn):
2222
tags = ["functions", "getaz"]
2323

2424
def __init__(self) -> None:
25-
super().__init__("Fn::GetAZs", ("array",), ("Ref",))
25+
super().__init__("Fn::GetAZs", ("array",), ("Ref",), resolved_rule="W1036")
2626
self.fn_getazs = self.validate
2727

2828
def schema(self, validator: Validator, instance: Any) -> dict[str, Any]:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
from cfnlint.rules import CloudFormationLintRule
7+
8+
9+
class FindInMapResolved(CloudFormationLintRule):
10+
id = "W1036"
11+
shortdesc = "Validate the values that come from a Fn::GetAZs function"
12+
description = (
13+
"Resolve the Fn::GetAZs and then validate the values against the schema"
14+
)
15+
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getavailabilityzones.html"
16+
tags = ["functions", "getazs"]

src/cfnlint/rules/functions/Join.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ class Join(BaseFn):
2222
tags = ["functions", "join"]
2323

2424
def __init__(self) -> None:
25-
super().__init__("Fn::Join", ("string",))
26-
self.child_rules = {
27-
"I1022": None,
28-
}
25+
super().__init__("Fn::Join", ("string",), resolved_rule="W1032")
26+
self.child_rules.update(
27+
{
28+
"I1022": None,
29+
}
30+
)
2931

3032
def schema(self, validator, instance) -> dict[str, Any]:
3133
return {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
from cfnlint.rules import CloudFormationLintRule
7+
8+
9+
class JoinResolved(CloudFormationLintRule):
10+
id = "W1032"
11+
shortdesc = "Validate the values that come from a Fn::Join function"
12+
description = "Resolve the Fn::Join and then validate the values against the schema"
13+
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-join.html"
14+
tags = ["functions", "join"]

src/cfnlint/rules/functions/Ref.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ class Ref(BaseFn):
2222
tags = ["functions", "ref"]
2323

2424
def __init__(self) -> None:
25-
super().__init__("Ref", all_types)
25+
super().__init__("Ref", all_types, resolved_rule="W1030")
2626
self._all_refs = [
2727
"W2010",
2828
]
29-
self.child_rules = dict.fromkeys(self._all_refs)
29+
self.child_rules.update(dict.fromkeys(self._all_refs))
3030

3131
def schema(self, validator, instance) -> dict[str, Any]:
3232
return {
@@ -94,5 +94,7 @@ def ref(self, validator, subschema, instance, schema):
9494
for rule in self.child_rules.values():
9595
if not rule or rule.id in self._all_refs:
9696
continue
97+
if not hasattr(rule, "keywords"):
98+
continue
9799
if keyword in rule.keywords:
98100
yield from rule.validate(validator, keyword, instance, schema)
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
from cfnlint.rules import CloudFormationLintRule
7+
8+
9+
class RefResolved(CloudFormationLintRule):
10+
id = "W1030"
11+
shortdesc = "Validate the values that come from a Ref function"
12+
description = "Resolve the Ref and then validate the values against the schema"
13+
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html"
14+
tags = ["functions", "ref"]

src/cfnlint/rules/functions/Select.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class Select(BaseFn):
2121
tags = ["functions", "select"]
2222

2323
def __init__(self) -> None:
24-
super().__init__("Fn::Select", all_types)
24+
super().__init__("Fn::Select", all_types, resolved_rule="W1035")
2525
self.fn_select = self.validate
2626

2727
def schema(self, validator: Validator, instance: Any) -> dict[str, Any]:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
from cfnlint.rules import CloudFormationLintRule
7+
8+
9+
class SelectResolved(CloudFormationLintRule):
10+
id = "W1035"
11+
shortdesc = "Validate the values that come from a Fn::Select function"
12+
description = (
13+
"Resolve the Fn::Select and then validate the values against the schema"
14+
)
15+
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-select.html"
16+
tags = ["functions", "select"]

src/cfnlint/rules/functions/Split.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class Split(BaseFn):
2626
tags = ["functions", "split"]
2727

2828
def __init__(self) -> None:
29-
super().__init__("Fn::Split", ("array",))
29+
super().__init__("Fn::Split", ("array",), resolved_rule="W1033")
3030

3131
def schema(self, validator: Validator, instance: Any) -> dict[str, Any]:
3232
return {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
from cfnlint.rules import CloudFormationLintRule
7+
8+
9+
class SplitResolved(CloudFormationLintRule):
10+
id = "W1033"
11+
shortdesc = "Validate the values that come from a Fn::Split function"
12+
description = (
13+
"Resolve the Fn::Split and then validate the values against the schema"
14+
)
15+
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-split.html"
16+
tags = ["functions", "split"]

src/cfnlint/rules/functions/Sub.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ class Sub(BaseFn):
2525
tags = ["functions", "sub"]
2626

2727
def __init__(self) -> None:
28-
super().__init__("Fn::Sub", ("string",))
28+
super().__init__("Fn::Sub", ("string",), resolved_rule="W1031")
2929
self.sub_parameter_types = ["string", "integer", "number", "boolean"]
30-
self.child_rules = {
31-
"W1019": None,
32-
"W1020": None,
33-
}
30+
self.child_rules.update(
31+
{
32+
"W1019": None,
33+
"W1020": None,
34+
}
35+
)
3436
self._functions = [
3537
"Fn::Base64",
3638
"Fn::FindInMap",
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
from cfnlint.rules import CloudFormationLintRule
7+
8+
9+
class SubResolved(CloudFormationLintRule):
10+
id = "W1031"
11+
shortdesc = "Validate the values that come from a Fn::Sub function"
12+
description = "Resolve the Fn::Sub and then validate the values against the schema"
13+
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html"
14+
tags = ["functions", "sub"]

src/cfnlint/rules/functions/ToJsonString.py

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ def __init__(self) -> None:
3434
"Fn::Split",
3535
"Ref",
3636
),
37+
resolved_rule="W1040",
3738
)
3839

3940
def schema(self, validator: Validator, instance: Any) -> dict[str, Any]:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
from cfnlint.rules import CloudFormationLintRule
7+
8+
9+
class ToJsonStringResolved(CloudFormationLintRule):
10+
id = "W1040"
11+
shortdesc = "Validate the values that come from a Fn::ToJsonString function"
12+
description = (
13+
"Resolve the Fn::ToJsonString and then validate the values against the schema"
14+
)
15+
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ToJsonString.html"
16+
tags = ["functions", "tojsonstring"]

src/cfnlint/rules/functions/_BaseFn.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,14 @@ def __init__(
2323
name: str = "",
2424
types: Tuple[str, ...] | None = None,
2525
functions: Tuple[str, ...] | None = None,
26+
resolved_rule: str = "",
2627
) -> None:
2728
super().__init__()
2829
self.fn = ToPy(name)
2930
self.types = types or tuple([])
3031
self.functions = functions or tuple([])
32+
self.resolved_rule = resolved_rule
33+
self.child_rules[self.resolved_rule] = None
3134

3235
def key_value(self, instance: dict[str, Any]) -> Tuple[str, Any]:
3336
return list(instance.keys())[0], instance.get(self.fn.name)
@@ -60,6 +63,9 @@ def resolve(
6063
instance: Any,
6164
schema: Any,
6265
) -> ValidationResult:
66+
if not self.resolved_rule:
67+
return
68+
6369
key, _ = self.key_value(instance)
6470

6571
validator = validator.evolve(
@@ -90,7 +96,10 @@ def resolve(
9096
err.message = f"{err.message} when {self.fn.name!r} is resolved"
9197
all_errs.append(err)
9298

93-
yield from iter(all_errs)
99+
for err in all_errs:
100+
if self.child_rules[self.resolved_rule]:
101+
err.rule = self.child_rules[self.resolved_rule]
102+
yield err
94103

95104
def _resolve_ref(self, validator, schema) -> Any:
96105

test/fixtures/results/quickstart/nist_application.json

+18-18
Original file line numberDiff line numberDiff line change
@@ -419,8 +419,8 @@
419419
},
420420
{
421421
"Filename": "test/fixtures/templates/quickstart/nist_application.yaml",
422-
"Id": "99444d58-b2c3-aee5-41f9-b2252a17fc41",
423-
"Level": "Error",
422+
"Id": "6ecda82c-9ccf-e772-b940-41eafbc02f6e",
423+
"Level": "Warning",
424424
"Location": {
425425
"End": {
426426
"ColumnNumber": 12,
@@ -441,10 +441,10 @@
441441
"Message": "{'Ref': 'pAppAmi'} is not a 'AWS::EC2::Image.Id' when 'Ref' is resolved",
442442
"ParentId": null,
443443
"Rule": {
444-
"Description": "Check that a AMI id matches a pattern",
445-
"Id": "E1152",
446-
"ShortDescription": "Validate AMI id format",
447-
"Source": "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/format_keyword.md#AWS::EC2::Image.Id"
444+
"Description": "Resolve the Ref and then validate the values against the schema",
445+
"Id": "W1030",
446+
"ShortDescription": "Validate the values that come from a Ref function",
447+
"Source": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html"
448448
}
449449
},
450450
{
@@ -644,8 +644,8 @@
644644
},
645645
{
646646
"Filename": "test/fixtures/templates/quickstart/nist_application.yaml",
647-
"Id": "36b41df4-77e9-d1c7-179f-feb9bec8cf8b",
648-
"Level": "Error",
647+
"Id": "300dd743-adad-ad4c-c09d-63fd5e9efcf2",
648+
"Level": "Warning",
649649
"Location": {
650650
"End": {
651651
"ColumnNumber": 12,
@@ -666,10 +666,10 @@
666666
"Message": "{'Ref': 'pWebServerAMI'} is not a 'AWS::EC2::Image.Id' when 'Ref' is resolved",
667667
"ParentId": null,
668668
"Rule": {
669-
"Description": "Check that a AMI id matches a pattern",
670-
"Id": "E1152",
671-
"ShortDescription": "Validate AMI id format",
672-
"Source": "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/format_keyword.md#AWS::EC2::Image.Id"
669+
"Description": "Resolve the Ref and then validate the values against the schema",
670+
"Id": "W1030",
671+
"ShortDescription": "Validate the values that come from a Ref function",
672+
"Source": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html"
673673
}
674674
},
675675
{
@@ -1672,8 +1672,8 @@
16721672
},
16731673
{
16741674
"Filename": "test/fixtures/templates/quickstart/nist_application.yaml",
1675-
"Id": "2d2c5854-e28f-1351-9543-77260d81770e",
1676-
"Level": "Error",
1675+
"Id": "ce028b65-d316-4519-8018-ac6ec0477964",
1676+
"Level": "Warning",
16771677
"Location": {
16781678
"End": {
16791679
"ColumnNumber": 12,
@@ -1694,10 +1694,10 @@
16941694
"Message": "{'Ref': 'pWebServerAMI'} is not a 'AWS::EC2::Image.Id' when 'Ref' is resolved",
16951695
"ParentId": null,
16961696
"Rule": {
1697-
"Description": "Check that a AMI id matches a pattern",
1698-
"Id": "E1152",
1699-
"ShortDescription": "Validate AMI id format",
1700-
"Source": "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/format_keyword.md#AWS::EC2::Image.Id"
1697+
"Description": "Resolve the Ref and then validate the values against the schema",
1698+
"Id": "W1030",
1699+
"ShortDescription": "Validate the values that come from a Ref function",
1700+
"Source": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html"
17011701
}
17021702
},
17031703
{

test/fixtures/results/quickstart/nist_vpc_management.json

+6-6
Original file line numberDiff line numberDiff line change
@@ -416,8 +416,8 @@
416416
},
417417
{
418418
"Filename": "test/fixtures/templates/quickstart/nist_vpc_management.yaml",
419-
"Id": "52edbc3e-89e3-9de8-2e50-09ed7fad4979",
420-
"Level": "Error",
419+
"Id": "f0f419da-862a-4317-0b95-8af2df6e8ad2",
420+
"Level": "Warning",
421421
"Location": {
422422
"End": {
423423
"ColumnNumber": 12,
@@ -438,10 +438,10 @@
438438
"Message": "{'Ref': 'pBastionAmi'} is not a 'AWS::EC2::Image.Id' when 'Ref' is resolved",
439439
"ParentId": null,
440440
"Rule": {
441-
"Description": "Check that a AMI id matches a pattern",
442-
"Id": "E1152",
443-
"ShortDescription": "Validate AMI id format",
444-
"Source": "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/format_keyword.md#AWS::EC2::Image.Id"
441+
"Description": "Resolve the Ref and then validate the values against the schema",
442+
"Id": "W1030",
443+
"ShortDescription": "Validate the values that come from a Ref function",
444+
"Source": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html"
445445
}
446446
},
447447
{

0 commit comments

Comments
 (0)