Spaces:
Runtime error
Runtime error
from typing import Optional, Any, Dict, List, Union | |
from phi.aws.api_client import AwsApiClient | |
from phi.aws.resource.base import AwsResource | |
from phi.aws.resource.secret.manager import SecretsManager | |
from phi.aws.resource.secret.reader import read_secrets | |
from phi.utils.log import logger | |
class EcsContainer(AwsResource): | |
""" | |
Reference: | |
- https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecs.html | |
""" | |
resource_type: Optional[str] = "EcsContainer" | |
service_name: str = "ecs" | |
# The name of a container. | |
# If you're linking multiple containers together in a task definition, the name of one container can be entered in | |
# the links of another container to connect the containers. | |
name: str | |
# The image used to start a container. | |
image: str | |
# The private repository authentication credentials to use. | |
repository_credentials: Optional[Dict[str, Any]] = None | |
# The number of cpu units reserved for the container. | |
cpu: Optional[int] = None | |
# The amount (in MiB) of memory to present to the container. | |
memory: Optional[int] = None | |
# The soft limit (in MiB) of memory to reserve for the container. | |
memory_reservation: Optional[int] = None | |
# The links parameter allows containers to communicate with each other without the need for port mappings. | |
links: Optional[List[str]] = None | |
# The list of port mappings for the container. Port mappings allow containers to access ports on the host container | |
# instance to send or receive traffic. | |
port_mappings: Optional[List[Dict[str, Any]]] = None | |
# If the essential parameter of a container is marked as true , and that container fails or stops for any reason, | |
# all other containers that are part of the task are stopped. If the essential parameter of a container is marked | |
# as false , its failure doesn't affect the rest of the containers in a task. If this parameter is omitted, | |
# a container is assumed to be essential. | |
essential: Optional[bool] = None | |
# The entry point that's passed to the container. | |
entry_point: Optional[List[str]] = None | |
# The command that's passed to the container. | |
command: Optional[List[str]] = None | |
# The environment variables to pass to a container. | |
environment: Optional[List[Dict[str, Any]]] = None | |
# A list of files containing the environment variables to pass to a container. | |
environment_files: Optional[List[Dict[str, Any]]] = None | |
# Read environment variables from AWS Secrets. | |
env_from_secrets: Optional[Union[SecretsManager, List[SecretsManager]]] = None | |
# The mount points for data volumes in your container. | |
mount_points: Optional[List[Dict[str, Any]]] = None | |
# Data volumes to mount from another container. | |
volumes_from: Optional[List[Dict[str, Any]]] = None | |
# Linux-specific modifications that are applied to the container, such as Linux kernel capabilities. | |
linux_parameters: Optional[Dict[str, Any]] = None | |
# The secrets to pass to the container. | |
secrets: Optional[List[Dict[str, Any]]] = None | |
# The dependencies defined for container startup and shutdown. | |
depends_on: Optional[List[Dict[str, Any]]] = None | |
# Time duration (in seconds) to wait before giving up on resolving dependencies for a container. | |
start_timeout: Optional[int] = None | |
# Time duration (in seconds) to wait before the container is forcefully killed if it doesn't exit normally. | |
stop_timeout: Optional[int] = None | |
# The hostname to use for your container. | |
hostname: Optional[str] = None | |
# The user to use inside the container. | |
user: Optional[str] = None | |
# The working directory to run commands inside the container in. | |
working_directory: Optional[str] = None | |
# When this parameter is true, networking is disabled within the container. | |
disable_networking: Optional[bool] = None | |
# When this parameter is true, the container is given elevated privileges | |
# on the host container instance (similar to the root user). | |
privileged: Optional[bool] = None | |
readonly_root_filesystem: Optional[bool] = None | |
dns_servers: Optional[List[str]] = None | |
dns_search_domains: Optional[List[str]] = None | |
extra_hosts: Optional[List[Dict[str, Any]]] = None | |
docker_security_options: Optional[List[str]] = None | |
interactive: Optional[bool] = None | |
pseudo_terminal: Optional[bool] = None | |
docker_labels: Optional[Dict[str, Any]] = None | |
ulimits: Optional[List[Dict[str, Any]]] = None | |
log_configuration: Optional[Dict[str, Any]] = None | |
health_check: Optional[Dict[str, Any]] = None | |
system_controls: Optional[List[Dict[str, Any]]] = None | |
resource_requirements: Optional[List[Dict[str, Any]]] = None | |
firelens_configuration: Optional[Dict[str, Any]] = None | |
def get_container_definition(self, aws_client: Optional[AwsApiClient] = None) -> Dict[str, Any]: | |
container_definition: Dict[str, Any] = {} | |
# Build container environment | |
container_environment: List[Dict[str, Any]] = self.build_container_environment(aws_client=aws_client) | |
if container_environment is not None: | |
container_definition["environment"] = container_environment | |
if self.name is not None: | |
container_definition["name"] = self.name | |
if self.image is not None: | |
container_definition["image"] = self.image | |
if self.repository_credentials is not None: | |
container_definition["repositoryCredentials"] = self.repository_credentials | |
if self.cpu is not None: | |
container_definition["cpu"] = self.cpu | |
if self.memory is not None: | |
container_definition["memory"] = self.memory | |
if self.memory_reservation is not None: | |
container_definition["memoryReservation"] = self.memory_reservation | |
if self.links is not None: | |
container_definition["links"] = self.links | |
if self.port_mappings is not None: | |
container_definition["portMappings"] = self.port_mappings | |
if self.essential is not None: | |
container_definition["essential"] = self.essential | |
if self.entry_point is not None: | |
container_definition["entryPoint"] = self.entry_point | |
if self.command is not None: | |
container_definition["command"] = self.command | |
if self.environment_files is not None: | |
container_definition["environmentFiles"] = self.environment_files | |
if self.mount_points is not None: | |
container_definition["mountPoints"] = self.mount_points | |
if self.volumes_from is not None: | |
container_definition["volumesFrom"] = self.volumes_from | |
if self.linux_parameters is not None: | |
container_definition["linuxParameters"] = self.linux_parameters | |
if self.secrets is not None: | |
container_definition["secrets"] = self.secrets | |
if self.depends_on is not None: | |
container_definition["dependsOn"] = self.depends_on | |
if self.start_timeout is not None: | |
container_definition["startTimeout"] = self.start_timeout | |
if self.stop_timeout is not None: | |
container_definition["stopTimeout"] = self.stop_timeout | |
if self.hostname is not None: | |
container_definition["hostname"] = self.hostname | |
if self.user is not None: | |
container_definition["user"] = self.user | |
if self.working_directory is not None: | |
container_definition["workingDirectory"] = self.working_directory | |
if self.disable_networking is not None: | |
container_definition["disableNetworking"] = self.disable_networking | |
if self.privileged is not None: | |
container_definition["privileged"] = self.privileged | |
if self.readonly_root_filesystem is not None: | |
container_definition["readonlyRootFilesystem"] = self.readonly_root_filesystem | |
if self.dns_servers is not None: | |
container_definition["dnsServers"] = self.dns_servers | |
if self.dns_search_domains is not None: | |
container_definition["dnsSearchDomains"] = self.dns_search_domains | |
if self.extra_hosts is not None: | |
container_definition["extraHosts"] = self.extra_hosts | |
if self.docker_security_options is not None: | |
container_definition["dockerSecurityOptions"] = self.docker_security_options | |
if self.interactive is not None: | |
container_definition["interactive"] = self.interactive | |
if self.pseudo_terminal is not None: | |
container_definition["pseudoTerminal"] = self.pseudo_terminal | |
if self.docker_labels is not None: | |
container_definition["dockerLabels"] = self.docker_labels | |
if self.ulimits is not None: | |
container_definition["ulimits"] = self.ulimits | |
if self.log_configuration is not None: | |
container_definition["logConfiguration"] = self.log_configuration | |
if self.health_check is not None: | |
container_definition["healthCheck"] = self.health_check | |
if self.system_controls is not None: | |
container_definition["systemControls"] = self.system_controls | |
if self.resource_requirements is not None: | |
container_definition["resourceRequirements"] = self.resource_requirements | |
if self.firelens_configuration is not None: | |
container_definition["firelensConfiguration"] = self.firelens_configuration | |
return container_definition | |
def build_container_environment(self, aws_client: Optional[AwsApiClient] = None) -> List[Dict[str, Any]]: | |
logger.debug("Building container environment") | |
container_environment: List[Dict[str, Any]] = [] | |
if self.environment is not None: | |
from phi.aws.resource.reference import AwsReference | |
for env in self.environment: | |
env_name = env.get("name", None) | |
env_value = env.get("value", None) | |
env_value_parsed = None | |
if isinstance(env_value, AwsReference): | |
logger.debug(f"{env_name} is an AwsReference") | |
try: | |
env_value_parsed = env_value.get_reference(aws_client=aws_client) | |
except Exception as e: | |
logger.error(f"Error while parsing {env_name}: {e}") | |
else: | |
env_value_parsed = env_value | |
if env_value_parsed is not None: | |
try: | |
env_val_str = str(env_value_parsed) | |
container_environment.append({"name": env_name, "value": env_val_str}) | |
except Exception as e: | |
logger.error(f"Error while converting {env_value} to str: {e}") | |
if self.env_from_secrets is not None: | |
secrets: Dict[str, Any] = read_secrets(self.env_from_secrets, aws_client=aws_client) | |
for secret_name, secret_value in secrets.items(): | |
try: | |
secret_value = str(secret_value) | |
container_environment.append({"name": secret_name, "value": secret_value}) | |
except Exception as e: | |
logger.error(f"Error while converting {secret_value} to str: {e}") | |
return container_environment | |