Source code for ecs_composex.ecs.task_compute

#  SPDX-License-Identifier: MPL-2.0
#  Copyright 2020-2022 John Mille <john@compose-x.io>

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from ecs_composex.ecs.ecs_family import ComposeFamily

from itertools import chain

from troposphere import If, NoValue

from ecs_composex.common.logging import LOG
from ecs_composex.compose.compose_services.docker_tools import (
    find_closest_fargate_configuration,
)
from ecs_composex.ecs.ecs_conditions import USE_FARGATE_CON_T
from ecs_composex.ecs.ecs_params import (
    FARGATE_CPU,
    FARGATE_CPU_RAM_CONFIG_T,
    FARGATE_RAM,
)

from .helpers import unlock_compute_for_main_container


[docs]class TaskCompute: """ Class to handle task and services compute settings (CPU/RAM) """ def __init__(self, family: ComposeFamily): self.family = family self._raw_cpu = 0 self._raw_ram = 0 self._fargate_cpu = 0 self._fargate_ram = 0 self.fargate_cpu = 256 self.fargate_ram = 512 self._sidecar_used_cpu = 0 self._sidecar_used_ram = 0 @property def fargate_cpu(self): return self._fargate_cpu @fargate_cpu.setter def fargate_cpu(self, value): if value > 0: self._fargate_cpu = value elif value <= 0: raise ValueError("Fargate CPU must be a positive value") @property def fargate_ram(self): return self._fargate_ram @fargate_ram.setter def fargate_ram(self, value: int): if value > 0: self._fargate_ram = value elif value <= 0: raise ValueError("Fargate RAM must be a positive value") @property def family_cpu(self): return self._raw_cpu @property def cfn_family_cpu(self): if self._raw_cpu < 128: LOG.debug( f"{self.family.name} - Minimum CPU for task in ECS is 128. Got {self._raw_cpu}. Correcting" ) return "128" return str(self._raw_cpu) @family_cpu.setter def family_cpu(self, value: int): self._raw_cpu = value if self.family.task_definition: setattr( self.family.task_definition, "Cpu", If(USE_FARGATE_CON_T, FARGATE_CPU, self.cfn_family_cpu), ) @property def family_ram(self): return self._raw_ram @property def cfn_family_ram(self): if self._raw_ram < 128: LOG.debug( f"{self.family.name} - Minimum RAM for task in ECS is 128MB. Got {self._raw_ram}. Correcting" ) return "128" return str(self._raw_ram) @family_ram.setter def family_ram(self, value: int): self._raw_ram = value if self.family.task_definition: setattr( self.family.task_definition, "Memory", If(USE_FARGATE_CON_T, FARGATE_RAM, self.cfn_family_ram), )
[docs] def update_family_fargate(self, cpu, ram): self.fargate_cpu, self.fargate_ram = find_closest_fargate_configuration( cpu, ram ) if self.family.stack: cpu_ram = f"{self.fargate_cpu}!{self.fargate_ram}" self.family.stack.Parameters.update({FARGATE_CPU_RAM_CONFIG_T: cpu_ram})
[docs] def set_task_compute_parameter(self): """ Method to update task parameter for CPU/RAM profile """ math_cpu = 0 math_ram = 0 for service in chain( self.family.managed_sidecars, self.family.ordered_services ): if isinstance(service.container_definition.Cpu, int): math_cpu += service.container_definition.Cpu if ( isinstance(service.container_definition.Memory, int) and service.container_definition.MemoryReservation == NoValue ): math_ram += service.container_definition.Memory elif service.container_definition.Memory == NoValue and isinstance( service.container_definition.MemoryReservation, int ): math_ram += service.container_definition.MemoryReservation elif isinstance(service.container_definition.Memory, int) and isinstance( service.container_definition.MemoryReservation, int ): if ( service.container_definition.MemoryReservation > service.container_definition.Memory ): raise ValueError( f"{service.name} has more Memory reservations than limits" ) math_ram += service.container_definition.Memory self.family_cpu = math_cpu self.family_ram = math_ram self.update_family_fargate(math_cpu, math_ram)
[docs] def unlock_compute_for_main_container(self): unlock_compute_for_main_container(self.family)