Skip to content

Commit

Permalink
Add two new rules to validate fargate tasks (#3464)
Browse files Browse the repository at this point in the history
* Add rule E3047 to validate ECS Fargate cpu/memory
* Add two new rules to validate fargate tasks
  • Loading branch information
kddejong authored Jul 15, 2024
1 parent 4e28934 commit 83b0cdb
Show file tree
Hide file tree
Showing 6 changed files with 521 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
{
"if": {
"properties": {
"Cpu": {
"type": [
"string",
"integer"
]
},
"Memory": {
"type": [
"string",
"integer"
]
},
"RequiresCompatibilities": {
"contains": {
"enum": [
"FARGATE"
],
"type": "string"
},
"type": "array"
}
},
"required": [
"RequiresCompatibilities",
"Cpu",
"Memory"
]
},
"then": {
"anyOf": [
{
"properties": {
"Cpu": {
"enum": [
"256"
]
},
"Memory": {
"enum": [
"512",
"1024",
"2048"
]
}
}
},
{
"properties": {
"Cpu": {
"enum": [
"512"
]
},
"Memory": {
"maximum": 4096,
"minimum": 1024,
"multipleOf": 1024
}
}
},
{
"properties": {
"Cpu": {
"enum": [
"1024"
]
},
"Memory": {
"maximum": 8192,
"minimum": 2048,
"multipleOf": 1024
}
}
},
{
"properties": {
"Cpu": {
"enum": [
"2048"
]
},
"Memory": {
"maximum": 16384,
"minimum": 4096,
"multipleOf": 1024
}
}
},
{
"properties": {
"Cpu": {
"enum": [
"4096"
]
},
"Memory": {
"maximum": 30720,
"minimum": 8192,
"multipleOf": 1024
}
}
},
{
"properties": {
"Cpu": {
"enum": [
"8192"
]
},
"Memory": {
"maximum": 61440,
"minimum": 16384,
"multipleOf": 4096
}
}
},
{
"properties": {
"Cpu": {
"enum": [
"16384"
]
},
"Memory": {
"maximum": 122880,
"minimum": 32768,
"multipleOf": 8192
}
}
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"if": {
"properties": {
"RequiresCompatibilities": {
"contains": {
"enum": [
"FARGATE"
],
"type": "string"
},
"type": "array"
}
},
"required": [
"RequiresCompatibilities"
]
},
"then": {
"if": {
"properties": {
"Cpu": {
"type": [
"string",
"integer"
]
}
},
"required": [
"Cpu"
]
},
"not": {
"required": [
"PlacementConstraints"
]
},
"required": [
"Cpu",
"Memory"
],
"then": {
"properties": {
"Cpu": {
"enum": [
"256",
"512",
"1024",
"2048",
"4096",
"8192",
"16384"
]
}
}
}
}
}
41 changes: 41 additions & 0 deletions src/cfnlint/rules/resources/ecs/FargateCpuMemory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from __future__ import annotations

from typing import Any

import cfnlint.data.schemas.extensions.aws_ecs_taskdefinition
from cfnlint.jsonschema import ValidationError
from cfnlint.rules.jsonschema.CfnLintJsonSchema import CfnLintJsonSchema, SchemaDetails


class FargateCpuMemory(CfnLintJsonSchema):
id = "E3047"
shortdesc = (
"Validate ECS Fargate tasks have the right combination of CPU and memory"
)
description = (
"When using a ECS Fargate task there is a specfic combination "
"of memory and cpu that can be used"
)
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html#cfn-ecs-taskdefinition-memory"
tags = ["properties", "ecs", "service", "container", "fargate"]

def __init__(self) -> None:
super().__init__(
keywords=["Resources/AWS::ECS::TaskDefinition/Properties"],
schema_details=SchemaDetails(
module=cfnlint.data.schemas.extensions.aws_ecs_taskdefinition,
filename="fargate_cpu_memory.json",
),
)

def message(self, instance: Any, err: ValidationError) -> str:
return (
f"Cpu {instance.get('Cpu')!r} is not "
"compatible with memory "
f"{instance.get('Memory')!r}"
)
46 changes: 46 additions & 0 deletions src/cfnlint/rules/resources/ecs/TaskFargateProperties.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from __future__ import annotations

from collections import deque
from typing import Any

import cfnlint.data.schemas.extensions.aws_ecs_taskdefinition
from cfnlint.jsonschema import ValidationResult
from cfnlint.jsonschema.protocols import Validator
from cfnlint.rules.jsonschema.CfnLintJsonSchema import CfnLintJsonSchema, SchemaDetails


class TaskFargateProperties(CfnLintJsonSchema):
id = "E3048"
shortdesc = "Validate ECS Fargate tasks have required properties and values"
description = (
"When using a ECS Fargate task there is a specfic combination "
"of required properties and values"
)
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html#cfn-ecs-taskdefinition-memory"
tags = ["properties", "ecs", "service", "container", "fargate"]

def __init__(self) -> None:
super().__init__(
keywords=["Resources/AWS::ECS::TaskDefinition/Properties"],
schema_details=SchemaDetails(
module=cfnlint.data.schemas.extensions.aws_ecs_taskdefinition,
filename="fargate_properties.json",
),
all_matches=True,
)

def validate(
self, validator: Validator, keywords: Any, instance: Any, schema: dict[str, Any]
) -> ValidationResult:
for err in super().validate(validator, keywords, instance, schema):
if err.validator == "not":
err.message = "'PlacementConstraints' isn't supported for Fargate tasks"
err.path = deque(["PlacementConstraints"])
yield err
continue
yield err
Loading

0 comments on commit 83b0cdb

Please sign in to comment.