Skip to content

Commit

Permalink
Increase coverage and update rules
Browse files Browse the repository at this point in the history
  • Loading branch information
kddejong committed Mar 2, 2023
1 parent d6d6394 commit 155e3f4
Show file tree
Hide file tree
Showing 48 changed files with 819 additions and 302 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
},
"Type": {
"type": "string",
"cfnType": true
"awsType": true
},
"UpdateReplacePolicy": {
"type": "string",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@
"aws-autoscaling-autoscalinggroup/onlyone"
]
},
{
"op": "add",
"path": "/properties/AvailabilityZones/awsType",
"value": "AvailabilityZones"
},
{
"op": "add",
"path": "/properties/AvailabilityZones/items/awsType",
"value": "AvailabilityZone"
},
{
"op": "add",
"path": "/definitions/LaunchTemplateSpecification/cfnSchema",
Expand Down
12 changes: 12 additions & 0 deletions src/cfnlint/data/ExtendedProviderSchema/all/aws-dax-cluster.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"op": "add",
"path": "/properties/AvailabilityZones/awsType",
"value": "AvailabilityZones"
},
{
"op": "add",
"path": "/properties/AvailabilityZones/items/awsType",
"value": "AvailabilityZone"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"op": "add",
"path": "/properties/AvailabilityZone/awsType",
"value": "AvailabilityZone"
}
]
7 changes: 7 additions & 0 deletions src/cfnlint/data/ExtendedProviderSchema/all/aws-ec2-host.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"op": "add",
"path": "/properties/AvailabilityZone/awsType",
"value": "AvailabilityZone"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,10 @@
"aws-ec2-instance/blockdevicemapping-virtualname-exclusive",
"aws-ec2-instance/blockdevicemapping-onlyone"
]
},
{
"op": "add",
"path": "/properties/AvailabilityZone/awsType",
"value": "AvailabilityZone"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,10 @@
"op": "add",
"path": "/definitions/BlockDeviceMapping/cfnSchema",
"value": ["aws-ec2-launchtemplate/blockdevicemapping-virtualname"]
},
{
"op": "add",
"path": "/definitions/Placement/properties/AvailabilityZone/awsType",
"value": "AvailabilityZone"
}
]
10 changes: 10 additions & 0 deletions src/cfnlint/data/ExtendedProviderSchema/all/aws-ec2-spotfleet.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,15 @@
"op": "add",
"path": "/definitions/SpotFleetRequestConfigData/cfnSchema",
"value": ["aws-ec2-spotfleet/spotfleetrequestconfigdata-onlyone"]
},
{
"op": "add",
"path": "/definitions/LaunchTemplateOverrides/properties/AvailabilityZone/awsType",
"value": "AvailabilityZone"
},
{
"op": "add",
"path": "/definitions/SpotPlacement/properties/AvailabilityZone/awsType",
"value": "AvailabilityZone"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"op": "add",
"path": "/properties/AvailabilityZone/awsType",
"value": "AvailabilityZone"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"op": "add",
"path": "/properties/AvailabilityZone/awsType",
"value": "AvailabilityZone"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"op": "add",
"path": "/properties/AvailabilityZones/awsType",
"value": "AvailabilityZones"
},
{
"op": "add",
"path": "/properties/AvailabilityZones/items/awsType",
"value": "AvailabilityZone"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"op": "add",
"path": "/definitions/TargetDescription/properties/AvailabilityZone/awsType",
"value": "AvailabilityZone"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"op": "add",
"path": "/definitions/PlacementType/properties/AvailabilityZone/awsType",
"value": "AvailabilityZone"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"op": "add",
"path": "/definitions/PhysicalConnectionRequirements/properties/AvailabilityZone/awsType",
"value": "AvailabilityZone"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@
"aws-opsworks-instance/blockdevicemapping-virtualname",
"aws-opsworks-instance/blockdevicemapping-onlyone"
]
},
{
"op": "add",
"path": "/properties/AvailabilityZone/awsType",
"value": "AvailabilityZone"
}
]
]
10 changes: 10 additions & 0 deletions src/cfnlint/data/ExtendedProviderSchema/all/aws-rds-dbcluster.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,15 @@
"aws-rds-dbcluster/snapshotidentifier-exclusive",
"aws-rds-dbcluster/serverless-exclusive"
]
},
{
"op": "add",
"path": "/properties/AvailabilityZones/awsType",
"value": "AvailabilityZones"
},
{
"op": "add",
"path": "/properties/AvailabilityZones/items/awsType",
"value": "AvailabilityZone"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,10 @@
"aws-rds-dbinstance/sourcedbinstanceidentifier-exclusive",
"aws-rds-dbinstance/aurora-exclusive"
]
},
{
"op": "add",
"path": "/properties/AvailabilityZone/awsType",
"value": "AvailabilityZone"
}
]
59 changes: 12 additions & 47 deletions src/cfnlint/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@
import re
import sys
from io import BytesIO
from typing import Dict, List
from typing import List
from urllib.request import Request, urlopen, urlretrieve

import jsonpatch

LOGGER = logging.getLogger(__name__)

