Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert resolver errors to warnings #3493

Merged
merged 2 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/cfnlint/rules/functions/FindInMap.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ class FindInMap(BaseFn):
tags = ["functions", "findinmap"]

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

def schema(self, validator: Validator, instance: Any) -> dict[str, Any]:
scalar_schema = {
Expand Down
16 changes: 16 additions & 0 deletions src/cfnlint/rules/functions/FindInMapResolved.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from cfnlint.rules import CloudFormationLintRule


class FindInMapResolved(CloudFormationLintRule):
id = "W1034"
shortdesc = "Validate the values that come from a Fn::FindInMap function"
description = (
"Resolve the Fn::FindInMap and then validate the values against the schema"
)
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-findinmap.html"
tags = ["functions", "findinmap"]
2 changes: 1 addition & 1 deletion src/cfnlint/rules/functions/GetAz.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class GetAz(BaseFn):
tags = ["functions", "getaz"]

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

def schema(self, validator: Validator, instance: Any) -> dict[str, Any]:
Expand Down
16 changes: 16 additions & 0 deletions src/cfnlint/rules/functions/GetAzResolved.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from cfnlint.rules import CloudFormationLintRule


class FindInMapResolved(CloudFormationLintRule):
id = "W1036"
shortdesc = "Validate the values that come from a Fn::GetAZs function"
description = (
"Resolve the Fn::GetAZs and then validate the values against the schema"
)
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getavailabilityzones.html"
tags = ["functions", "getazs"]
10 changes: 6 additions & 4 deletions src/cfnlint/rules/functions/Join.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ class Join(BaseFn):
tags = ["functions", "join"]

def __init__(self) -> None:
super().__init__("Fn::Join", ("string",))
self.child_rules = {
"I1022": None,
}
super().__init__("Fn::Join", ("string",), resolved_rule="W1032")
self.child_rules.update(
{
"I1022": None,
}
)

def schema(self, validator, instance) -> dict[str, Any]:
return {
Expand Down
14 changes: 14 additions & 0 deletions src/cfnlint/rules/functions/JoinResolved.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from cfnlint.rules import CloudFormationLintRule


class JoinResolved(CloudFormationLintRule):
id = "W1032"
shortdesc = "Validate the values that come from a Fn::Join function"
description = "Resolve the Fn::Join and then validate the values against the schema"
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-join.html"
tags = ["functions", "join"]
6 changes: 4 additions & 2 deletions src/cfnlint/rules/functions/Ref.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ class Ref(BaseFn):
tags = ["functions", "ref"]

def __init__(self) -> None:
super().__init__("Ref", all_types)
super().__init__("Ref", all_types, resolved_rule="W1030")
self._all_refs = [
"W2010",
]
self.child_rules = dict.fromkeys(self._all_refs)
self.child_rules.update(dict.fromkeys(self._all_refs))

def schema(self, validator, instance) -> dict[str, Any]:
return {
Expand Down Expand Up @@ -94,5 +94,7 @@ def ref(self, validator, subschema, instance, schema):
for rule in self.child_rules.values():
if not rule or rule.id in self._all_refs:
continue
if not hasattr(rule, "keywords"):
continue
if keyword in rule.keywords:
yield from rule.validate(validator, keyword, instance, schema)
14 changes: 14 additions & 0 deletions src/cfnlint/rules/functions/RefResolved.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from cfnlint.rules import CloudFormationLintRule


class RefResolved(CloudFormationLintRule):
id = "W1030"
shortdesc = "Validate the values that come from a Ref function"
description = "Resolve the Ref and then validate the values against the schema"
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html"
tags = ["functions", "ref"]
2 changes: 1 addition & 1 deletion src/cfnlint/rules/functions/Select.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Select(BaseFn):
tags = ["functions", "select"]

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

def schema(self, validator: Validator, instance: Any) -> dict[str, Any]:
Expand Down
16 changes: 16 additions & 0 deletions src/cfnlint/rules/functions/SelectResolved.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from cfnlint.rules import CloudFormationLintRule


class SelectResolved(CloudFormationLintRule):
id = "W1035"
shortdesc = "Validate the values that come from a Fn::Select function"
description = (
"Resolve the Fn::Select and then validate the values against the schema"
)
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-select.html"
tags = ["functions", "select"]
2 changes: 1 addition & 1 deletion src/cfnlint/rules/functions/Split.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Split(BaseFn):
tags = ["functions", "split"]

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

def schema(self, validator: Validator, instance: Any) -> dict[str, Any]:
return {
Expand Down
16 changes: 16 additions & 0 deletions src/cfnlint/rules/functions/SplitResolved.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from cfnlint.rules import CloudFormationLintRule


class SplitResolved(CloudFormationLintRule):
id = "W1033"
shortdesc = "Validate the values that come from a Fn::Split function"
description = (
"Resolve the Fn::Split and then validate the values against the schema"
)
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-split.html"
tags = ["functions", "split"]
12 changes: 7 additions & 5 deletions src/cfnlint/rules/functions/Sub.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ class Sub(BaseFn):
tags = ["functions", "sub"]

def __init__(self) -> None:
super().__init__("Fn::Sub", ("string",))
super().__init__("Fn::Sub", ("string",), resolved_rule="W1031")
self.sub_parameter_types = ["string", "integer", "number", "boolean"]
self.child_rules = {
"W1019": None,
"W1020": None,
}
self.child_rules.update(
{
"W1019": None,
"W1020": None,
}
)
self._functions = [
"Fn::Base64",
"Fn::FindInMap",
Expand Down
14 changes: 14 additions & 0 deletions src/cfnlint/rules/functions/SubResolved.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from cfnlint.rules import CloudFormationLintRule


class SubResolved(CloudFormationLintRule):
id = "W1031"
shortdesc = "Validate the values that come from a Fn::Sub function"
description = "Resolve the Fn::Sub and then validate the values against the schema"
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html"
tags = ["functions", "sub"]
1 change: 1 addition & 0 deletions src/cfnlint/rules/functions/ToJsonString.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def __init__(self) -> None:
"Fn::Split",
"Ref",
),
resolved_rule="W1040",
)

def schema(self, validator: Validator, instance: Any) -> dict[str, Any]:
Expand Down
16 changes: 16 additions & 0 deletions src/cfnlint/rules/functions/ToJsonStringResolved.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from cfnlint.rules import CloudFormationLintRule


class ToJsonStringResolved(CloudFormationLintRule):
id = "W1040"
shortdesc = "Validate the values that come from a Fn::ToJsonString function"
description = (
"Resolve the Fn::ToJsonString and then validate the values against the schema"
)
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ToJsonString.html"
tags = ["functions", "tojsonstring"]
11 changes: 10 additions & 1 deletion src/cfnlint/rules/functions/_BaseFn.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@ def __init__(
name: str = "",
types: Tuple[str, ...] | None = None,
functions: Tuple[str, ...] | None = None,
resolved_rule: str = "",
) -> None:
super().__init__()
self.fn = ToPy(name)
self.types = types or tuple([])
self.functions = functions or tuple([])
self.resolved_rule = resolved_rule
self.child_rules[self.resolved_rule] = None

def key_value(self, instance: dict[str, Any]) -> Tuple[str, Any]:
return list(instance.keys())[0], instance.get(self.fn.name)
Expand Down Expand Up @@ -60,6 +63,9 @@ def resolve(
instance: Any,
schema: Any,
) -> ValidationResult:
if not self.resolved_rule:
return

key, _ = self.key_value(instance)

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

yield from iter(all_errs)
for err in all_errs:
if self.child_rules[self.resolved_rule]:
err.rule = self.child_rules[self.resolved_rule]
yield err

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

Expand Down
36 changes: 18 additions & 18 deletions test/fixtures/results/quickstart/nist_application.json
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,8 @@
},
{
"Filename": "test/fixtures/templates/quickstart/nist_application.yaml",
"Id": "99444d58-b2c3-aee5-41f9-b2252a17fc41",
"Level": "Error",
"Id": "6ecda82c-9ccf-e772-b940-41eafbc02f6e",
"Level": "Warning",
"Location": {
"End": {
"ColumnNumber": 12,
Expand All @@ -441,10 +441,10 @@
"Message": "{'Ref': 'pAppAmi'} is not a 'AWS::EC2::Image.Id' when 'Ref' is resolved",
"ParentId": null,
"Rule": {
"Description": "Check that a AMI id matches a pattern",
"Id": "E1152",
"ShortDescription": "Validate AMI id format",
"Source": "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/format_keyword.md#AWS::EC2::Image.Id"
"Description": "Resolve the Ref and then validate the values against the schema",
"Id": "W1030",
"ShortDescription": "Validate the values that come from a Ref function",
"Source": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html"
}
},
{
Expand Down Expand Up @@ -644,8 +644,8 @@
},
{
"Filename": "test/fixtures/templates/quickstart/nist_application.yaml",
"Id": "36b41df4-77e9-d1c7-179f-feb9bec8cf8b",
"Level": "Error",
"Id": "300dd743-adad-ad4c-c09d-63fd5e9efcf2",
"Level": "Warning",
"Location": {
"End": {
"ColumnNumber": 12,
Expand All @@ -666,10 +666,10 @@
"Message": "{'Ref': 'pWebServerAMI'} is not a 'AWS::EC2::Image.Id' when 'Ref' is resolved",
"ParentId": null,
"Rule": {
"Description": "Check that a AMI id matches a pattern",
"Id": "E1152",
"ShortDescription": "Validate AMI id format",
"Source": "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/format_keyword.md#AWS::EC2::Image.Id"
"Description": "Resolve the Ref and then validate the values against the schema",
"Id": "W1030",
"ShortDescription": "Validate the values that come from a Ref function",
"Source": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html"
}
},
{
Expand Down Expand Up @@ -1672,8 +1672,8 @@
},
{
"Filename": "test/fixtures/templates/quickstart/nist_application.yaml",
"Id": "2d2c5854-e28f-1351-9543-77260d81770e",
"Level": "Error",
"Id": "ce028b65-d316-4519-8018-ac6ec0477964",
"Level": "Warning",
"Location": {
"End": {
"ColumnNumber": 12,
Expand All @@ -1694,10 +1694,10 @@
"Message": "{'Ref': 'pWebServerAMI'} is not a 'AWS::EC2::Image.Id' when 'Ref' is resolved",
"ParentId": null,
"Rule": {
"Description": "Check that a AMI id matches a pattern",
"Id": "E1152",
"ShortDescription": "Validate AMI id format",
"Source": "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/format_keyword.md#AWS::EC2::Image.Id"
"Description": "Resolve the Ref and then validate the values against the schema",
"Id": "W1030",
"ShortDescription": "Validate the values that come from a Ref function",
"Source": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html"
}
},
{
Expand Down
12 changes: 6 additions & 6 deletions test/fixtures/results/quickstart/nist_vpc_management.json
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,8 @@
},
{
"Filename": "test/fixtures/templates/quickstart/nist_vpc_management.yaml",
"Id": "52edbc3e-89e3-9de8-2e50-09ed7fad4979",
"Level": "Error",
"Id": "f0f419da-862a-4317-0b95-8af2df6e8ad2",
"Level": "Warning",
"Location": {
"End": {
"ColumnNumber": 12,
Expand All @@ -438,10 +438,10 @@
"Message": "{'Ref': 'pBastionAmi'} is not a 'AWS::EC2::Image.Id' when 'Ref' is resolved",
"ParentId": null,
"Rule": {
"Description": "Check that a AMI id matches a pattern",
"Id": "E1152",
"ShortDescription": "Validate AMI id format",
"Source": "https://github.com/aws-cloudformation/cfn-lint/blob/main/docs/format_keyword.md#AWS::EC2::Image.Id"
"Description": "Resolve the Ref and then validate the values against the schema",
"Id": "W1030",
"ShortDescription": "Validate the values that come from a Ref function",
"Source": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html"
}
},
{
Expand Down
Loading
Loading