feat: Fargate
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import {describe, expect, test} from 'bun:test'
|
||||
import {CreateServiceCommand, DeleteServiceCommand, DescribeServicesCommand, DescribeTasksCommand, ListClustersCommand, ListServicesCommand, ListTasksCommand, type ECSClient} from '@aws-sdk/client-ecs'
|
||||
import {DescribeLoadBalancersCommand, DescribeTargetGroupsCommand, DescribeTargetHealthCommand, type ElasticLoadBalancingV2Client} from '@aws-sdk/client-elastic-load-balancing-v2'
|
||||
import {AwsEcsAdapter} from './AwsEcsAdapter'
|
||||
import {AwsFargateAdapter} from './AwsFargateAdapter'
|
||||
|
||||
const cluster = 'orders-cluster'
|
||||
|
||||
describe('AwsEcsAdapter', () => {
|
||||
test('lists EC2 and Fargate services with task, IP target, and ALB health', async () => {
|
||||
const ecs = {async send(command: object) {
|
||||
if (command instanceof ListClustersCommand) return {clusterArns: [cluster]}
|
||||
if (command instanceof ListServicesCommand) return {serviceArns: ['orders', 'fargate']}
|
||||
if (command instanceof DescribeServicesCommand) return {services: [
|
||||
{serviceName: 'orders', serviceArn: 'arn:aws:ecs:us-east-1:000000000000:service/orders', launchType: 'EC2', status: 'ACTIVE', desiredCount: 2, runningCount: 1, pendingCount: 1, taskDefinition: 'orders:4'},
|
||||
{serviceName: 'fargate', serviceArn: 'arn:aws:ecs:us-east-1:000000000000:service/fargate', launchType: 'FARGATE', status: 'ACTIVE', desiredCount: 1, runningCount: 1, taskDefinition: 'fargate:1', networkConfiguration: {awsvpcConfiguration: {subnets: ['subnet-1'], securityGroups: ['sg-1'], assignPublicIp: 'ENABLED'}}, loadBalancers: [{targetGroupArn: 'tg-1', containerName: 'app', containerPort: 8080}]},
|
||||
]}
|
||||
if (command instanceof ListTasksCommand) return {taskArns: ['task-1']}
|
||||
if (command instanceof DescribeTasksCommand) return {tasks: [{taskArn: 'task-1', lastStatus: 'RUNNING', healthStatus: 'HEALTHY', connectivity: 'CONNECTED'}]}
|
||||
return {}
|
||||
}} as unknown as ECSClient
|
||||
const elb = {async send(command: object) {
|
||||
if (command instanceof DescribeTargetGroupsCommand) return {TargetGroups: [{TargetType: 'ip', LoadBalancerArns: ['alb-1']}]}
|
||||
if (command instanceof DescribeTargetHealthCommand) return {TargetHealthDescriptions: [{Target: {Id: '10.0.1.5', Port: 8080}, TargetHealth: {State: 'healthy'}}]}
|
||||
if (command instanceof DescribeLoadBalancersCommand) return {LoadBalancers: [{DNSName: 'orders.example.test', Scheme: 'internet-facing', State: {Code: 'active'}}]}
|
||||
return {}
|
||||
}} as unknown as ElasticLoadBalancingV2Client
|
||||
|
||||
const services = await new AwsEcsAdapter(ecs, elb).list()
|
||||
|
||||
expect(services).toHaveLength(2)
|
||||
expect(services[0]).toMatchObject({metadata: {launchType: 'EC2', tasks: [{healthStatus: 'HEALTHY'}]}})
|
||||
expect(services[1]).toMatchObject({metadata: {launchType: 'FARGATE', networkConfiguration: {subnets: ['subnet-1']}, loadBalancers: [{targetType: 'ip', targets: [{state: 'healthy'}], endpoints: [{dnsName: 'orders.example.test', state: 'active'}]}]}})
|
||||
})
|
||||
|
||||
test('creates an awsvpc Fargate service and force deletes it', async () => {
|
||||
const sent: object[] = []
|
||||
const ecs = {async send(command: object) {
|
||||
sent.push(command)
|
||||
if (command instanceof CreateServiceCommand) return {service: {serviceName: 'orders', serviceArn: 'arn:aws:ecs:us-east-1:000000000000:service/orders', launchType: 'FARGATE', status: 'ACTIVE', desiredCount: 1, runningCount: 0, taskDefinition: 'orders:1'}}
|
||||
if (command instanceof ListTasksCommand) return {taskArns: []}
|
||||
return {}
|
||||
}} as unknown as ECSClient
|
||||
const elb = {async send() { return {} }} as unknown as ElasticLoadBalancingV2Client
|
||||
const adapter = new AwsEcsAdapter(ecs, elb)
|
||||
|
||||
await adapter.create({values: {cluster, serviceName: 'orders', taskDefinition: 'orders:1', launchType: 'FARGATE', subnets: 'subnet-1, subnet-2', securityGroups: 'sg-1', assignPublicIp: 'ENABLED'}})
|
||||
await adapter.delete(`${cluster}|orders`)
|
||||
|
||||
expect((sent[0] as CreateServiceCommand).input).toMatchObject({cluster, serviceName: 'orders', launchType: 'FARGATE', networkConfiguration: {awsvpcConfiguration: {subnets: ['subnet-1', 'subnet-2'], securityGroups: ['sg-1'], assignPublicIp: 'ENABLED'}}})
|
||||
expect((sent.at(-1) as DeleteServiceCommand).input).toEqual({cluster, service: 'orders', force: true})
|
||||
})
|
||||
|
||||
test('does not present stale inactive counts as running', async () => {
|
||||
const ecs = {async send(command: object) {
|
||||
if (command instanceof DescribeServicesCommand) return {services: [{serviceName: 'orders', status: 'INACTIVE', desiredCount: 2, runningCount: 2, pendingCount: 1, deployments: [{desiredCount: 2, runningCount: 2}]}]}
|
||||
return {}
|
||||
}} as unknown as ECSClient
|
||||
const elb = {async send() { return {} }} as unknown as ElasticLoadBalancingV2Client
|
||||
|
||||
const service = await new AwsEcsAdapter(ecs, elb).get(`${cluster}|orders`)
|
||||
|
||||
expect(service).toMatchObject({metadata: {inactive: true, desiredCount: 0, runningCount: 0, pendingCount: 0, deployments: [{desiredCount: 0, runningCount: 0}]}})
|
||||
})
|
||||
|
||||
test('Fargate adapter lists and creates only Fargate services', async () => {
|
||||
const sent: object[] = []
|
||||
const ecs = {async send(command: object) {
|
||||
sent.push(command)
|
||||
if (command instanceof ListClustersCommand) return {clusterArns: [cluster]}
|
||||
if (command instanceof ListServicesCommand) return {serviceArns: ['ec2', 'fargate']}
|
||||
if (command instanceof DescribeServicesCommand) return {services: [
|
||||
{serviceName: 'ec2', launchType: 'EC2', status: 'ACTIVE'},
|
||||
{serviceName: 'fargate', launchType: 'FARGATE', status: 'ACTIVE'},
|
||||
]}
|
||||
if (command instanceof CreateServiceCommand) return {service: {serviceName: 'created', launchType: 'FARGATE', status: 'ACTIVE'}}
|
||||
if (command instanceof ListTasksCommand) return {taskArns: []}
|
||||
return {}
|
||||
}} as unknown as ECSClient
|
||||
const elb = {async send() { return {} }} as unknown as ElasticLoadBalancingV2Client
|
||||
const adapter = new AwsFargateAdapter(new AwsEcsAdapter(ecs, elb))
|
||||
|
||||
const services = await adapter.list()
|
||||
const created = await adapter.create({values: {cluster, serviceName: 'created', taskDefinition: 'created:1', launchType: 'EC2', subnets: 'subnet-1'}})
|
||||
|
||||
expect(services).toHaveLength(1)
|
||||
expect(services[0]).toMatchObject({service: 'fargate', name: 'fargate', metadata: {launchType: 'FARGATE'}})
|
||||
expect(created).toMatchObject({service: 'fargate', metadata: {launchType: 'FARGATE'}})
|
||||
expect(sent.find((command) => command instanceof CreateServiceCommand)).toMatchObject({input: {launchType: 'FARGATE'}})
|
||||
expect(adapter.schema().fields.find((field) => field.name === 'launchType')).toBeUndefined()
|
||||
expect(adapter.schema().fields.find((field) => field.name === 'subnets')).toMatchObject({required: true})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user