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

V1 - cleaning up more rules #2670

Merged
merged 2 commits into from
Apr 7, 2023
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"additionalProperties": false,
"awsType": true,
"else": {
"not": {
"required": [
Expand Down Expand Up @@ -55,7 +56,6 @@
"type": "object"
},
"Type": {
"awsType": true,
"type": "string"
},
"UpdatePolicy": {
Expand Down
39 changes: 39 additions & 0 deletions src/cfnlint/rules/parameters/AllowedPattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""
from typing import Generator, List, Union

import regex as re

from cfnlint.jsonschema import ValidationError
from cfnlint.rules import CloudFormationLintRule
from cfnlint.template import Template


class AllowedPattern(CloudFormationLintRule):
Expand All @@ -14,3 +19,37 @@ class AllowedPattern(CloudFormationLintRule):
description = "Check if parameters have a valid value in a pattern. The Parameter's allowed pattern is based on the usages in property (Ref)"
source_url = "https://github.com/aws-cloudformation/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#allowedpattern"
tags = ["parameters", "resources", "property", "allowed pattern"]

def __init__(self):
super().__init__()
self.parameters = {}

def initialize(self, cfn: Template):
"""Initialize the rule"""
self.parameters = cfn.get_parameters()

def _pattern(
self, instance: str, patrn: str, path: List[Union[str, int]]
) -> Generator[ValidationError, None, None]:
if not re.search(patrn, instance):
yield ValidationError(
f"{instance!r} does not match {patrn!r}",
rule=self,
path_override=path,
)

def validate(self, ref: str, patrn: str):
p = self.parameters.get(ref, {})
if isinstance(p, dict):
p_default = p.get("Default", None)
if isinstance(p_default, (str)):
yield from self._pattern(
p_default, patrn, ["Parameters", ref, "Default"]
)

p_avs = p.get("AllowedValues", [])
if isinstance(p_avs, list):
for p_av_index, p_av in enumerate(p_avs):
yield from self._pattern(
p_av, patrn, ["Parameters", ref, "AllowedValues", p_av_index]
)
31 changes: 21 additions & 10 deletions src/cfnlint/rules/resources/Configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,40 @@ def __init__(self):
cfn=None,
rules=None,
)(schema=schema)
self.cfn = None

def initialize(self, cfn):
super().initialize(cfn)
self.regions = cfn.regions
self.cfn = cfn

# pylint: disable=unused-argument
def _awsType(self, validator, iT, instance, schema):
if not validator.is_type(instance, "string"):
resource_type = instance.get("Type")
if not validator.is_type(resource_type, "string"):
return

resource_condition = instance.get("Condition")

for region in self.regions:
if instance in PROVIDER_SCHEMA_MANAGER.get_resource_types(region=region):
return
if not instance.startswith(
if validator.is_type(resource_condition, "string"):
if False in self.cfn.conditions.build_scenerios_on_region(
resource_condition, region
):
continue
if resource_type in PROVIDER_SCHEMA_MANAGER.get_resource_types(
region=region
):
continue
if not resource_type.startswith(
("Custom::", "AWS::Serverless::")
) and not instance.endswith("::MODULE"):
) and not resource_type.endswith("::MODULE"):
yield ValidationError(
f"Resource type `{instance}` does not exist in '{region}'"
f"Resource type `{resource_type}` does not exist in '{region}'"
)

# pylint: disable=unused-argument
def _check_resource(self, cfn, resource_name, resource_values):
def _check_resource(self, resource_name, resource_values):
"""Check Resource"""
matches = []

Expand Down Expand Up @@ -97,8 +110,6 @@ def match(self, cfn):
self.logger.debug(
"Validating resource %s base configuration", resource_name
)
matches.extend(
self._check_resource(cfn, resource_name, resource_values)
)
matches.extend(self._check_resource(resource_name, resource_values))

return matches
10 changes: 10 additions & 0 deletions src/cfnlint/rules/resources/properties/AllowedPattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,19 @@ class AllowedPattern(CloudFormationLintRule):
description = "Check if properties have a valid value in case of a pattern (Regular Expression)"
source_url = "https://github.com/awslabs/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#allowedpattern"
tags = ["resources", "property", "allowed pattern", "regex"]
child_rules = {
"W2031": None,
}

# pylint: disable=unused-argument
def pattern(self, validator, patrn, instance, schema):
if isinstance(instance, dict):
if len(instance) == 1:
for k, v in instance.items():
if k == "Ref":
if self.child_rules.get("W2031"):
yield from self.child_rules["W2031"].validate(v, patrn)
return
if validator.is_type(instance, "string"):
# skip any dynamic reference strings
if REGEX_DYN_REF.findall(instance):
Expand Down
33 changes: 0 additions & 33 deletions src/cfnlint/schema/_constants.py

This file was deleted.

35 changes: 34 additions & 1 deletion src/cfnlint/schema/getatts.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,42 @@
import enum
from typing import Any, Dict, Optional

from cfnlint.schema._constants import _all_property_types
from cfnlint.schema._pointer import resolve_pointer

_all_property_types = [
"AWS::Amplify::Branch",
"AWS::Amplify::Domain",
"AWS::AppSync::DomainName",
"AWS::Backup::BackupSelection",
"AWS::Backup::BackupVault",
"AWS::CodeArtifact::Domain",
"AWS::CodeArtifact::Repository",
"AWS::EC2::CapacityReservation",
"AWS::EC2::Subnet",
"AWS::EC2::VPC",
"AWS::EFS::MountTarget",
"AWS::EKS::Nodegroup",
"AWS::ImageBuilder::Component",
"AWS::ImageBuilder::ContainerRecipe",
"AWS::ImageBuilder::DistributionConfiguration",
"AWS::ImageBuilder::ImagePipeline",
"AWS::ImageBuilder::ImageRecipe",
"AWS::ImageBuilder::InfrastructureConfiguration",
"AWS::RDS::DBParameterGroup",
"AWS::RoboMaker::RobotApplication",
"AWS::RoboMaker::SimulationApplication",
"AWS::Route53Resolver::ResolverRule",
"AWS::Route53Resolver::ResolverRuleAssociation",
"AWS::SNS::Topic",
"AWS::SQS::Queue",
"AWS::SageMaker::DataQualityJobDefinition",
"AWS::SageMaker::ModelBiasJobDefinition",
"AWS::SageMaker::ModelExplainabilityJobDefinition",
"AWS::SageMaker::ModelQualityJobDefinition",
"AWS::SageMaker::MonitoringSchedule",
"AWS::StepFunctions::Activity",
]


class GetAttType(enum.Enum):
ReadOnly = 1
Expand Down
Loading