chore: commit all pending changes and ignore project context
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
import http from 'k6/http';
|
||||
import { check, fail, sleep } from 'k6';
|
||||
import exec from 'k6/execution';
|
||||
|
||||
const BASE_URL = (__ENV.BASE_URL || 'https://127.0.0.1:2288').replace(/\/$/, '');
|
||||
const HOST_HEADER = (__ENV.HOST_HEADER || 'stend.4mont.ru').trim();
|
||||
const SERVICE_A = __ENV.SERVICE_A || 'termidesk';
|
||||
const SERVICE_B = __ENV.SERVICE_B || 'vmmanager';
|
||||
const CLOSE_SESSION = (__ENV.CLOSE_SESSION || '1') !== '0';
|
||||
const REQ_TIMEOUT = __ENV.REQ_TIMEOUT || '20s';
|
||||
|
||||
const users = (__ENV.USERS_CSV || '')
|
||||
.split(';')
|
||||
.map((v) => v.trim())
|
||||
.filter(Boolean)
|
||||
.map((pair) => {
|
||||
const i = pair.indexOf(':');
|
||||
return i > 0 ? { username: pair.slice(0, i), password: pair.slice(i + 1) } : null;
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
export const options = {
|
||||
scenarios: {
|
||||
burst_100_users: {
|
||||
executor: 'per-vu-iterations',
|
||||
vus: 100,
|
||||
iterations: 1,
|
||||
maxDuration: '3m',
|
||||
},
|
||||
},
|
||||
insecureSkipTLSVerify: true,
|
||||
thresholds: {
|
||||
http_req_failed: ['rate<0.2'],
|
||||
},
|
||||
};
|
||||
|
||||
function hdr(extra = {}) {
|
||||
return HOST_HEADER ? { ...extra, Host: HOST_HEADER } : extra;
|
||||
}
|
||||
|
||||
function getCreds() {
|
||||
if (users.length < 100) fail(`Need at least 100 users in USERS_CSV, got ${users.length}`);
|
||||
const idx = (exec.vu.idInTest || 1) - 1;
|
||||
return users[idx % users.length];
|
||||
}
|
||||
|
||||
function login(username, password) {
|
||||
const jar = http.cookieJar();
|
||||
jar.clear(BASE_URL);
|
||||
|
||||
const landing = http.get(`${BASE_URL}/`, {
|
||||
redirects: 0,
|
||||
timeout: REQ_TIMEOUT,
|
||||
headers: hdr(),
|
||||
tags: { name: 'GET /' },
|
||||
});
|
||||
|
||||
const csrfFromCookie = (jar.cookiesForURL(BASE_URL).csrf_token || [])[0] || '';
|
||||
const csrf = csrfFromCookie || ((landing.cookies.csrf_token || [])[0] || {}).value || '';
|
||||
if (!csrf) fail(`No CSRF for ${username}`);
|
||||
|
||||
const payload = [
|
||||
`username=${encodeURIComponent(username)}`,
|
||||
`password=${encodeURIComponent(password)}`,
|
||||
`csrf_token=${encodeURIComponent(csrf)}`,
|
||||
].join('&');
|
||||
|
||||
const loginRes = http.post(`${BASE_URL}/login`, payload, {
|
||||
redirects: 0,
|
||||
timeout: REQ_TIMEOUT,
|
||||
headers: hdr({ 'Content-Type': 'application/x-www-form-urlencoded' }),
|
||||
tags: { name: 'POST /login' },
|
||||
});
|
||||
|
||||
const ok = check(loginRes, { 'login status 303': (r) => r.status === 303 });
|
||||
if (!ok) fail(`Login failed ${username}, status=${loginRes.status}`);
|
||||
}
|
||||
|
||||
function openService(slug) {
|
||||
const res = http.get(`${BASE_URL}/go/${slug}`, {
|
||||
redirects: 0,
|
||||
timeout: REQ_TIMEOUT,
|
||||
headers: hdr(),
|
||||
tags: { name: 'GET /go/:slug' },
|
||||
});
|
||||
const ok = check(res, { [`open ${slug} -> 303`]: (r) => r.status === 303 });
|
||||
const location = res.headers.Location || '';
|
||||
const m = location.match(/\/s\/([0-9a-fA-F-]{36})\//);
|
||||
return { ok, status: res.status, sessionId: m ? m[1] : '', location };
|
||||
}
|
||||
|
||||
function closeSession(sessionId) {
|
||||
if (!sessionId || !CLOSE_SESSION) return;
|
||||
http.post(`${BASE_URL}/api/sessions/${sessionId}/close`, null, {
|
||||
redirects: 0,
|
||||
timeout: REQ_TIMEOUT,
|
||||
headers: hdr(),
|
||||
tags: { name: 'POST /api/sessions/:id/close' },
|
||||
});
|
||||
}
|
||||
|
||||
export default function () {
|
||||
const { username, password } = getCreds();
|
||||
login(username, password);
|
||||
|
||||
const a = openService(SERVICE_A);
|
||||
sleep(0.1);
|
||||
const b = openService(SERVICE_B);
|
||||
|
||||
closeSession(a.sessionId);
|
||||
closeSession(b.sessionId);
|
||||
|
||||
if (!a.ok || !b.ok) {
|
||||
fail(`open failed user=${username} a=${a.status} b=${b.status}`);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import exec from 'k6/execution';
|
||||
import { Counter, Rate, Trend } from 'k6/metrics';
|
||||
|
||||
const BASE_URL = (__ENV.BASE_URL || 'https://stend.4mont.ru').replace(/\/$/, '');
|
||||
const HOST_HEADER = (__ENV.HOST_HEADER || '').trim();
|
||||
const SERVICE_SLUGS = (__ENV.SERVICE_SLUGS || 'vmmanager')
|
||||
.split(',')
|
||||
.map((s) => s.trim())
|
||||
@@ -51,6 +52,7 @@ const selected = PROFILE_OPTIONS[PROFILE] || PROFILE_OPTIONS.smoke;
|
||||
|
||||
export const options = {
|
||||
...selected,
|
||||
noCookiesReset: true,
|
||||
insecureSkipTLSVerify: (__ENV.INSECURE_TLS || '0') === '1',
|
||||
thresholds: {
|
||||
http_req_failed: ['rate<0.02'],
|
||||
@@ -61,6 +63,11 @@ export const options = {
|
||||
|
||||
let loggedInKey = '';
|
||||
|
||||
function withHostHeaders(headers = {}) {
|
||||
if (!HOST_HEADER) return headers;
|
||||
return { ...headers, Host: HOST_HEADER };
|
||||
}
|
||||
|
||||
function parseUsersCsv(raw) {
|
||||
if (!raw.trim()) return [];
|
||||
return raw
|
||||
@@ -98,7 +105,11 @@ function ensureLoggedIn() {
|
||||
const jar = http.cookieJar();
|
||||
jar.clear(BASE_URL);
|
||||
|
||||
const landing = http.get(`${BASE_URL}/`, { redirects: 0, tags: { name: 'GET /' } });
|
||||
const landing = http.get(`${BASE_URL}/`, {
|
||||
redirects: 0,
|
||||
tags: { name: 'GET /' },
|
||||
headers: withHostHeaders(),
|
||||
});
|
||||
const csrfFromCookie = (jar.cookiesForURL(BASE_URL).csrf_token || [])[0] || '';
|
||||
const csrf = csrfFromCookie || ((landing.cookies.csrf_token || [])[0] || {}).value || '';
|
||||
if (!csrf) {
|
||||
@@ -114,7 +125,7 @@ function ensureLoggedIn() {
|
||||
|
||||
const loginRes = http.post(`${BASE_URL}/login`, payload, {
|
||||
redirects: 0,
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
headers: withHostHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' }),
|
||||
tags: { name: 'POST /login' },
|
||||
});
|
||||
|
||||
@@ -150,6 +161,7 @@ export default function () {
|
||||
const openRes = http.get(`${BASE_URL}/go/${slug}`, {
|
||||
redirects: 0,
|
||||
tags: { name: 'GET /go/:slug' },
|
||||
headers: withHostHeaders(),
|
||||
});
|
||||
openLatency.add(openRes.timings.duration);
|
||||
|
||||
@@ -187,6 +199,7 @@ export default function () {
|
||||
const touchRes = http.post(`${BASE_URL}/api/sessions/${sessionId}/touch`, null, {
|
||||
redirects: 0,
|
||||
tags: { name: 'POST /api/sessions/:id/touch' },
|
||||
headers: withHostHeaders(),
|
||||
});
|
||||
|
||||
if (touchRes.status === 410) {
|
||||
@@ -208,6 +221,7 @@ export default function () {
|
||||
const closeRes = http.post(`${BASE_URL}/api/sessions/${sessionId}/close`, null, {
|
||||
redirects: 0,
|
||||
tags: { name: 'POST /api/sessions/:id/close' },
|
||||
headers: withHostHeaders(),
|
||||
});
|
||||
closeCalls.add(1);
|
||||
check(closeRes, {
|
||||
|
||||
Reference in New Issue
Block a user