Skip to content

Commit

Permalink
Update GetAtt logic for SC Cfn type (#3475)
Browse files Browse the repository at this point in the history
  • Loading branch information
kddejong authored Jul 8, 2024
1 parent 78e9fa9 commit d87e63c
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 6 deletions.
5 changes: 0 additions & 5 deletions src/cfnlint/rules/functions/GetAtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,6 @@ def _resolve_getatt(
yield err
continue

# because of the complexities of schemas ($ref, anyOf, allOf, etc.)
# we will simplify the validator to just have a type check
# then we will provide a simple value to represent the type from the
# getAtt
evolved = validator.evolve(schema=s) # type: ignore
evolved.validators = { # type: ignore
"type": validator.validators.get("type"), # type: ignore
Expand All @@ -124,7 +120,6 @@ def _resolve_getatt(
t, validator.context.regions
):
getatt_schema = schema.resolver.resolve_cfn_pointer(pointer)

if not getatt_schema.get("type") or not s.get("type"):
continue

Expand Down
8 changes: 8 additions & 0 deletions src/cfnlint/schema/_getatts.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,14 @@ def __init__(self, schema: "Schema") -> None:
self._attrs["Outputs\\..*"] = "/properties/CfnLintStringType"
return

if schema.type_name == "AWS::ServiceCatalog::CloudFormationProvisionedProduct":
for ro_attr in schema.schema.get("readOnlyProperties", []):
if ro_attr == "/properties/Outputs":
self._attrs["Outputs\\..*"] = "/properties/CfnLintStringType"
else:
self._attrs[self._pointer_to_attr(ro_attr)] = ro_attr
return

for unnamed_type in _unnamed_unknown_types:
if schema.type_name.startswith(unnamed_type):
self._attrs[".*"] = "/properties/CfnLintAllTypes"
Expand Down
153 changes: 152 additions & 1 deletion test/unit/module/schema/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ def resource_vpc_schema():


def test_vpc_schema(resource_vpc_schema):

schema = Schema(schema=resource_vpc_schema)
assert list(schema.get_atts.keys()) == [
"CidrBlock",
Expand All @@ -161,3 +160,155 @@ def test_vpc_schema(resource_vpc_schema):
assert schema.get_atts["VpcId"] == "/properties/VpcId"
assert schema.get_atts["CidrBlock"] == "/properties/CidrBlock"
assert schema.get_atts["Ipv6CidrBlocks"] == "/properties/Ipv6CidrBlocks"


@pytest.fixture
def resource_servicecatalog_schema():
return {
"additionalProperties": False,
"createOnlyProperties": [
"/properties/NotificationArns",
"/properties/ProvisionedProductName",
],
"definitions": {
"OutputType": {"type": "string"},
"ProvisioningParameter": {
"additionalProperties": False,
"properties": {
"Key": {"maxLength": 1000, "minLength": 1, "type": "string"},
"Value": {"maxLength": 4096, "type": "string"},
},
"required": ["Key", "Value"],
"type": "object",
},
"ProvisioningPreferences": {
"additionalProperties": False,
"properties": {
"StackSetAccounts": {
"items": {"pattern": "^[0-9]{12}$", "type": "string"},
"type": "array",
"uniqueItems": True,
},
"StackSetFailureToleranceCount": {"minimum": 0, "type": "integer"},
"StackSetFailureTolerancePercentage": {
"maximum": 100,
"minimum": 0,
"type": "integer",
},
"StackSetMaxConcurrencyCount": {"minimum": 1, "type": "integer"},
"StackSetMaxConcurrencyPercentage": {
"maximum": 100,
"minimum": 1,
"type": "integer",
},
"StackSetOperationType": {
"enum": ["CREATE", "UPDATE", "DELETE"],
"type": "string",
},
"StackSetRegions": {
"items": {
"pattern": "^[a-z]{2}-([a-z]+-)+[1-9]",
"type": "string",
},
"type": "array",
"uniqueItems": True,
},
},
"type": "object",
},
"Tag": {
"additionalProperties": False,
"properties": {
"Key": {
"maxLength": 128,
"minLength": 1,
"pattern": "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$",
"type": "string",
},
"Value": {
"maxLength": 256,
"minLength": 1,
"pattern": "^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$",
"type": "string",
},
},
"required": ["Key", "Value"],
"type": "object",
},
},
"documentationUrl": "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-servicecatalog-cloudformationprovisionedproduct.html",
"handlers": {
"create": {"permissions": ["*"], "timeoutInMinutes": 720},
"delete": {"permissions": ["*"]},
"read": {"permissions": ["*"]},
"update": {"permissions": ["*"], "timeoutInMinutes": 720},
},
"primaryIdentifier": ["/properties/ProvisionedProductId"],
"properties": {
"AcceptLanguage": {"enum": ["en", "jp", "zh"], "type": "string"},
"CloudformationStackArn": {
"maxLength": 256,
"minLength": 1,
"type": "string",
},
"NotificationArns": {
"items": {"type": "string"},
"maxItems": 5,
"type": "array",
"uniqueItems": True,
},
"Outputs": {
"additionalProperties": False,
"maxProperties": 100,
"patternProperties": {
"^[A-Za-z0-9]{1,64}$": {"$ref": "#/definitions/OutputType"}
},
"type": "object",
},
"PathId": {"maxLength": 100, "minLength": 1, "type": "string"},
"PathName": {"maxLength": 100, "minLength": 1, "type": "string"},
"ProductId": {"maxLength": 100, "minLength": 1, "type": "string"},
"ProductName": {"maxLength": 128, "minLength": 1, "type": "string"},
"ProvisionedProductId": {"maxLength": 50, "minLength": 1, "type": "string"},
"ProvisionedProductName": {
"maxLength": 128,
"minLength": 1,
"type": "string",
},
"ProvisioningArtifactId": {
"maxLength": 100,
"minLength": 1,
"type": "string",
},
"ProvisioningArtifactName": {"type": "string"},
"ProvisioningParameters": {
"items": {"$ref": "#/definitions/ProvisioningParameter"},
"type": "array",
},
"ProvisioningPreferences": {
"$ref": "#/definitions/ProvisioningPreferences"
},
"RecordId": {"maxLength": 50, "minLength": 1, "type": "string"},
"Tags": {"items": {"$ref": "#/definitions/Tag"}, "type": "array"},
},
"readOnlyProperties": [
"/properties/RecordId",
"/properties/CloudformationStackArn",
"/properties/Outputs",
"/properties/ProvisionedProductId",
],
"sourceUrl": "https://github.com/aws-cloudformation/aws-cloudformation-rpdk.git",
"typeName": "AWS::ServiceCatalog::CloudFormationProvisionedProduct",
}


def test_servicecatalog_cloudformation_schema(resource_servicecatalog_schema):

schema = Schema(schema=resource_servicecatalog_schema)
assert list(schema.get_atts.keys()) == [
"RecordId",
"CloudformationStackArn",
"Outputs\\..*",
"ProvisionedProductId",
]
assert schema.get_atts["Outputs.Example"] == "/properties/CfnLintStringType"

0 comments on commit d87e63c

Please sign in to comment.