mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-23 03:18:09 +08:00
feat(ql3): add opaque cluster environment bundle delivery
This commit is contained in:
@@ -24,31 +24,52 @@ const SECRET_REF = createSecretRef({ projectId: 'project-1', name: 'token' });
|
||||
|
||||
function acceptedOffer() {
|
||||
const executionRevision = createClusterTaskExecutionRevision({
|
||||
projectId: 'project-1', taskId: 'task-1', taskRevision: TASK_REVISION,
|
||||
sourceRevision: 1, sourceContentDigest: SOURCE_DIGEST,
|
||||
executorType: 'remote_worker', planSchema: 'qinglong/command-execution@v1',
|
||||
projectId: 'project-1',
|
||||
taskId: 'task-1',
|
||||
taskRevision: TASK_REVISION,
|
||||
sourceRevision: 1,
|
||||
sourceContentDigest: SOURCE_DIGEST,
|
||||
executorType: 'remote_worker',
|
||||
planSchema: 'qinglong/command-execution@v1',
|
||||
command: { kind: 'argv', file: '/bin/true', args: [] },
|
||||
environment: [{ name: 'TOKEN', kind: 'secret', secretRef: SECRET_REF }],
|
||||
createdAtMs: 1,
|
||||
});
|
||||
return createClusterRemoteExecutionOffer({
|
||||
offerId: 'offer-1', deliveryKind: 'new_claim',
|
||||
offerId: 'offer-1',
|
||||
deliveryKind: 'new_claim',
|
||||
executionDigest: executionRevision.contentDigest,
|
||||
candidate: {
|
||||
runId: 'run-1', attemptId: 'attempt-1', projectId: 'project-1',
|
||||
taskId: 'task-1', taskRevision: TASK_REVISION, priority: 1,
|
||||
queuedAtMs: 10, attemptCreatedAtMs: 11, attemptNumber: 1,
|
||||
runId: 'run-1',
|
||||
attemptId: 'attempt-1',
|
||||
projectId: 'project-1',
|
||||
taskId: 'task-1',
|
||||
taskRevision: TASK_REVISION,
|
||||
priority: 1,
|
||||
queuedAtMs: 10,
|
||||
attemptCreatedAtMs: 11,
|
||||
attemptNumber: 1,
|
||||
executorType: 'remote_worker',
|
||||
},
|
||||
worker: { workerId: 'edge-1', sessionId: SESSION_ID, generation: 2 },
|
||||
lease: {
|
||||
attemptId: 'attempt-1', runId: 'run-1', status: 'leased', version: 4,
|
||||
leaseGeneration: 3, workerId: 'edge-1', workerSessionId: SESSION_ID,
|
||||
workerGeneration: 2, leaseTokenDigest: digestRunDispatchLeaseToken(LEASE_TOKEN),
|
||||
acquiredAtMs: 20, renewedAtMs: 20, expiresAtMs: 30_020,
|
||||
attemptId: 'attempt-1',
|
||||
runId: 'run-1',
|
||||
status: 'leased',
|
||||
version: 4,
|
||||
leaseGeneration: 3,
|
||||
workerId: 'edge-1',
|
||||
workerSessionId: SESSION_ID,
|
||||
workerGeneration: 2,
|
||||
leaseTokenDigest: digestRunDispatchLeaseToken(LEASE_TOKEN),
|
||||
acquiredAtMs: 20,
|
||||
renewedAtMs: 20,
|
||||
expiresAtMs: 30_020,
|
||||
updatedAtMs: 20,
|
||||
},
|
||||
leaseToken: LEASE_TOKEN, executionRevision, placementScore: 0,
|
||||
leaseToken: LEASE_TOKEN,
|
||||
executionRevision,
|
||||
placementScore: 0,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -62,6 +83,7 @@ function requestFor(offer) {
|
||||
offerId: offer.offerId,
|
||||
executionDigest: offer.executionDigest,
|
||||
secretRefs: [SECRET_REF],
|
||||
environmentBundleRefs: [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -78,12 +100,17 @@ test('rehydrates lease authority from inbox and delivers one exact Secret batch'
|
||||
client: {
|
||||
async postJson(request) {
|
||||
transport = request;
|
||||
return Buffer.from(JSON.stringify({
|
||||
schema: 'qinglong/remote-secret-delivery@v1',
|
||||
runId: 'run-1', attemptId: 'attempt-1', offerId: 'offer-1',
|
||||
executionDigest: offer.executionDigest,
|
||||
values: [{ secretRef: SECRET_REF, value: 'resolved-value' }],
|
||||
}));
|
||||
return Buffer.from(
|
||||
JSON.stringify({
|
||||
schema: 'qinglong/remote-secret-delivery@v2',
|
||||
runId: 'run-1',
|
||||
attemptId: 'attempt-1',
|
||||
offerId: 'offer-1',
|
||||
executionDigest: offer.executionDigest,
|
||||
values: [{ secretRef: SECRET_REF, value: 'resolved-value' }],
|
||||
environmentBundles: [],
|
||||
}),
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -91,7 +118,11 @@ test('rehydrates lease authority from inbox and delivers one exact Secret batch'
|
||||
assert.deepEqual(resolution.values, [
|
||||
{ secretRef: SECRET_REF, value: 'resolved-value' },
|
||||
]);
|
||||
assert.equal(transport.path.endsWith(`/sessions/${SESSION_ID}/secrets`), true);
|
||||
assert.deepEqual(resolution.environmentBundles, []);
|
||||
assert.equal(
|
||||
transport.path.endsWith(`/sessions/${SESSION_ID}/secrets`),
|
||||
true,
|
||||
);
|
||||
assert.equal(transport.body.leaseToken, LEASE_TOKEN);
|
||||
assert.equal(transport.maximumRequestBytes, 64 * 1024);
|
||||
assert.equal(JSON.stringify(requestFor(offer)).includes(LEASE_TOKEN), false);
|
||||
@@ -102,9 +133,15 @@ test('rejects a stale inbox identity before sending the capability', async () =>
|
||||
let calls = 0;
|
||||
const provider = new WorkerRemoteSecretHttpsProvider({
|
||||
inbox: {
|
||||
async readOffer() { return { state: 'starting_acknowledged', offer }; },
|
||||
async readOffer() {
|
||||
return { state: 'starting_acknowledged', offer };
|
||||
},
|
||||
},
|
||||
client: {
|
||||
async postJson() {
|
||||
calls += 1;
|
||||
},
|
||||
},
|
||||
client: { async postJson() { calls += 1; } },
|
||||
});
|
||||
await assert.rejects(
|
||||
provider.resolve({ ...requestFor(offer), executionDigest: 'b'.repeat(64) }),
|
||||
@@ -117,16 +154,23 @@ test('rejects response authority drift and does not return plaintext', async ()
|
||||
const offer = acceptedOffer();
|
||||
const provider = new WorkerRemoteSecretHttpsProvider({
|
||||
inbox: {
|
||||
async readOffer() { return { state: 'starting_acknowledged', offer }; },
|
||||
async readOffer() {
|
||||
return { state: 'starting_acknowledged', offer };
|
||||
},
|
||||
},
|
||||
client: {
|
||||
async postJson() {
|
||||
return Buffer.from(JSON.stringify({
|
||||
schema: 'qinglong/remote-secret-delivery@v1',
|
||||
runId: 'run-other', attemptId: 'attempt-1', offerId: 'offer-1',
|
||||
executionDigest: offer.executionDigest,
|
||||
values: [{ secretRef: SECRET_REF, value: 'must-not-escape' }],
|
||||
}));
|
||||
return Buffer.from(
|
||||
JSON.stringify({
|
||||
schema: 'qinglong/remote-secret-delivery@v2',
|
||||
runId: 'run-other',
|
||||
attemptId: 'attempt-1',
|
||||
offerId: 'offer-1',
|
||||
executionDigest: offer.executionDigest,
|
||||
values: [{ secretRef: SECRET_REF, value: 'must-not-escape' }],
|
||||
environmentBundles: [],
|
||||
}),
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -138,10 +182,21 @@ test('does not fetch Secrets before starting ACK or after the launch barrier', a
|
||||
for (const state of ['accepted', 'launching']) {
|
||||
let calls = 0;
|
||||
const provider = new WorkerRemoteSecretHttpsProvider({
|
||||
inbox: { async readOffer() { return { state, offer }; } },
|
||||
client: { async postJson() { calls += 1; } },
|
||||
inbox: {
|
||||
async readOffer() {
|
||||
return { state, offer };
|
||||
},
|
||||
},
|
||||
client: {
|
||||
async postJson() {
|
||||
calls += 1;
|
||||
},
|
||||
},
|
||||
});
|
||||
await assert.rejects(provider.resolve(requestFor(offer)), /offer_unavailable/);
|
||||
await assert.rejects(
|
||||
provider.resolve(requestFor(offer)),
|
||||
/offer_unavailable/,
|
||||
);
|
||||
assert.equal(calls, 0);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user