Skip to content

Commit

Permalink
Add rule E3047 to validate ECS Fargate cpu/memory
Browse files Browse the repository at this point in the history
  • Loading branch information
kddejong committed Jul 4, 2024
1 parent 07705c0 commit b713f39
Show file tree
Hide file tree
Showing 3 changed files with 259 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
{
"if": {
"properties": {
"RequiresCompatibilities": {
"type": "array",
"contains": {
"type": "string",
"enum": ["FARGATE"]
}
},
"Cpu": {
"type": ["string", "integer"]
},
"Memory": {
"type": ["string", "integer"]
}
},
"required": ["RequiresCompatibilities", "Cpu", "Memory"]
},
"then": {
"anyOf": [
{
"properties": {
"Cpu": {
"enum": ["256", 256]
},
"Memory": {
"enum": [
"512",
"1024",
"2048",
512,
1024,
2048
]
}
}
},
{
"properties": {
"Cpu": {
"enum": ["512", 512]
},
"Memory": {
"minimum": 1024,
"maximum": 4096,
"multipleOf": 1024
}
}
},
{
"properties": {
"Cpu": {
"enum": ["1024", 1024]
},
"Memory": {
"minimum": 2048,
"maximum": 8192,
"multipleOf": 1024
}
}
},
{
"properties": {
"Cpu": {
"enum": ["2048", 2048]
},
"Memory": {
"minimum": 4096,
"maximum": 16384,
"multipleOf": 1024
}
}
},
{
"properties": {
"Cpu": {
"enum": ["4096", 4096]
},
"Memory": {
"minimum": 8192,
"maximum": 30720,
"multipleOf": 1024

}
}
},
{
"properties": {
"Cpu": {
"enum": ["8192", 8192]
},
"Memory": {
"minimum": 16384,
"maximum": 61440,
"multipleOf": 4096
}
}
},
{
"properties": {
"Cpu": {
"enum": ["16384", 16384]
},
"Memory": {
"minimum": 32768,
"maximum": 122880,
"multipleOf": 8192
}
}
}
]
}
}
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}"
)
104 changes: 104 additions & 0 deletions test/unit/rules/resources/ecs/test_ecs_fargate_cpu_memory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from collections import deque

import pytest

from cfnlint.jsonschema import ValidationError
from cfnlint.rules.resources.ecs.FargateCpuMemory import FargateCpuMemory


@pytest.fixture(scope="module")
def rule():
rule = FargateCpuMemory()
yield rule


@pytest.mark.parametrize(
"instance,expected",
[
(
{
"RequiresCompatibilities": ["FARGATE"],
"Cpu": 256,
"Memory": "512",
},
[],
),
(
{
"RequiresCompatibilities": ["FARGATE"],
"Cpu": "512",
"Memory": 1024,
},
[],
),
(
{
"RequiresCompatibilities": ["FARGATE"],
"Cpu": "1024",
"Memory": "2048",
},
[],
),
(
{
"RequiresCompatibilities": ["FARGATE"],
"Cpu": 2048,
"Memory": 4096,
},
[],
),
(
{
"RequiresCompatibilities": ["FARGATE"],
"Cpu": 4096,
"Memory": 30720,
},
[],
),
(
{
"RequiresCompatibilities": ["FARGATE"],
"Cpu": 8192,
"Memory": 16384,
},
[],
),
(
{
"RequiresCompatibilities": ["FARGATE"],
"Cpu": 16384,
"Memory": 122880,
},
[],
),
(
{
"RequiresCompatibilities": ["FARGATE"],
"Cpu": 16384,
"Memory": 123904,
},
[
ValidationError(
"Cpu 16384 is not compatible with memory 123904",
rule=FargateCpuMemory(),
path=deque([]),
validator="anyOf",
schema_path=deque(["then", "anyOf"]),
)
],
),
],
)
def test_validate(instance, expected, rule, validator):
errs = list(rule.validate(validator, "", instance, {}))
for err in errs:
print(err.schema_path)
print(err.validator)
print(err.rule)
print(err.path)
assert errs == expected, f"Expected {expected} got {errs}"

0 comments on commit b713f39

Please sign in to comment.