Add tests and implement timeline ingestion options with NATS and Redis subscribers
- Introduced `BinaryReachabilityLifterTests` to validate binary lifting functionality. - Created `PackRunWorkerOptions` for configuring worker paths and execution persistence. - Added `TimelineIngestionOptions` for configuring NATS and Redis ingestion transports. - Implemented `NatsTimelineEventSubscriber` for subscribing to NATS events. - Developed `RedisTimelineEventSubscriber` for reading from Redis Streams. - Added `TimelineEnvelopeParser` to normalize incoming event envelopes. - Created unit tests for `TimelineEnvelopeParser` to ensure correct field mapping. - Implemented `TimelineAuthorizationAuditSink` for logging authorization outcomes.
This commit is contained in:
84
ops/devops/tenant/k6-tenant-load.js
Normal file
84
ops/devops/tenant/k6-tenant-load.js
Normal file
@@ -0,0 +1,84 @@
|
||||
import http from 'k6/http';
|
||||
import { check, sleep } from 'k6';
|
||||
import { Rate, Trend } from 'k6/metrics';
|
||||
|
||||
const BASE_URL = __ENV.BASE_URL || 'http://localhost:8080';
|
||||
const TENANT_HEADER = __ENV.TENANT_HEADER || 'X-StellaOps-Tenant';
|
||||
const TENANTS = (__ENV.TENANTS || 'tenant-a,tenant-b,tenant-c,tenant-d,tenant-e,tenant-f,tenant-g,tenant-h,tenant-i,tenant-j')
|
||||
.split(',')
|
||||
.map((t) => t.trim())
|
||||
.filter(Boolean);
|
||||
const READ_PATHS = (__ENV.TENANT_READ_PATHS || '/api/v1/policy/effective,/api/v1/vuln/search?limit=50,/notify/api/v1/events?limit=20,/health/readiness')
|
||||
.split(',')
|
||||
.map((p) => p.trim())
|
||||
.filter(Boolean);
|
||||
const WRITE_PATHS = (__ENV.TENANT_WRITE_PATHS || '/api/v1/policy/evaluate,/notify/api/v1/test,/api/v1/tasks/submit')
|
||||
.split(',')
|
||||
.map((p) => p.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
const READ_FRACTION = Number(__ENV.READ_FRACTION || '0.9');
|
||||
const SLEEP_MS = Number(__ENV.SLEEP_MS || '250');
|
||||
let seed = Number(__ENV.SEED || '1');
|
||||
|
||||
function rnd() {
|
||||
seed = (seed * 1664525 + 1013904223) >>> 0;
|
||||
return seed / 4294967296;
|
||||
}
|
||||
|
||||
export const options = {
|
||||
vus: Number(__ENV.VUS || '250'),
|
||||
duration: __ENV.DURATION || '10m',
|
||||
thresholds: {
|
||||
http_req_failed: ['rate<0.005'],
|
||||
http_req_duration: ['p(95)<300'],
|
||||
'tenant_write_duration': ['p(95)<600'],
|
||||
'tenant_auth_failures': ['rate<0.01'],
|
||||
},
|
||||
};
|
||||
|
||||
const readDuration = new Trend('tenant_read_duration', true);
|
||||
const writeDuration = new Trend('tenant_write_duration', true);
|
||||
const authFailures = new Rate('tenant_auth_failures');
|
||||
|
||||
function pick(list) {
|
||||
return list[Math.floor(rnd() * list.length)];
|
||||
}
|
||||
|
||||
export default function () {
|
||||
const tenant = pick(TENANTS);
|
||||
const doWrite = rnd() > READ_FRACTION;
|
||||
const path = doWrite ? pick(WRITE_PATHS) : pick(READ_PATHS);
|
||||
|
||||
const headers = {
|
||||
[TENANT_HEADER]: tenant,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
const url = `${BASE_URL}${path}`;
|
||||
const payload = JSON.stringify({
|
||||
tenant,
|
||||
traceId: __VU + '-' + Date.now(),
|
||||
now: new Date().toISOString(),
|
||||
sample: 'tenant-chaos',
|
||||
});
|
||||
|
||||
const params = { headers, tags: { tenant, path, kind: doWrite ? 'write' : 'read' } };
|
||||
const res = doWrite ? http.post(url, payload, params) : http.get(url, params);
|
||||
|
||||
if (!check(res, {
|
||||
'status ok': (r) => r.status >= 200 && r.status < 300,
|
||||
})) {
|
||||
if (res.status === 401 || res.status === 403) {
|
||||
authFailures.add(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (doWrite) {
|
||||
writeDuration.add(res.timings.duration);
|
||||
} else {
|
||||
readDuration.add(res.timings.duration);
|
||||
}
|
||||
|
||||
sleep(SLEEP_MS / 1000);
|
||||
}
|
||||
Reference in New Issue
Block a user