diff --git a/src/index.ts b/src/index.ts index cdab86c..1c7309d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,52 @@ -export class SampleClass { - add(a: number, b: number): number { - return a+b; +export interface VM { + cpu: number, + memory: number, + network: number, +} + +export interface ServerCapacity { + limitCpu: number, + limitMemory: number, + limitNetwork: number, +} + +export type Server = Set; + + +export class ServerConsolidation { + doesVmFitOnServer(vm: VM, capacity: ServerCapacity): boolean { + return vm.cpu <= capacity.limitCpu && + vm.memory <= capacity.limitMemory && + vm.network <= capacity.limitNetwork; + } + + reduceCapacity(vm: VM, capacity: ServerCapacity): void { + capacity.limitCpu -= vm.cpu; + capacity.limitMemory -= vm.memory; + capacity.limitNetwork -= vm.network; + } + + fit(vms: VM[], capacity: ServerCapacity): Server[] { + const servers: Server[] = []; + const capacitiesLeft: ServerCapacity[] = []; + for (const vm of vms) { + let found = false; + for (const [idx, server] of servers.entries()) { + const capacity = capacitiesLeft[idx]; + if (this.doesVmFitOnServer(vm, capacity)) { + found = true; + server.add(vm); + this.reduceCapacity(vm, capacity); + break; + } + } + if (!found) { + servers.push(new Set([vm])); + const newCapacity = {...capacity}; + this.reduceCapacity(vm, newCapacity); + capacitiesLeft.push(newCapacity); + } + } + return servers; } } diff --git a/test/index.ts b/test/index.ts index 80d2c5f..f6556e6 100644 --- a/test/index.ts +++ b/test/index.ts @@ -1,16 +1,140 @@ import {expect} from 'chai'; -import {SampleClass} from '../src'; +import {ServerCapacity, ServerConsolidation, VM, Server} from '../src'; -describe('index', () => { - it('main', () => { - const cls = new SampleClass(); - const cases: [number, number, unknown][] = [ - [2, 3, 5], - [2, 0, 2], - [500, -10, 490], +interface TestCase { + vms: VM[], + capacity: ServerCapacity, + results: Server[], +} + +describe('ServerConsolidation - fit', () => { + const cls = new ServerConsolidation(); + const vms: {[name: string]: VM} = { + 'a': { + cpu: 1, + memory: 1, + network: 1, + }, + 'b': { + cpu: 2, + memory: 2, + network: 2, + }, + 'b-copy': { + cpu: 2, + memory: 2, + network: 2, + }, + 'large': { + cpu: 10, + memory: 10, + network: 10, + }, + 'd': { + cpu: 3, + memory: 3, + network: 3, + }, + }; + + it('should match server allocation', () => { + const cases: TestCase[] = [ + // every vm fits on a single server + { + vms: [vms.a, vms.b], + capacity: { + limitCpu: 10, + limitMemory: 10, + limitNetwork: 10, + }, + results: [ + new Set([vms.a, vms.b]), + ], + }, + // multiple servers needed + { + vms: [vms.a, vms.b, vms.large], + capacity: { + limitCpu: 10, + limitMemory: 10, + limitNetwork: 10, + }, + results: [ + new Set([vms.a, vms.b]), + new Set([vms.large]), + ], + }, + // reuse of existing servers + { + vms: [ + vms.a, vms.b, vms.large, vms.d], + capacity: { + limitCpu: 10, + limitMemory: 10, + limitNetwork: 10, + }, + results: [ + new Set([vms.a, vms.b, vms.d]), + new Set([vms.large]), + ], + }, ]; - for (const [a, b, res] of cases) { - expect(cls.add(a, b)).to.be.deep.equal(res); + for (const {vms, capacity, results} of cases) { + const servers = cls.fit(vms, capacity); + for (const [idx, server] of servers.entries()) { + const result = results[idx]; + expect(server).to.eqls(result); + } + } + }); + + it('should match reference', () => { + const cases: TestCase[] = [ + // same reference of objects + { + vms: [ + vms.a, + ], + capacity: { + limitCpu: 10, + limitMemory: 10, + limitNetwork: 10, + }, + results: [ + new Set([ + vms.a, + ]), + ], + }, + ]; + for (const {vms, capacity, results} of cases) { + const servers = cls.fit(vms, capacity); + for (const server of servers[0]) { + results[0].has(server); + } } }); }); + +describe('ServerConsolidation - reduceCapacity', () => { + const cls = new ServerConsolidation(); + it('should equal', () => { + const capacity: ServerCapacity = { + limitCpu: 10, + limitMemory: 3, + limitNetwork: 9, + }; + const vm: VM = { + cpu: 3, + memory: 1, + network: 0, + }; + const result: ServerCapacity = { + limitCpu: 7, + limitMemory: 2, + limitNetwork: 9, + }; + cls.reduceCapacity(vm, capacity); + expect(capacity).to.deep.equal(result); + }); +});