UNPKG

smc-hub

Version:

CoCalc: Backend webserver component

1,251 lines (1,162 loc) 31.4 kB
/* * This file is part of CoCalc: Copyright © 2020 Sagemath, Inc. * License: AGPLv3 s.t. "Commons Clause" see LICENSE.md for details */ // this tests kucalc's quota function // // after any change to quota.ts, be a good citizen and run this test or even extend it // ~/src/smc-hub/test$ SMC_DB_RESET=true SMC_TEST=true npx jest kucalc/quota.test.ts // import * as init from "./init"; //let db = undefined; //const setup = (cb) => // init.setup(function (err) { // db = init.db(); // cb(err); // }); //const { teardown } = init; import expect from "expect"; const { quota } = require("smc-util/upgrades/quota"); describe("default quota", () => { it("basics are fine", () => { // quota should work without any arguments const basic = quota(); const exp = { cpu_limit: 1, cpu_request: 0.02, disk_quota: 3000, idle_timeout: 1800, member_host: false, memory_limit: 1000, memory_request: 200, network: false, privileged: false, always_running: false, }; expect(basic).toEqual(exp); }); it("gives members a bit more memory by default", () => { const member = quota({}, { userX: { upgrades: { member_host: 1 } } }); const exp = { cpu_limit: 1, cpu_request: 0.05, // set at the top of quota config disk_quota: 3000, idle_timeout: 1800, member_host: true, // what this upgrade is about memory_limit: 1500, // set at the top of quota config memory_request: 300, // set at the top of quota config network: false, privileged: false, always_running: false, }; expect(member).toEqual(exp); }); it("respects admin member/network upgrades", () => { const admin1 = quota({ member_host: 1, network: 1 }, {}); const exp = { cpu_limit: 1, cpu_request: 0.05, // set at the top of quota config disk_quota: 3000, idle_timeout: 1800, member_host: true, // what this upgrade is about memory_limit: 1500, // set at the top of quota config memory_request: 300, // set at the top of quota config network: true, // what this upgrade is about privileged: false, always_running: false, }; expect(admin1).toEqual(exp); }); it("adds up user contributions", () => { const users = { user1: { upgrades: { network: 1, memory: 1500, memory_request: 2500, cpu_shares: 1024 * 0.33, }, }, user2: { upgrades: { member_host: 1, network: 1, memory: 123, cores: 0.5, disk_quota: 1000, }, }, user3: { upgrades: { mintime: 99, memory: 7, }, }, }; const added = quota({}, users); const exp = { network: true, member_host: true, memory_request: 2500, memory_limit: 2630, // 1000 mb free cpu_request: 0.33, cpu_limit: 1.5, // 1 for free privileged: false, idle_timeout: 1899, // 1800 secs free disk_quota: 4000, always_running: false, }; expect(added).toEqual(exp); }); it("do NOT set limits >= requests -- manage pod in kucalc does that", () => { const users = { user1: { upgrades: { member_host: true, network: true, memory_request: 3210, }, }, }; const exp = { network: true, member_host: true, memory_request: 3210, memory_limit: 1500, // 1500 mb free for members cpu_request: 0.05, cpu_limit: 1, privileged: false, idle_timeout: 1800, // 1800 secs free disk_quota: 3000, always_running: false, }; expect(quota({}, users)).toEqual(exp); }); it("caps user upgrades at their maximum", () => { const over_max = { user2: { upgrades: { network: 2, member_host: 3, disk_quota: 32000, // max 20gb memory: 20000, // max 16gb mintime: 24 * 3600 * 100, // max 90 days memory_request: 10000, // max 8gb cores: 7, // max 3 cpu_shares: 1024 * 4, }, }, // max 2 requests }; const maxedout = quota({}, over_max); const exp = { cpu_limit: 3, cpu_request: 2, // set at the top of quota config disk_quota: 20000, idle_timeout: 24 * 3600 * 90, member_host: true, memory_limit: 16000, // set at the top of quota config memory_request: 8000, // set at the top of quota config network: true, privileged: false, always_running: false, }; expect(maxedout).toEqual(exp); }); it("does not limit admin upgrades", () => { const settings = { network: 2, member_host: 3, disk_quota: 32000, // max 20gb memory: 20000, // max 16gb mintime: 24 * 3600 * 100, // max 90 days memory_request: 10000, // max 8gb cores: 7, // max 4 shared cpu_shares: 1024 * 4, // max 3 requests }; const maxedout = quota(settings, {}); const exp = { cpu_limit: 7, // > limit cpu_request: 4, // > limit disk_quota: 32000, // > limit idle_timeout: 24 * 3600 * 100, // > limit member_host: true, memory_limit: 20000, // > limit memory_request: 10000, // > limit network: true, privileged: false, always_running: false, }; expect(maxedout).toEqual(exp); }); it("combines admin and user upgrades properly", () => { const settings = { network: 1, member_host: 0, disk_quota: 19000, // max 20gb memory: 1000, // max 16gb mintime: 24 * 3600 * 33, // max 90 days memory_request: 1000, // max 8gb cores: 1, // max 2 shared cpu_shares: 0.1 * 1024, }; const users = { user1: { upgrades: { member_host: true, network: true, memory_request: 3210, disk_quota: 3000, // settings are already near max cores: 2, mintime: 24 * 3600 * 50, cpu_shares: 1024 * 0.5, }, }, user2: { upgrades: { member_host: true, network: true, cores: 2, mintime: 24 * 3600 * 50, }, }, }; const exp = { network: true, member_host: true, memory_request: 4210, memory_limit: 1500, // 1500 mb free for members cpu_request: 0.5 + 0.1, cpu_limit: 3, privileged: false, idle_timeout: 24 * 3600 * (Math.min(90, 50 + 50) + 33) - 1800, // 1800 secs free disk_quota: 22000, always_running: false, }; expect(quota(settings, users)).toEqual(exp); }); it("admin upgrades can move user upgrades beyond the limit", () => { const settings = { memory: 5000 }; const users = { user1: { upgrades: { member_host: true, network: true, memory: 15000, memory_request: 2000, }, }, }; const exp = { network: true, member_host: true, memory_limit: 20000, cpu_limit: 1, cpu_request: 0.05, disk_quota: 3000, idle_timeout: 1800, memory_request: 2000, privileged: false, always_running: false, }; expect(quota(settings, users)).toEqual(exp); }); it("sanitizes admin upgrades", () => { const settings = { memory: "5000", // some are strings disk_quota: "3210", // we do know this could be a strings mintime: "3600", network: "1", cores: "1.5", member_host: "1", always_running: "0", memory_request: "512", }; expect(quota(settings)).toEqual({ always_running: false, cpu_limit: 1.5, cpu_request: 0.05, // due to member hosting minimum disk_quota: 3210, idle_timeout: 3600, member_host: true, memory_limit: 5000, memory_request: 512, network: true, privileged: false, }); }); it("does not allow privileged updates for users", () => { const users = { user1: { upgrades: { privileged: 1 } } }; const q = quota({}, users); expect(q.privileged).toBe(false); }); it("allows privileged updates for admins", () => { const settings = { privileged: 1 }; const q = quota(settings, {}); expect(q.privileged).toBe(true); }); it("caps ensures a minimum lower limit for ceratin quotas", () => { const settings = { cpu_request: 0, memory_request: 0, memory_limit: 0, }; const users = { user1: { upgrades: { cpu_request: 0, memory_request: 0, memory_limit: 0, }, }, }; const q = quota(settings, users); expect(q.cpu_request).toBeGreaterThan(0.01); expect(q.memory_request).toBeGreaterThan(100); expect(q.memory_limit).toBeGreaterThan(100); }); it("caps depending on free vs. member", () => { const free = { user1: { upgrades: { member_host: 0 } } }; const member = { user2: { upgrades: { member_host: 1 } } }; const qfree = quota({}, free); const qmember = quota({}, member); // checking two of them explicitly expect(qfree.cpu_request).toBe(0.02); expect(qmember.cpu_request).toBe(0.05); // members get strictly more than free users expect(qfree.cpu_request).toBeLessThan(qmember.cpu_request); expect(qfree.memory_request).toBeLessThan(qmember.memory_request); expect(qfree.memory_limit).toBeLessThan(qmember.memory_limit); }); it("partial site_settings1/mem", () => { const site_settings = { default_quotas: { internet: true, idle_timeout: 3600, mem_oc: 5 }, }; const member = { user2: { upgrades: { member_host: 1, memory: 4100 } } }; const q = quota({}, member, undefined, site_settings); expect(q).toEqual({ idle_timeout: 3600, memory_limit: 5100, memory_request: 1020, // (4100 + 1000) / 5 cpu_limit: 1, cpu_request: 0.05, disk_quota: 3000, member_host: true, network: true, privileged: false, always_running: false, }); }); it("partial site_settings2/cpu", () => { const site_settings = { default_quotas: { idle_timeout: 9999, cpu_oc: 10, mem_oc: 2, disk_quota: 5432, }, }; const member = { user2: { upgrades: { network: 1, cores: 1.4 } } }; const q = quota({}, member, undefined, site_settings); expect(q).toEqual({ idle_timeout: 9999, memory_limit: 1000, memory_request: 500, cpu_limit: 2.4, cpu_request: 0.24, disk_quota: 5432, member_host: false, network: true, privileged: false, always_running: false, }); }); it("respect different (lower) max_upgrades", () => { const site_settings = { max_upgrades: { member_host: 0, disk_quota: 616, // only disk quota is below the hardcoded default memory: 1515, mintime: 4345, memory_request: 505, cores: 3.14, cpu_shares: 2.2 * 1024, }, }; const over_max = { user2: { upgrades: { network: 2, member_host: 3, disk_quota: 32000, // max 20gb memory: 20000, // max 16gb mintime: 24 * 3600 * 100, // max 90 days memory_request: 10000, // max 8gb cores: 7, // max 3 cpu_shares: 1024 * 4, }, }, // max 2 requests }; const maxedout = quota({}, over_max, undefined, site_settings); expect(maxedout).toEqual({ cpu_limit: 3.14, cpu_request: 2.2, disk_quota: 616, idle_timeout: 4345, member_host: false, memory_limit: 1515, memory_request: 505, network: true, privileged: false, always_running: false, }); }); it("respect different (lower) max_upgrades /2", () => { // here, we go well below the default everywhere const site_settings = { max_upgrades: { member_host: 0, network: 0, always_running: 0, disk_quota: 616, memory: 512, mintime: 300, memory_request: 64, cores: 0.5, cpu_shares: 256, }, }; const over_max = { user2: { upgrades: { network: 2, member_host: 3, always_running: 4, disk_quota: 32000, // max 20gb memory: 20000, // max 16gb mintime: 24 * 3600 * 100, // max 90 days memory_request: 10000, // max 8gb cores: 7, // max 3 cpu_shares: 1024 * 4, }, }, }; const maxedout = quota({}, over_max, undefined, site_settings); expect(maxedout).toEqual({ network: false, member_host: false, privileged: false, memory_request: 64, cpu_request: 0.25, disk_quota: 616, memory_limit: 512, cpu_limit: 0.5, idle_timeout: 300, always_running: false, }); }); it("site-license upgrades /1", () => { const site_license = { "1234-5678-asdf-yxcv": { member_host: true, network: true, memory: 3210, memory_request: 531, disk_quota: 345, cores: 1.5, mintime: 24 * 3600, cpu_shares: 1024 * 0.5, }, }; const q1 = quota({}, { userX: {} }, site_license); expect(q1).toEqual({ idle_timeout: 24 * 3600 + 1800, memory_limit: 4210, memory_request: 531, cpu_limit: 2.5, cpu_request: 0.5, disk_quota: 3345, // 3gb free member_host: true, network: true, privileged: false, always_running: false, }); }); it("site-license upgrades /2", () => { const site_license = { "1234-5678-asdf-yxcv": { // will be ignored member_host: true, network: true, disk_quota: 222, }, "1234-5678-asdf-asdf": { disk_quota: 111, always_running: true, }, "333-5678-asdf-asdf": { disk_quota: 333, always_running: true, }, }; const users = { user1: { upgrades: { network: 1, memory: 1234, disk_quota: 321, }, }, user2: { upgrades: { cores: 0.25, }, }, }; const q1 = quota({}, users, site_license); expect(q1.memory_limit).toEqual(2234); // not +222, because always_running has higher priority than member hosting expect(q1.disk_quota).toBe(3000 + 321 + 111 + 333); expect(q1.member_host).toBe(false); expect(q1.network).toBe(true); expect(q1.cpu_limit).toBe(1.25); expect(q1.always_running).toBe(true); }); it("site-license quota upgrades /1", () => { const site_license = { "1234-5678-asdf-yxcv": { quota: { ram: 2, dedicated_ram: 1, cpu: 1, dedicated_cpu: 0.5, disk: 3, always_running: true, member: true, user: "academic", }, }, }; const users = { user1: { upgrades: { memory: 1313, // maxed with "ram" }, }, }; const q1 = quota({}, users, site_license); expect(q1).toEqual({ network: true, member_host: true, memory_request: 1000, cpu_request: 0.5, privileged: false, disk_quota: 3000, memory_limit: 3000, cpu_limit: 1.5, idle_timeout: 1800, always_running: true, }); }); it("site-license quota upgrades /2", () => { const site_license = { "1234-5678-asdf-yxcv": { quota: { ram: 2, cpu: 1.5, disk: 3, always_running: true, member: true, user: "academic", }, }, }; const users = { user1: { upgrades: { memory: 4321, // +1gb base quota, maxed with "ram" }, }, }; const q1 = quota({}, users, site_license); expect(q1).toEqual({ network: true, member_host: true, memory_request: 300, cpu_request: 0.05, privileged: false, disk_quota: 3000, memory_limit: 5321, cpu_limit: 1.5, idle_timeout: 1800, always_running: true, }); }); it("uses different default_quotas", () => { const site_settings = { default_quotas: { internet: true, idle_timeout: 9999, cpu: 1.5, cpu_oc: 10, mem: 2000, mem_oc: 4, disk_quota: 5432, }, }; const q1 = quota({}, { userX: {} }, undefined, site_settings); expect(q1).toEqual({ network: true, member_host: false, memory_request: 500, // OC 1:4 of 2000mb memory_limit: 2000, // default cpu_request: 0.15, // OC 1:10 and cpu 1.5 cpu_limit: 1.5, // default privileged: false, idle_timeout: 9999, disk_quota: 5432, always_running: false, }); }); it("defaults capped by lower max_upgrades", () => { const site_settings = { max_upgrades: { member_host: false, network: false, disk_quota: 333, mintime: 999, cpu_shares: 64, cores: 0.44, memory_request: 1, memory_limit: 555, }, }; const over_max = { user2: { upgrades: { network: 1, member_host: 1, }, }, }; const q1 = quota({}, over_max, undefined, site_settings); expect(q1).toEqual({ network: false, member_host: false, privileged: false, memory_request: 1, // below minimum cap, because max_upgrades in settings are stronger than hardcoded vals cpu_request: 0.02, disk_quota: 333, memory_limit: 1000, cpu_limit: 0.44, // below minimum cap, because max_upgrades in settings are stronger than hardcoded vals idle_timeout: 999, always_running: false, }); }); it("site_settings default_quotas and max_upgrades/1", () => { const site_settings = { default_quotas: { internet: true, idle_timeout: 9999, mem: 1515, cpu: 1.6, cpu_oc: 4, mem_oc: 5, }, max_upgrades: { disk_quota: 512, mintime: 3600, cpu_shares: 1024 / 10, memory_request: 1000, }, }; // capped hardcoded default by max_upgrades const q1 = quota({}, { userX: {} }, undefined, site_settings); expect(q1).toEqual({ network: true, member_host: false, memory_request: 303, // OC 1:5 of 1515mb memory_limit: 1515, // default cpu_request: 0.1, // OC 1:4 and cpu 1.6 0.4, but cpu_shares .1! cpu_limit: 1.6, // default privileged: false, idle_timeout: 3600, // capped by max_upgrades disk_quota: 512, always_running: false, }); }); it("site_settings default_quotas and max_upgrades/2", () => { const site_settings = { default_quotas: { internet: true, cpu: 1, cpu_oc: 5, }, max_upgrades: { cpu_request: 0.1, cores: 0.5, cpu_shares: 1024 / 10, }, // .1 core }; const q1 = quota({}, { userX: {} }, undefined, site_settings); expect(q1).toEqual({ network: true, member_host: false, memory_request: 200, // non-member minimum memory_limit: 1000, cpu_request: 0.1, // max upgrade cpu_limit: 0.5, // cores max_upgrades privileged: false, idle_timeout: 1800, disk_quota: 3000, always_running: false, }); }); it("site_settings default_quotas and max_upgrades/3", () => { const site_settings = { default_quotas: { internet: true, idle_timeout: 9999, mem: 2000, mem_oc: 2, cpu: 2.2, cpu_oc: 4, }, max_upgrades: { disk_quota: 512, mintime: 3600, cpu_shares: 1024, // 1 core limit cores: 2, memory_request: 500, }, }; const q1 = quota({}, { userX: {} }, undefined, site_settings); expect(q1).toEqual({ network: true, member_host: false, memory_request: 500, // OC 1:2 of 2000mb memory_limit: 2000, // default cpu_request: 0.55, // OC 1:4 of 2.2, not at maximum cpu_limit: 2, // default limited by max_upgrades privileged: false, idle_timeout: 3600, // capped by max_upgrades disk_quota: 512, always_running: false, }); }); it("takes overcommitment ratios into account for user upgrades", () => { const site_settings = { default_quotas: { mem_oc: 4, cpu_oc: 5, }, }; const users = { user1: { upgrades: { memory: 3444, cores: 1.5, }, }, }; const q1 = quota({}, users, undefined, site_settings); expect(q1.memory_request).toEqual(1111); expect(q1.memory_limit).toEqual(4444); expect(q1.cpu_request).toEqual(0.5); // (1+1.5)/5 expect(q1.cpu_limit).toEqual(2.5); }); // sum it("sanitizes bad overcommitment ratios", () => { // too low values are limited at 1 const site_settings = { default_quotas: { mem_oc: 0.25, cpu_oc: 0, }, }; const users = { user1: { upgrades: { memory: 100, cores: 1, }, }, }; const q1 = quota({}, users, undefined, site_settings); expect(q1.memory_request).toEqual(1100); expect(q1.memory_limit).toEqual(1100); expect(q1.cpu_request).toEqual(2); expect(q1.cpu_limit).toEqual(2); }); it("overcommitment with fractions", () => { // too low values are limited at 1 const site_settings = { default_quotas: { mem_oc: 2.22, cpu_oc: 6.66, }, }; const users = { user1: { upgrades: { memory: 234.56, cores: 0.234, }, }, }; const q1 = quota({}, users, undefined, site_settings); expect(q1.memory_request).toEqual(Math.round(1234 / 2.22)); expect(q1.memory_limit).toEqual(1234); expect(q1.cpu_request).toEqual(1.234 / 6.66); expect(q1.cpu_limit).toEqual(1.234); }); it("takes overcommitment ratios into account for user upgrades + site updates", () => { const site_settings = { default_quotas: { mem: 2000, mem_oc: 6, cpu: 2, cpu_oc: 10, }, }; const users = { user1: { upgrades: { memory: 1000, cores: 0.5, }, }, }; const q1 = quota({}, users, undefined, site_settings); expect(q1.memory_request).toEqual(500); expect(q1.memory_limit).toEqual(3000); expect(q1.cpu_request).toEqual(0.25); expect(q1.cpu_limit).toEqual(2.5); }); it("handles always_running admin upgrades", () => { const admin1 = quota({ member_host: 1, network: 1, always_running: 1 }, {}); const exp = { cpu_limit: 1, cpu_request: 0.05, // set at the top of quota config disk_quota: 3000, idle_timeout: 1800, member_host: true, // what this upgrade is about memory_limit: 1500, // set at the top of quota config memory_request: 300, // set at the top of quota config network: true, // what this upgrade is about privileged: false, always_running: true, }; expect(admin1).toEqual(exp); }); it("takes user always_running upgrades into account", () => { const member = quota( {}, { userX: { upgrades: { member_host: 1, always_running: 1 } } } ); expect(member.always_running).toBe(true); expect(member.member_host).toBe(true); }); it("always_running from a site_license", () => { const site_license = { "1234-5678-asdf-yxcv": { member_host: true, network: true, always_running: true, }, }; const q1 = quota({}, { userX: {} }, site_license); expect(q1.member_host).toBe(true); expect(q1.always_running).toBe(true); expect(q1.privileged).toBe(false); expect(q1.network).toBe(true); }); it("site_license basic update as expected", () => { const site_license = { "1234-5432-3456-7654": { ram: 1, cpu: 1, disk: 3, member: true, }, }; const q = quota({}, {}, site_license); expect(q.idle_timeout).toBe(1800); expect(q).toEqual({ idle_timeout: 1800, member_host: false, always_running: false, cpu_limit: 1, cpu_request: 0.02, disk_quota: 3000, memory_limit: 1000, memory_request: 200, network: false, privileged: false, }); }); it("site_license 'complements' user upgrades", () => { const site_license = { "1234-5432-3456-7654": { quota: { ram: 2, cpu: 1.5, disk: 5, member: true, }, }, }; const users = { user1: { upgrades: { member_host: false, network: true, memory_request: 1234, memory: 2345, mintime: 24 * 3600 * 50, }, }, }; const q = quota({}, users, site_license); // user quota + basic upgrade expect(q.idle_timeout).toBe(24 * 3600 * 50 + 1800); expect(q).toEqual({ always_running: false, cpu_limit: 1.5, // license cpu_request: 0.05, // implied by license member hosting disk_quota: 5000, // license idle_timeout: 4321800, // upgrade member_host: true, // license memory_limit: 2345 + 1000, // upgrade + base memory_request: 1234, // upgrade network: true, // both privileged: false, }); }); it("site_license always_running do not mix", () => { const site_license = { a: { quota: { ram: 4, always_running: false, }, }, b: { quota: { ram: 2, always_running: true, }, }, c: { quota: { ram: 1, always_running: true, }, }, }; const q = quota({}, { userX: {} }, site_license); expect(q.always_running).toBe(true); expect(q.memory_limit).toBe(3000); }); it("site_license always_running do not mix incomplete 1", () => { const site_license = { a: { quota: { ram: 4, always_running: true, member: false, }, }, b: { quota: { ram: 2, member: true, }, }, c: { quota: { ram: 1, always_running: false, }, }, }; const q = quota({}, { userX: {} }, site_license); expect(q.always_running).toBe(true); expect(q.memory_limit).toBe(4000); expect(q.member_host).toBe(false); }); it("site_license always_running do not mix incomplete 2", () => { const site_license = { a: { quota: { cpu: 2, ram: 2, disk: 2, member: true, dedicated_cpu: 1, dedicated_ram: 1, always_running: true, }, }, b: { quota: { ram: 4, dedicated_cpu: 1, dedicated_ram: 1, always_running: false, }, }, }; const q = quota({}, { userX: {} }, site_license); expect(q.always_running).toBe(true); expect(q.memory_limit).toBe(3000); expect(q.member_host).toBe(true); expect(q.memory_request).toBe(1000); expect(q.cpu_limit).toBe(3); expect(q.cpu_request).toBe(1); }); it("cap site_license upgrades by max_upgrades /1", () => { const site_license = { "1234-5678-asdf-yxcv": { quota: { ram: 10, dedicated_ram: 5, cpu: 2, dedicated_cpu: 5, disk: 10000, always_running: false, member: true, user: "academic", }, }, "4321-5678-asdf-yxcv": { quota: { ram: 7, dedicated_ram: 4, cpu: 5, dedicated_cpu: 2, disk: 60000, always_running: false, member: true, user: "academic", }, }, }; // capped at default limits const q = quota({}, null, site_license); expect(q).toEqual({ network: true, member_host: true, memory_request: 8000, cpu_request: 2, privileged: false, disk_quota: 20000, memory_limit: 16000, cpu_limit: 3, idle_timeout: 1800, always_running: false, }); }); it("cap site_license upgrades by max_upgrades /2", () => { const site_license = { "1234-5678-asdf-yxcv": { quota: { ram: 4, dedicated_ram: 3, cpu: 3, dedicated_cpu: 2, disk: 7500, always_running: true, member: true, user: "academic", }, }, "9876-5432-1098-6543": { quota: { ram: 2.1, dedicated_ram: 2.3, cpu: 2, dedicated_cpu: 1, disk: 4000, always_running: false, member: true, user: "academic", }, }, }; const users = { user1: { upgrades: { memory: 1313, }, }, }; const site_settings = { max_upgrades: { member_host: false, network: false, always_running: false, disk_quota: 333, mintime: 999, cpu_shares: 512, cores: 2, memory_request: 2500, memory: 4321, }, }; const q = quota({}, users, site_license, site_settings); expect(q).toEqual({ network: false, // user upgrade not allowed member_host: false, // user upgrade not allowed always_running: false, // user upgrade not allowed memory_request: 2500, // lower cap is 2500 memory_limit: 4321, // dedicated+shared in license > limit cpu_request: 0.5, // those 512 shares cpu_limit: 2, privileged: false, idle_timeout: 999, disk_quota: 333, }); }); it("cap site_license upgrades by max_upgrades /3", () => { const site_license = { "1234-5678-asdf-yxcv": { quota: { ram: 1, dedicated_ram: 0, cpu: 1, dedicated_cpu: 0, disk: 2000, always_running: false, member: true, user: "academic", }, }, }; // dominating site license upgrade const users = { user1: { upgrades: { network: 2, member_host: 3, disk_quota: 32000, // max 20gb memory: 20000, // max 16gb mintime: 24 * 3600 * 100, // max 90 days memory_request: 10000, // max 8gb cores: 7, // max 3 cpu_shares: 1024 * 4, }, }, }; const q = quota({}, users, site_license); expect(q).toEqual({ cpu_limit: 3, cpu_request: 2, // set at the top of quota config disk_quota: 20000, idle_timeout: 24 * 3600 * 90, member_host: true, memory_limit: 16000, // set at the top of quota config memory_request: 8000, // set at the top of quota config network: true, privileged: false, always_running: false, }); }); });