@milaboratories/pl-client 3.16.2 → 3.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/capabilities.cjs.map +1 -1
- package/dist/core/capabilities.d.ts +1 -1
- package/dist/core/capabilities.d.ts.map +1 -1
- package/dist/core/capabilities.js.map +1 -1
- package/dist/core/transaction.cjs +37 -5
- package/dist/core/transaction.cjs.map +1 -1
- package/dist/core/transaction.d.ts +32 -3
- package/dist/core/transaction.d.ts.map +1 -1
- package/dist/core/transaction.js +37 -5
- package/dist/core/transaction.js.map +1 -1
- package/dist/core/tree_filter.cjs +2 -1
- package/dist/core/tree_filter.cjs.map +1 -1
- package/dist/core/tree_filter.d.ts +2 -1
- package/dist/core/tree_filter.d.ts.map +1 -1
- package/dist/core/tree_filter.js +2 -1
- package/dist/core/tree_filter.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs +33 -11
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts +129 -37
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js +33 -11
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js.map +1 -1
- package/dist/test/test_config.cjs +92 -3
- package/dist/test/test_config.cjs.map +1 -1
- package/dist/test/test_config.d.ts +29 -4
- package/dist/test/test_config.d.ts.map +1 -1
- package/dist/test/test_config.js +88 -4
- package/dist/test/test_config.js.map +1 -1
- package/package.json +4 -4
- package/src/core/capabilities.ts +4 -0
- package/src/core/client.test.ts +5 -5
- package/src/core/ll_client.test.ts +8 -1
- package/src/core/ll_transaction.test.ts +9 -3
- package/src/core/transaction.test.ts +6 -6
- package/src/core/transaction.ts +53 -8
- package/src/core/tree_filter.ts +2 -1
- package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.ts +158 -51
- package/src/test/test_config.test.ts +14 -1
- package/src/test/test_config.ts +102 -4
package/src/test/test_config.ts
CHANGED
|
@@ -19,6 +19,8 @@ export interface TestConfig {
|
|
|
19
19
|
test_proxy?: string;
|
|
20
20
|
test_user?: string;
|
|
21
21
|
test_password?: string;
|
|
22
|
+
test_admin_user?: string;
|
|
23
|
+
test_admin_password?: string;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
const CONFIG_FILE = "test_config.json";
|
|
@@ -44,6 +46,12 @@ export function getTestConfig(): TestConfig {
|
|
|
44
46
|
|
|
45
47
|
if (process.env.PL_TEST_PROXY !== undefined) conf.test_proxy = process.env.PL_TEST_PROXY;
|
|
46
48
|
|
|
49
|
+
if (process.env.PL_TEST_ADMIN_USER !== undefined)
|
|
50
|
+
conf.test_admin_user = process.env.PL_TEST_ADMIN_USER;
|
|
51
|
+
|
|
52
|
+
if (process.env.PL_TEST_ADMIN_PASSWORD !== undefined)
|
|
53
|
+
conf.test_admin_password = process.env.PL_TEST_ADMIN_PASSWORD;
|
|
54
|
+
|
|
47
55
|
if (conf.address === undefined)
|
|
48
56
|
throw new Error(
|
|
49
57
|
`can't resolve platform address (checked ${CONFIG_FILE} file and PL_ADDRESS environment var)`,
|
|
@@ -52,13 +60,37 @@ export function getTestConfig(): TestConfig {
|
|
|
52
60
|
return conf as TestConfig;
|
|
53
61
|
}
|
|
54
62
|
|
|
55
|
-
/**
|
|
56
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Default request timeout for tests (ms).
|
|
65
|
+
*
|
|
66
|
+
* Kept short so a hung call fails the test instead of the suite's own budget. A deploy the
|
|
67
|
+
* tests reach over cluster DNS needs more than that on first contact, where the deadline
|
|
68
|
+
* covers name resolution too:
|
|
69
|
+
*
|
|
70
|
+
* RpcError: Deadline exceeded after 0.500s,waiting for name resolution
|
|
71
|
+
*
|
|
72
|
+
* That call builds the shared client, so the whole file dies with it and retries only
|
|
73
|
+
* repeat the error against an undefined client. PL_TEST_REQUEST_TIMEOUT raises the budget
|
|
74
|
+
* where resolution is slow, and every other environment keeps the short one.
|
|
75
|
+
*/
|
|
76
|
+
export const TEST_REQUEST_TIMEOUT = Number(process.env.PL_TEST_REQUEST_TIMEOUT ?? 500);
|
|
77
|
+
|
|
78
|
+
/** True when the address carries an explicit `request-timeout` query parameter. */
|
|
79
|
+
function addressStatesRequestTimeout(address: string): boolean {
|
|
80
|
+
if (address.indexOf("://") === -1) return false;
|
|
81
|
+
return new URL(address).searchParams.has("request-timeout");
|
|
82
|
+
}
|
|
57
83
|
|
|
58
|
-
/** Returns PlClientConfig with reduced timeout for tests */
|
|
84
|
+
/** Returns PlClientConfig with reduced timeout for tests, unless the address sets its own */
|
|
59
85
|
export function plAddressToTestConfig(address: string): PlClientConfig {
|
|
60
86
|
const plConf = plAddressToConfig(address);
|
|
61
|
-
|
|
87
|
+
// An explicit request-timeout in the address wins over TEST_REQUEST_TIMEOUT. In the k8s e2e
|
|
88
|
+
// deploy the client dials a cluster service DNS name, and the first call on a cold channel must
|
|
89
|
+
// finish name resolution and get a load-balancer pick before it is even sent; 500ms does not
|
|
90
|
+
// cover that, so whichever test happened to open the cold channel died with DEADLINE_EXCEEDED
|
|
91
|
+
// ("Waiting for LB pick") against a healthy backend. Addresses that carry no request-timeout
|
|
92
|
+
// keep the short default, so local runs still fail fast.
|
|
93
|
+
if (!addressStatesRequestTimeout(address)) plConf.defaultRequestTimeout = TEST_REQUEST_TIMEOUT;
|
|
62
94
|
return plConf;
|
|
63
95
|
}
|
|
64
96
|
|
|
@@ -178,6 +210,72 @@ export async function getTestLLClient(confOverrides: Partial<PlClientConfig> = {
|
|
|
178
210
|
return await LLPlClient.build({ ...conf, ...confOverrides }, { auth });
|
|
179
211
|
}
|
|
180
212
|
|
|
213
|
+
/** Returns a config logged in as the admin test user, or the ordinary test config where no
|
|
214
|
+
* admin credentials are set. A backend that needs no auth, and one whose single test user
|
|
215
|
+
* already holds the admin role, both leave PL_TEST_ADMIN_USER and PL_TEST_ADMIN_PASSWORD
|
|
216
|
+
* unset, and a test that asks for admin must still run there. */
|
|
217
|
+
export async function getTestAdminClientConf(): Promise<{ conf: PlClientConfig; auth: AuthOps }> {
|
|
218
|
+
const tConf = getTestConfig();
|
|
219
|
+
|
|
220
|
+
if (tConf.test_admin_user === undefined || tConf.test_admin_password === undefined)
|
|
221
|
+
return await getTestClientConf();
|
|
222
|
+
|
|
223
|
+
const plConf = plAddressToTestConfig(tConf.address);
|
|
224
|
+
const uClient = await UnauthenticatedPlClient.build(plConf);
|
|
225
|
+
const authInformation = await uClient.login(tConf.test_admin_user, tConf.test_admin_password);
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
conf: plConf,
|
|
229
|
+
auth: {
|
|
230
|
+
authInformation,
|
|
231
|
+
onUpdate: () => {},
|
|
232
|
+
onAuthError: () => {},
|
|
233
|
+
onUpdateError: () => {},
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export async function getTestAdminLLClient(confOverrides: Partial<PlClientConfig> = {}) {
|
|
239
|
+
const { conf, auth } = await getTestAdminClientConf();
|
|
240
|
+
return await LLPlClient.build({ ...conf, ...confOverrides }, { auth });
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export async function getTestAdminClient(
|
|
244
|
+
alternativeRoot?: string,
|
|
245
|
+
confOverrides: Partial<PlClientConfig> = {},
|
|
246
|
+
) {
|
|
247
|
+
const { conf, auth } = await getTestAdminClientConf();
|
|
248
|
+
if (alternativeRoot !== undefined && conf.alternativeRoot !== undefined)
|
|
249
|
+
throw new Error("test pl address configured with alternative root");
|
|
250
|
+
return await PlClient.init({ ...conf, ...confOverrides, alternativeRoot }, auth);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export async function withAdminTempRoot<T>(body: (pl: PlClient) => Promise<T>): Promise<T | void> {
|
|
254
|
+
const alternativeRoot = `test_${Date.now()}_${randomUUID()}`;
|
|
255
|
+
let altRootId: OptionalSignedResourceId = NullSignedResourceId;
|
|
256
|
+
try {
|
|
257
|
+
const client = await getTestAdminClient(alternativeRoot);
|
|
258
|
+
altRootId = client.clientRoot;
|
|
259
|
+
try {
|
|
260
|
+
const value = await body(client);
|
|
261
|
+
const rawClient = await getTestAdminClient();
|
|
262
|
+
try {
|
|
263
|
+
await rawClient.deleteAlternativeRoot(alternativeRoot);
|
|
264
|
+
} catch (cleanupErr: any) {
|
|
265
|
+
console.warn(`Failed to clean up alternative root ${alternativeRoot}:`, cleanupErr.message);
|
|
266
|
+
} finally {
|
|
267
|
+
await rawClient.close();
|
|
268
|
+
}
|
|
269
|
+
return value;
|
|
270
|
+
} finally {
|
|
271
|
+
await client.close();
|
|
272
|
+
}
|
|
273
|
+
} catch (err: any) {
|
|
274
|
+
console.log(`ALTERNATIVE ROOT: ${alternativeRoot} (${resourceIdToString(altRootId)})`);
|
|
275
|
+
throw err;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
181
279
|
export async function getTestClient(
|
|
182
280
|
alternativeRoot?: string,
|
|
183
281
|
confOverrides: Partial<PlClientConfig> = {},
|