Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/database/postgres/site-license/hook.test.ts
1503 views
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
/**
7
8
pnpm test hook.test.ts
9
10
* This tests the core of ./hook.ts
11
* It's not using it directly, though, because of the complex dependency of the database.
12
* The main purpose of this test is to simulate what happens, if first a partial set of licenses,
13
* and then one more license is fed through the quota function.
14
* There was a bug, where licenses were modified in place, and the second call to the quota function
15
* used the modified license, which led to very subtle but severe problems.
16
*
17
* The quota function uses a deep copy operation on all its arguments to avoid this.
18
*/
19
20
// see packages/database/pool/pool.ts for where this name is also hard coded:
21
process.env.PGDATABASE = "smc_ephemeral_testing_database";
22
23
import { isEqual } from "lodash";
24
25
import getPool, { initEphemeralDatabase } from "@cocalc/database/pool";
26
import { quota_with_reasons, SiteLicenses } from "@cocalc/util/upgrades/quota";
27
28
beforeAll(async () => {
29
await initEphemeralDatabase({});
30
}, 15000);
31
32
afterAll(async () => {
33
await getPool().end();
34
});
35
36
test("allow for much larger max_upgrades", () => {
37
const site_settings = {
38
default_quotas: {
39
internet: true,
40
idle_timeout: 1800,
41
mem: 2000,
42
cpu: 1,
43
cpu_oc: 20,
44
mem_oc: 10,
45
},
46
max_upgrades: {
47
disk_quota: 20000,
48
memory: 50000,
49
memory_request: 1000,
50
cores: 16,
51
network: 1,
52
cpu_shares: 1024,
53
mintime: 7776000,
54
member_host: 1,
55
ephemeral_state: 1,
56
ephemeral_disk: 1,
57
always_running: 1,
58
},
59
kucalc: "onprem",
60
datastore: true,
61
};
62
63
const site_licenses: SiteLicenses = {
64
a: {
65
quota: { cpu: 2, ram: 13 },
66
},
67
b: {
68
quota: { cpu: 3, ram: 32 },
69
},
70
};
71
72
const q1 = quota_with_reasons(
73
{},
74
{ userX: {} },
75
{ a: site_licenses.a },
76
site_settings,
77
);
78
expect(q1).toEqual({
79
quota: {
80
network: true,
81
member_host: false,
82
privileged: false,
83
gpu: false,
84
memory_request: 1000,
85
cpu_request: 0.1,
86
disk_quota: 3000,
87
memory_limit: 13000,
88
cpu_limit: 2,
89
idle_timeout: 1800,
90
always_running: false,
91
dedicated_vm: false,
92
dedicated_disks: [],
93
},
94
reasons: {},
95
});
96
97
const q2 = quota_with_reasons(
98
{},
99
{ userX: {} },
100
site_licenses,
101
site_settings,
102
);
103
expect(q2).toEqual({
104
quota: {
105
always_running: false,
106
cpu_limit: 5,
107
cpu_request: 0.25,
108
dedicated_disks: [],
109
dedicated_vm: false,
110
disk_quota: 3000,
111
idle_timeout: 1800,
112
member_host: false,
113
memory_limit: 45000,
114
memory_request: 1000,
115
network: true,
116
privileged: false,
117
gpu: false,
118
},
119
reasons: {},
120
});
121
});
122
123
test("two licenses", () => {
124
const site_settings = {
125
default_quotas: {
126
internet: true,
127
idle_timeout: 1800,
128
mem: 2000,
129
cpu: 1,
130
cpu_oc: 20,
131
mem_oc: 10,
132
},
133
max_upgrades: {
134
disk_quota: 20000,
135
memory: 50000,
136
memory_request: 1000,
137
cores: 16,
138
network: 1,
139
cpu_shares: 1024,
140
mintime: 7776000,
141
member_host: 1,
142
ephemeral_state: 1,
143
ephemeral_disk: 1,
144
always_running: 1,
145
},
146
kucalc: "onprem",
147
datastore: true,
148
};
149
150
const site_licenses = {
151
a: {
152
quota: { cpu: 1, ram: 13 },
153
},
154
b: {
155
quota: { cpu: 3, ram: 32 },
156
},
157
};
158
159
const q1 = quota_with_reasons(
160
{},
161
{ userX: {} },
162
{ a: site_licenses.a },
163
site_settings,
164
);
165
expect(q1).toEqual({
166
quota: {
167
network: true,
168
member_host: false,
169
privileged: false,
170
gpu: false,
171
memory_request: 1000,
172
cpu_request: 0.05,
173
disk_quota: 3000,
174
memory_limit: 13000,
175
cpu_limit: 1,
176
idle_timeout: 1800,
177
always_running: false,
178
dedicated_vm: false,
179
dedicated_disks: [],
180
},
181
reasons: {},
182
});
183
184
const q2 = quota_with_reasons(
185
{},
186
{ userX: {} },
187
site_licenses,
188
site_settings,
189
);
190
expect(q1).toEqual({
191
quota: {
192
network: true,
193
member_host: false,
194
privileged: false,
195
gpu: false,
196
memory_request: 1000,
197
cpu_request: 0.05,
198
disk_quota: 3000,
199
memory_limit: 13000,
200
cpu_limit: 1,
201
idle_timeout: 1800,
202
always_running: false,
203
dedicated_vm: false,
204
dedicated_disks: [],
205
},
206
reasons: {},
207
});
208
209
expect(q2).toEqual({
210
quota: {
211
always_running: false,
212
cpu_limit: 4,
213
cpu_request: 0.2,
214
dedicated_disks: [],
215
dedicated_vm: false,
216
disk_quota: 3000,
217
idle_timeout: 1800,
218
member_host: false,
219
memory_limit: 45000,
220
memory_request: 1000,
221
network: true,
222
privileged: false,
223
gpu: false,
224
},
225
reasons: {},
226
});
227
228
// in particular, this implies that the second license indeed HAS an effect and hence will be used.
229
expect(isEqual(q1, q2)).toBe(false);
230
});
231
232
// TODO the test below would be very important to get to work, but the call to the site_license_hook has no effect at all
233
234
// describe("site_license_hook", () => {
235
// const pool = getPool();
236
// const account_id = uuid();
237
// const license_id_1 = uuid();
238
// const license_id_2 = uuid();
239
240
// let project_id;
241
// test("creates a project", async () => {
242
// project_id = await createProject({
243
// account_id,
244
// title: "Test Project",
245
// });
246
// });
247
248
// test("setup project license", async () => {
249
// const site_licenses_data: SiteLicenses = {
250
// [license_id_1]: {
251
// quota: {
252
// dedicated_disk: { speed: "standard", size_gb: 128, name: "bar" },
253
// },
254
// },
255
// [license_id_2]: {
256
// quota: {
257
// ram: 2,
258
// cpu: 1,
259
// disk: 3,
260
// always_running: true,
261
// member: true,
262
// user: "academic",
263
// },
264
// },
265
// };
266
267
// await pool.query(
268
// "UPDATE projects SET site_license=$1 WHERE project_id=$2",
269
// [site_licenses_data, project_id]
270
// );
271
// });
272
273
// test("PAYGO mixes with dedicated disk", async () => {
274
// // run the hook -- "true" means there are PAYGO upgrades, different mode of how the license hook operates
275
// await site_license_hook(db(), project_id, true);
276
277
// const { rows } = await pool.query(
278
// "SELECT * FROM projects WHERE project_id=$1",
279
// [project_id]
280
// );
281
// expect(rows.length).toBe(1);
282
// const site_licenses = rows[0].site_license;
283
// expect(rows[0].site_license).toEqual({
284
// [license_id_1]: {
285
// quota: {
286
// dedicated_disk: { name: "bar", size_gb: 128, speed: "standard" },
287
// },
288
// },
289
// [license_id_2]: {
290
// quota: {
291
// always_running: true,
292
// cpu: 1,
293
// disk: 3,
294
// member: true,
295
// ram: 2,
296
// user: "academic",
297
// },
298
// },
299
// });
300
301
// const q = quota_with_reasons({}, { [account_id]: {} }, site_licenses);
302
// // projects on dedicated VMs get this quota
303
// expect(q).toEqual({
304
// quota: {
305
// always_running: false,
306
// cpu_limit: 1,
307
// cpu_request: 0.02,
308
// dedicated_disks: [
309
// {
310
// name: "bar",
311
// size_gb: 128,
312
// speed: "standard",
313
// },
314
// ],
315
// dedicated_vm: false,
316
// disk_quota: 3000,
317
// idle_timeout: 1800,
318
// member_host: false,
319
// memory_limit: 1000,
320
// memory_request: 200,
321
// network: false,
322
// privileged: false,gpu:false,
323
// },
324
// reasons: {},
325
// });
326
// });
327
// });
328
329