SPEC_REGIONS = {
Expand Down Expand Up @@ -110,17 +108,21 @@
FUNCTION_NOT = "Fn::Not"
FUNCTION_EQUALS = "Fn::Equals"

PSEUDOPARAMS = [
PSEUDOPARAMS_SINGLE = [
"AWS::AccountId",
"AWS::NotificationARNs",
"AWS::NoValue",
"AWS::Partition",
"AWS::Region",
"AWS::StackId",
"AWS::StackName",
"AWS::URLSuffix",
]

PSEUDOPARAMS_MULTIPLE = [
"AWS::NotificationARNs",
]

PSEUDOPARAMS = ["AWS::NoValue"] + PSEUDOPARAMS_SINGLE + PSEUDOPARAMS_MULTIPLE

LIMITS = {
"Mappings": {"number": 200, "attributes": 200, "name": 255}, # in characters
"Outputs": {
Expand Down Expand Up @@ -220,15 +222,10 @@ def __getitem__(self, item):
return possible_items[longest_match]

def __contains__(self, item):
for k, v in self.items():
if isinstance(v, dict):
if v.get("Type") == "MODULE":
if re.match(k, item):
return True
else:
if k == item:
return True
elif re.match(k, item):
if isinstance(item, (dict, list)):
return False
for k, _ in self.items():
if re.fullmatch(k, item):
return True
return False

Expand Down Expand Up @@ -328,7 +325,6 @@ def get_url_retrieve(url: str, caching: bool = False) -> str:
"""

if caching:
# Need to wrap this in a try, as URLLib2 in Python2 doesn't support HEAD requests
req = Request(url, method="HEAD")
with urlopen(req) as res:
if res.info().get("ETag"):
Expand Down Expand Up @@ -380,19 +376,6 @@ def load_resource(package, filename="us-east-1.json"):
REGISTRY_SCHEMAS: List[dict] = []


def merge_spec(source, destination):
"""Recursive merge spec dict"""

for key, value in source.items():
if isinstance(value, dict):
node = destination.setdefault(key, {})
merge_spec(value, node)
else:
destination[key] = value

return destination


def is_custom_resource(resource_type):
"""Return True if resource_type is a custom resource"""
return resource_type and (
Expand Down Expand Up @@ -486,21 +469,3 @@ def onerror(os_error):
result.extend(create_rules(mod))

return result


def apply_json_patch(data: Dict, patches: List[Dict], region: str) -> Dict:
# Process the generic patches 1 by 1 so we can "ignore" failed ones
for patch in patches:
try:
jsonpatch.JsonPatch([patch]).apply(data, in_place=True)
except jsonpatch.JsonPatchConflict:
LOGGER.debug("Patch (%s) not applied in region %s", patch, region)
except jsonpatch.JsonPointerException:
# Debug as the parent element isn't supported in the region
LOGGER.debug(
"Parent element not found for patch (%s) in region %s",
patches,
region,
)

return data
8 changes: 8 additions & 0 deletions src/cfnlint/jsonschema/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,11 @@ class Unset:

def __repr__(self):
return "<unset>"


def unbool(element, true=object(), false=object()):
if element is True:
return true
if element is False:
return false
return element
2 changes: 1 addition & 1 deletion src/cfnlint/jsonschema/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
equal,
extras_msg,
find_additional_properties,
unbool,
uniq,
)

from cfnlint.jsonschema._utils import unbool
from cfnlint.jsonschema.exceptions import ValidationError


Expand Down
14 changes: 0 additions & 14 deletions src/cfnlint/rules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,6 @@ def wrapper(self, filename: str, cfn: Template, *args, **kwargs):
if match_type == "match_resource_properties":
if args[1] not in self.resource_property_types:
return []
elif match_type == "match_resource_sub_properties":
if args[1] not in self.resource_sub_property_types:
return []

start = datetime.now()
LOGGER.debug("Starting match function for rule %s at %s", self.id, start)
Expand Down Expand Up @@ -220,7 +217,6 @@ def configure(self, configs=None, experimental=False):

match: Callable[[Template], List[RuleMatch]] = None # type: ignore
match_resource_properties: Callable[[Dict, str, List[str], Template], List[RuleMatch]] = None # type: ignore
match_resource_sub_properties: Callable[[Dict, str, List[str], Template], List[RuleMatch]] = None # type: ignore

@matching("match")
# pylint: disable=W0613
Expand All @@ -238,16 +234,6 @@ def matchall_resource_properties(
resource_properties, property_type, path, cfn
)

@matching("match_resource_sub_properties")
# pylint: disable=W0613
def matchall_resource_sub_properties(
self, filename, cfn, resource_properties, property_type, path
):
"""Check for resource properties type"""
return self.match_resource_sub_properties( # pylint: disable=E1102
resource_properties, property_type, path, cfn
)


# pylint: disable=too-many-instance-attributes
class RulesCollection:
Expand Down
13 changes: 3 additions & 10 deletions src/cfnlint/rules/functions/GetAtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from jsonschema.exceptions import best_match
from jsonschema.validators import extend

from cfnlint.jsonschema import ValidationError
from cfnlint.jsonschema import ValidationError, _utils
from cfnlint.rules import CloudFormationLintRule, RuleMatch
from cfnlint.template import Template

Expand All @@ -26,19 +26,12 @@ class GetAtt(CloudFormationLintRule):
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-getatt.html"
tags = ["functions", "getatt"]

def _unbool(self, element, true=object(), false=object()):
if element is True:
return true
if element is False:
return false
return element

# pylint: disable=unused-argument
def _enum(self, validator, enums, instance, schema):
enums.sort()
if instance in (0, 1):
unbooled = self._unbool(instance)
if all(unbooled != self._unbool(each) for each in enums):
unbooled = _utils.unbool(instance)
if all(unbooled != _utils.unbool(each) for each in enums):
yield ValidationError(f"{instance!r} is not one of {enums!r}")
elif instance not in enums:
if validator.is_type(instance, "string"):
Expand Down
Loading

0 comments on commit 155e3f4

Please sign in to comment.