import type {CloudResource} from '@/types/resource' import {formatDateTime} from '@/lib/format' interface EcsServicePanelProps { resource?: CloudResource } interface Deployment { id?: string; status?: string; taskDefinition?: string; desiredCount?: number; runningCount?: number; pendingCount?: number; createdAt?: string; updatedAt?: string } interface Task { arn?: string; lastStatus?: string; desiredStatus?: string; healthStatus?: string; connectivity?: string; stoppedReason?: string } interface Target { id?: string; port?: number; state?: string; reason?: string } interface LoadBalancer { targetGroupArn?: string; targetType?: string | null; containerName?: string; containerPort?: number; targets?: Target[]; endpoints?: Array<{dnsName?: string; state?: string | null; scheme?: string | null}> } export function EcsServicePanel({resource}: EcsServicePanelProps) { if (!resource) return null if (resource.type === 'ecs-cluster') return if (resource.type === 'ecs-task-definition') return const deployments = array(resource.metadata.deployments) const tasks = array(resource.metadata.tasks) const loadBalancers = array(resource.metadata.loadBalancers) const inactive = resource.status === 'INACTIVE' || resource.metadata.inactive === true const launchType = String(resource.metadata.launchType ?? 'EC2') const network = object(resource.metadata.networkConfiguration) return

{launchType === 'FARGATE' ? 'Fargate service state' : 'EC2 service state'}

{resource.name}

Launch type: {launchType} | Deployment controller: {String(resource.metadata.deploymentController ?? 'ECS')} | Cluster: {String(resource.metadata.cluster ?? '-')} | {inactive ? 'Inactive, not running' : `Running ${String(resource.metadata.runningCount ?? 0)} of ${String(resource.metadata.desiredCount ?? 0)}`}

{network &&

awsvpc networking: subnets {values(network.subnets)} | security groups {values(network.securityGroups)} | public IP {String(network.assignPublicIp ?? 'DISABLED')}

} {launchType === 'FARGATE' && !network &&

Fargate services require awsvpc networking. Attach an IP target group, not an instance target group, when using an ALB.

} {inactive ?

This service is inactive. ECS may retain historical deployment counts while deletion settles; they are not shown as running tasks.

: <>

Tasks

{tasks.length ?
{tasks.map((task, index) => )}
TaskLast statusHealthConnectivity
{task.arn ?? '-'}{task.lastStatus ?? '-'}{task.healthStatus ?? '-'}{task.connectivity ?? '-'}
:

No running tasks reported for this service.

} {loadBalancers.map((loadBalancer, index) =>

ALB and target health

Target group: {loadBalancer.targetGroupArn ?? '-'} | Target type: {loadBalancer.targetType ?? '-'}{launchType === 'FARGATE' && loadBalancer.targetType !== 'ip' ? ' (Fargate requires IP targets)' : ''}

{loadBalancer.endpoints?.map((endpoint, endpointIndex) =>

ALB endpoint: {endpoint.dnsName ?? '-'} | {endpoint.scheme ?? '-'} | {endpoint.state ?? '-'}

)}
{(loadBalancer.targets ?? []).map((target, targetIndex) => )}
TargetHealthReason
{target.id ?? '-'}{target.port ? `:${target.port}` : ''}{target.state ?? '-'}{target.reason ?? '-'}
{!loadBalancer.targets?.length &&

No target health reported by this target group.

}
)}

Deployments

{deployments.map((deployment, index) => )}
DeploymentStatusTask definitionRunningUpdated
{deployment.id ?? '-'}{deployment.status ?? '-'}{deployment.taskDefinition ?? '-'}{deployment.runningCount ?? 0} / {deployment.desiredCount ?? 0}{deployment.pendingCount ? ` (${deployment.pendingCount} pending)` : ''}{formatDateTime(deployment.updatedAt ?? deployment.createdAt) ?? '-'}
{deployments.length === 0 &&

No deployment state reported for this service.

} }
} function EcsClusterDetails({resource}: {resource: CloudResource}) { return

ECS cluster

{resource.name}

Status: {resource.status ?? '-'} | Services: {String(resource.metadata.activeServicesCount ?? 0)} | Running tasks: {String(resource.metadata.runningTasksCount ?? 0)} | Pending tasks: {String(resource.metadata.pendingTasksCount ?? 0)}

Registered container instances: {String(resource.metadata.registeredContainerInstancesCount ?? 0)}

} function EcsTaskDefinitionDetails({resource}: {resource: CloudResource}) { return

Fargate task definition

{resource.name}

CPU: {String(resource.metadata.cpu ?? '-')} | Memory: {String(resource.metadata.memory ?? '-')} MiB | Network mode: {String(resource.metadata.networkMode ?? '-')}

ContainerImagePort
{String(resource.metadata.containerName ?? '-')}{String(resource.metadata.image ?? '-')}{String(resource.metadata.containerPort ?? '-')}
} function array(value: unknown): T[] { return Array.isArray(value) ? value as T[] : [] } function object(value: unknown): Record | null { return typeof value === 'object' && value !== null && !Array.isArray(value) ? value as Record : null } function values(value: unknown): string { return Array.isArray(value) && value.length ? value.map(String).join(', ') : '-' }