import { check, fail, sleep } from 'k6'; import http from 'k6/http'; // Parameters const vus = __ENV.VUS || 1 const perVuIterations = parseInt(__ENV.PER_VU_ITERATIONS || 30) const baseUrl = __ENV.BASE_URL const username = __ENV.USERNAME const password = __ENV.PASSWORD const token = __ENV.TOKEN const cluster = __ENV.CLUSTER || "local" const resource = __ENV.RESOURCE || "management.cattle.io.setting" const api = __ENV.API || "steve" const paginationStyle = __ENV.PAGINATION_STYLE || "k8s" const pageSize = parseInt(__ENV.PAGE_SIZE || 100) const firstPageOnly = __ENV.FIRST_PAGE_ONLY === "true" const urlSuffix = __ENV.URL_SUFFIX || "" const pauseSeconds = parseFloat(__ENV.PAUSE_SECONDS || 0.0) // Option setting export const options = { insecureSkipTLSVerify: true, scenarios: { list: { executor: 'per-vu-iterations', exec: 'list', vus: vus, iterations: perVuIterations, maxDuration: '24h', } }, thresholds: { checks: ['rate>0.99'] } } // Test functions, in order of execution export function setup() { // if session cookie was specified, save it if (token) { return { R_SESS: token } } // if credentials were specified, log in if (username && password) { const res = http.post(`${baseUrl}/v3-public/localProviders/local?action=login`, JSON.stringify({ "description": "UI session", "responseType": "cookie", "username": username, "password": password })) check(res, { 'logging in returns status 200': (r) => r.status === 200, }) pause() return http.cookieJar().cookiesForURL(res.url) } return {} } // Simulate a pause after a click - on average pauseSeconds, +/- a random quantity up to 50% function pause() { sleep(pauseSeconds + (Math.random() - 0.5) * 2 * pauseSeconds / 2) } export function list(cookies, filters = "") { if (api === "steve") { const url = cluster === "local" ? `${baseUrl}/v1/${resource}` : `${baseUrl}/k8s/clusters/${cluster}/v1/${resource}` if (paginationStyle === "k8s") { listWithK8sStylePagination(url, cookies, filters) } else if (paginationStyle === "steve") { listWithSteveStylePagination(url, cookies, filters) } else { fail("Invalid PAGINATION_STYLE value: " + paginationStyle) } } else if (api === "norman") { const url = `${baseUrl}/v3/${resource}` listWithNormanStylePagination(url, cookies) } else { fail("Invalid API value: " + api) } } function listWithK8sStylePagination(url, cookies, filters) { let revision = null let continueToken = null while (true) { const fullUrl = url + "?limit=" + pageSize + (filters != "" && filters != "" ? "&" + filters : "") + (revision != null ? "&revision=" + revision : "") + (continueToken != null ? "&continue=" + continueToken : "") + urlSuffix const res = http.get(fullUrl, { cookies: cookies }) const criteria = {} criteria[`listing ${resource} from cluster ${cluster} (steve with k8s style pagination) succeeds`] = (r) => r.status === 200 criteria[`no slow pagination errors (410 Gone) detected`] = (r) => r.status !== 410 check(res, criteria) try { const body = JSON.parse(res.body) if (body === undefined || body.continue === undefined || firstPageOnly) { break } if (revision == null) { revision = body.revision } continueToken = body.continue } catch (e) { if (e instanceof SyntaxError) { fail("Response body does not parse as JSON: " + res.body) } throw e } pause() } } function listWithSteveStylePagination(url, cookies, filters) { let i = 1 let revision = null while (true) { const fullUrl = url + "?pagesize=" + pageSize + "&page=" + i + (filters != "" && filters != "" ? "&" + filters : "") + (revision != null ? "&revision=" + revision : "") + urlSuffix const res = http.get(fullUrl, { cookies: cookies }) const criteria = {} criteria[`listing ${resource} from cluster ${cluster} (steve style pagination) succeeds`] = (r) => r.status === 200 criteria[`no slow pagination errors (410 Gone) detected`] = (r) => r.status !== 410 check(res, criteria) try { const body = JSON.parse(res.body) if (body === undefined || body.data === undefined || body.data.length === 0 || firstPageOnly) { break } if (revision == null) { revision = body.revision } i = i + 1 } catch (e) { if (e instanceof SyntaxError) { fail("Response body does not parse as JSON: " + res.body) } throw e } pause() } } function listWithNormanStylePagination(url, cookies) { let nextUrl = url + "?limit=" + pageSize while (true) { const res = http.get(nextUrl, { cookies: cookies }) const criteria = {} criteria[`listing ${resource} from cluster ${cluster} (norman style pagination) succeeds`] = (r) => r.status === 200 criteria[`no slow pagination errors (410 Gone) detected`] = (r) => r.status !== 410 check(res, criteria) try { const body = JSON.parse(res.body) if (body === undefined || body.pagination === undefined || body.pagination.partial === undefined || body.pagination.next === undefined) { break } nextUrl = body.pagination.next } catch (e) { if (e instanceof SyntaxError) { fail("Response body does not parse as JSON: " + res.body) } throw e } pause() } }