Skip to content

Commit

Permalink
Create rule E3055 to validate CreationPolicy (#3609)
Browse files Browse the repository at this point in the history
* Create rule E3055 to validate CreationPolicy
* Better patch for required properties on AutoScalingGroup
  • Loading branch information
kddejong authored Aug 19, 2024
1 parent e500fcc commit 439806b
Show file tree
Hide file tree
Showing 6 changed files with 302 additions and 67 deletions.
28 changes: 6 additions & 22 deletions scripts/update_schemas_manually.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,28 +79,12 @@
),
Patch(
values={
"dependentExcluded": {
"InstanceId": [
"LaunchConfigurationName",
"LaunchTemplate",
"MixedInstancesPolicy",
],
"LaunchConfigurationName": [
"InstanceId",
"LaunchTemplate",
"MixedInstancesPolicy",
],
"LaunchTemplate": [
"InstanceId",
"LaunchConfigurationName",
"MixedInstancesPolicy",
],
"MixedInstancesPolicy": [
"InstanceId",
"LaunchConfigurationName",
"LaunchTemplate",
],
},
"requiredXor": [
"InstanceId",
"LaunchConfigurationName",
"LaunchTemplate",
"MixedInstancesPolicy",
]
},
path="/",
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,12 @@
},
{
"op": "add",
"path": "/dependentExcluded",
"value": {
"InstanceId": [
"LaunchConfigurationName",
"LaunchTemplate",
"MixedInstancesPolicy"
],
"LaunchConfigurationName": [
"InstanceId",
"LaunchTemplate",
"MixedInstancesPolicy"
],
"LaunchTemplate": [
"InstanceId",
"LaunchConfigurationName",
"MixedInstancesPolicy"
],
"MixedInstancesPolicy": [
"InstanceId",
"LaunchConfigurationName",
"LaunchTemplate"
]
}
"path": "/requiredXor",
"value": [
"InstanceId",
"LaunchConfigurationName",
"LaunchTemplate",
"MixedInstancesPolicy"
]
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -459,28 +459,6 @@
"type": "object"
}
},
"dependentExcluded": {
"InstanceId": [
"LaunchConfigurationName",
"LaunchTemplate",
"MixedInstancesPolicy"
],
"LaunchConfigurationName": [
"InstanceId",
"LaunchTemplate",
"MixedInstancesPolicy"
],
"LaunchTemplate": [
"InstanceId",
"LaunchConfigurationName",
"MixedInstancesPolicy"
],
"MixedInstancesPolicy": [
"InstanceId",
"LaunchConfigurationName",
"LaunchTemplate"
]
},
"deprecatedProperties": [
"/properties/NotificationConfiguration"
],
Expand Down Expand Up @@ -715,6 +693,12 @@
"MinSize",
"MaxSize"
],
"requiredXor": [
"InstanceId",
"LaunchConfigurationName",
"LaunchTemplate",
"MixedInstancesPolicy"
],
"tagging": {
"cloudFormationSystemTags": true,
"tagOnCreate": true,
Expand Down
102 changes: 102 additions & 0 deletions src/cfnlint/rules/resources/CreationPolicy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from __future__ import annotations

from typing import Any

from cfnlint.jsonschema import Validator
from cfnlint.rules.jsonschema.CfnLintJsonSchema import CfnLintJsonSchema


class CreationPolicy(CfnLintJsonSchema):
id = "E3055"
shortdesc = "Check CreationPolicy values for Resources"
description = "Check that the CreationPolicy values are valid"
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-attribute-creationpolicy.html"
tags = ["resources", "creationPolicy"]

def __init__(self) -> None:
super().__init__(
keywords=["Resources/*/CreationPolicy"],
all_matches=True,
)

def _get_schema(self, resource_type: str) -> dict[str, Any]:
if resource_type == "AWS::AppStream::Fleet":
return {
"type": "object",
"additionalProperties": False,
"properties": {
"StartFleet": {
"additionalProperties": False,
"type": "object",
"properties": {"Type": {"type": "boolean"}},
}
},
}
if resource_type == "AWS::AutoScaling::AutoScalingGroup":
return {
"type": "object",
"additionalProperties": False,
"properties": {
"AutoScalingCreationPolicy": {
"type": "object",
"additionalProperties": False,
"properties": {
"MinSuccessfulInstancesPercent": {"type": "integer"}
},
},
"ResourceSignal": {
"additionalProperties": False,
"type": "object",
"properties": {
"Timeout": {"type": "string"},
"Count": {"type": "integer"},
},
},
},
}
if resource_type == "AWS::CloudFormation::WaitCondition":

return {
"type": "object",
"additionalProperties": False,
"properties": {
"ResourceSignal": {
"additionalProperties": False,
"type": "object",
"properties": {
"Timeout": {"type": "string"},
"Count": {"type": "integer"},
},
}
},
}

return {}

# pylint: disable=unused-argument, arguments-renamed
def validate(self, validator: Validator, dP: str, instance, schema):
resource_name = validator.context.path.path[1]
if not isinstance(resource_name, str):
return
resource_type = validator.context.resources[resource_name].type

validator = validator.evolve(
context=validator.context.evolve(
functions=[
"Fn::Sub",
"Fn::Select",
"Fn::FindInMap",
"Fn::If",
"Ref",
],
strict_types=False,
),
schema=self._get_schema(resource_type),
)

yield from self._iter_errors(validator, instance)
1 change: 1 addition & 0 deletions test/integration/test_schema_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class TestSchemaFiles(TestCase):
"Resources",
"Resources/*",
"Resources/*/Condition",
"Resources/*/CreationPolicy",
"Resources/*/DeletionPolicy",
"Resources/*/DependsOn",
"Resources/*/DependsOn/*",
Expand Down
Loading

0 comments on commit 439806b

Please sign in to comment.