mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
devenv: Add docker load test which authenticates with API key (#28905)
* Add loadtest which authenticates with API key - Edit load tests to assign the orgId in the default function, as the setup function is only called once for all VUs and therefore the change is not persisted to each VU. - Remove side effect from orgId setup function and explicitly set orgId in setup client * sort semicolons, whitespace
This commit is contained in:
parent
763e958d9d
commit
d29f73b197
@ -53,6 +53,12 @@ Run auth proxy test:
|
||||
$ ./run.sh -c auth_proxy_test
|
||||
```
|
||||
|
||||
Run API key test (option `-k` must be a valid `admin` API key)
|
||||
|
||||
```bash
|
||||
$ ./run.sh -c auth_token_test -k "<api key here>"
|
||||
```
|
||||
|
||||
|
||||
Example output:
|
||||
|
||||
|
@ -12,15 +12,17 @@ const client = createClient(endpoint);
|
||||
export const setup = () => {
|
||||
const basicAuthClient = createBasicAuthClient(endpoint, 'admin', 'admin');
|
||||
const orgId = createTestOrgIfNotExists(basicAuthClient);
|
||||
basicAuthClient.withOrgId(orgId);
|
||||
const datasourceId = createTestdataDatasourceIfNotExists(basicAuthClient);
|
||||
client.withOrgId(orgId);
|
||||
return {
|
||||
orgId: orgId,
|
||||
datasourceId: datasourceId,
|
||||
orgId,
|
||||
datasourceId,
|
||||
};
|
||||
};
|
||||
|
||||
export default data => {
|
||||
client.withOrgId(data.orgId);
|
||||
|
||||
group('annotation by tag test', () => {
|
||||
if (__ITER === 0) {
|
||||
group('user authenticates through ui with username and password', () => {
|
||||
|
82
devenv/docker/loadtest/auth_key_test.js
Normal file
82
devenv/docker/loadtest/auth_key_test.js
Normal file
@ -0,0 +1,82 @@
|
||||
import { sleep, check, group } from 'k6';
|
||||
import { createClient, createBasicAuthClient, createBearerAuthClient } from './modules/client.js';
|
||||
import { createTestOrgIfNotExists, createTestdataDatasourceIfNotExists } from './modules/util.js';
|
||||
|
||||
|
||||
export let options = {
|
||||
noCookiesReset: true,
|
||||
};
|
||||
|
||||
let endpoint = __ENV.URL || 'http://localhost:3000';
|
||||
|
||||
let apiKey = __ENV.API_KEY;
|
||||
if (!apiKey) {
|
||||
throw new Error('This script requires the API key argument -k to be defined.');
|
||||
}
|
||||
const client = createBearerAuthClient(endpoint, apiKey);
|
||||
|
||||
export const setup = () => {
|
||||
const authClient = createBearerAuthClient(endpoint, apiKey);
|
||||
|
||||
const orgId = createTestOrgIfNotExists(authClient);
|
||||
authClient.withOrgId(orgId);
|
||||
const datasourceId = createTestdataDatasourceIfNotExists(authClient);
|
||||
|
||||
return {
|
||||
orgId,
|
||||
datasourceId,
|
||||
};
|
||||
};
|
||||
|
||||
export default data => {
|
||||
client.withOrgId(data.orgId);
|
||||
|
||||
group('API key test', () => {
|
||||
if (__ITER === 0) {
|
||||
group('user can access grafana instance with APIKey', () => {
|
||||
let res = client.datasources.getAll();
|
||||
|
||||
check(res, {
|
||||
'response status is 200': r => r.status === 200,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (__ITER !== 0) {
|
||||
group('batch tsdb requests', () => {
|
||||
const batchCount = 20;
|
||||
const requests = [];
|
||||
const payload = {
|
||||
from: '1547765247624',
|
||||
to: '1547768847624',
|
||||
queries: [
|
||||
{
|
||||
refId: 'A',
|
||||
scenarioId: 'random_walk',
|
||||
intervalMs: 10000,
|
||||
maxDataPoints: 433,
|
||||
datasourceId: data.datasourceId,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
requests.push({ method: 'GET', url: '/api/annotations?dashboardId=2074&from=1548078832772&to=1548082432772' });
|
||||
|
||||
for (let n = 0; n < batchCount; n++) {
|
||||
requests.push({ method: 'POST', url: '/api/tsdb/query', body: payload });
|
||||
}
|
||||
|
||||
let responses = client.batch(requests);
|
||||
for (let n = 0; n < batchCount; n++) {
|
||||
check(responses[n], {
|
||||
'response status is 200': r => r.status === 200,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
sleep(5);
|
||||
};
|
||||
|
||||
export const teardown = data => {};
|
@ -13,15 +13,17 @@ const client = createClient(endpoint);
|
||||
export const setup = () => {
|
||||
const basicAuthClient = createBasicAuthClient(endpoint, 'admin', 'admin');
|
||||
const orgId = createTestOrgIfNotExists(basicAuthClient);
|
||||
basicAuthClient.withOrgId(orgId);
|
||||
const datasourceId = createTestdataDatasourceIfNotExists(basicAuthClient);
|
||||
client.withOrgId(orgId);
|
||||
return {
|
||||
orgId: orgId,
|
||||
datasourceId: datasourceId,
|
||||
orgId,
|
||||
datasourceId,
|
||||
};
|
||||
};
|
||||
|
||||
export default data => {
|
||||
client.withOrgId(data.orgId);
|
||||
|
||||
group(`user auth token slow test (queries between 1 and ${slowQuery} seconds)`, () => {
|
||||
if (__ITER === 0) {
|
||||
group('user authenticates through ui with username and password', () => {
|
||||
|
@ -12,15 +12,18 @@ const client = createClient(endpoint);
|
||||
export const setup = () => {
|
||||
const basicAuthClient = createBasicAuthClient(endpoint, 'admin', 'admin');
|
||||
const orgId = createTestOrgIfNotExists(basicAuthClient);
|
||||
basicAuthClient.withOrgId(orgId);
|
||||
const datasourceId = createTestdataDatasourceIfNotExists(basicAuthClient);
|
||||
client.withOrgId(orgId);
|
||||
|
||||
return {
|
||||
orgId: orgId,
|
||||
datasourceId: datasourceId,
|
||||
orgId,
|
||||
datasourceId,
|
||||
};
|
||||
};
|
||||
|
||||
export default data => {
|
||||
client.withOrgId(data.orgId);
|
||||
|
||||
group('user auth token test', () => {
|
||||
if (__ITER === 0) {
|
||||
group('user authenticates through ui with username and password', () => {
|
||||
|
@ -17,6 +17,10 @@ export const DatasourcesEndpoint = class DatasourcesEndpoint {
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
getAll() {
|
||||
return this.httpClient.get('/datasources');
|
||||
}
|
||||
|
||||
getById(id) {
|
||||
return this.httpClient.get(`/datasources/${id}`);
|
||||
}
|
||||
@ -177,6 +181,25 @@ export class BasicAuthClient extends BaseClient {
|
||||
}
|
||||
}
|
||||
|
||||
export class BearerAuthClient extends BaseClient {
|
||||
constructor(url, subUrl, token) {
|
||||
super(url, subUrl);
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
withUrl(subUrl) {
|
||||
let c = new BearerAuthClient(this.url, subUrl, this.token);
|
||||
c.onBeforeRequest = this.onBeforeRequest;
|
||||
return c;
|
||||
}
|
||||
|
||||
beforeRequest(params) {
|
||||
params = params || {};
|
||||
params.headers = params.headers || {};
|
||||
params.headers['Authorization'] = `Bearer ${this.token}`;
|
||||
}
|
||||
}
|
||||
|
||||
export const createClient = url => {
|
||||
return new GrafanaClient(new BaseClient(url, ''));
|
||||
};
|
||||
@ -184,3 +207,7 @@ export const createClient = url => {
|
||||
export const createBasicAuthClient = (url, username, password) => {
|
||||
return new GrafanaClient(new BasicAuthClient(url, '', username, password));
|
||||
};
|
||||
|
||||
export const createBearerAuthClient = (url, token) => {
|
||||
return new GrafanaClient(new BearerAuthClient(url, '', token));
|
||||
}
|
||||
|
@ -1,20 +1,26 @@
|
||||
export const createTestOrgIfNotExists = client => {
|
||||
let orgId = 0;
|
||||
|
||||
let res = client.orgs.getByName('k6');
|
||||
if (res.status === 404) {
|
||||
res = client.orgs.create('k6');
|
||||
if (res.status !== 200) {
|
||||
throw new Error('Expected 200 response status when creating org');
|
||||
}
|
||||
orgId = res.json().orgId;
|
||||
} else {
|
||||
orgId = res.json().id;
|
||||
return res.json().orgId;
|
||||
}
|
||||
|
||||
client.withOrgId(orgId);
|
||||
return orgId;
|
||||
// This can happen e.g. in Hosted Grafana instances, where even admins
|
||||
// cannot see organisations
|
||||
if (res.status !== 200) {
|
||||
console.info(`unable to get orgs from instance, continuing with default orgId ${orgId}`);
|
||||
return orgId;
|
||||
}
|
||||
|
||||
return res.json().id;
|
||||
};
|
||||
|
||||
|
||||
export const createTestdataDatasourceIfNotExists = client => {
|
||||
const payload = {
|
||||
access: 'proxy',
|
||||
@ -26,9 +32,10 @@ export const createTestdataDatasourceIfNotExists = client => {
|
||||
let res = client.datasources.getByName(payload.name);
|
||||
if (res.status === 404) {
|
||||
res = client.datasources.create(payload);
|
||||
if (res.status !== 200) {
|
||||
throw new Error('Expected 200 response status when creating datasource');
|
||||
}
|
||||
}
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw new Error(`expected 200 response status when creating datasource, got ${res.status}`);
|
||||
}
|
||||
|
||||
return res.json().id;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
PWD=$(pwd)
|
||||
|
||||
@ -9,10 +9,11 @@ run() {
|
||||
testcase='auth_token_test'
|
||||
slowQuery=''
|
||||
out=''
|
||||
apiKey=''
|
||||
|
||||
while getopts ":d:u:v:c:s:o:" o; do
|
||||
while getopts ":d:u:v:c:s:o:k:" o; do
|
||||
case "${o}" in
|
||||
d)
|
||||
d)
|
||||
duration=${OPTARG}
|
||||
;;
|
||||
u)
|
||||
@ -27,14 +28,18 @@ run() {
|
||||
s)
|
||||
slowQuery=${OPTARG}
|
||||
;;
|
||||
o) out=${OPTARG}
|
||||
o)
|
||||
out=${OPTARG}
|
||||
;;
|
||||
k)
|
||||
apiKey=${OPTARG}
|
||||
;;
|
||||
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
docker run -t --network=host -v $PWD:/src -e URL=$url -e SLOW_QUERY=$slowQuery -e K6_OUT=$out --rm -i loadimpact/k6:master run --vus $vus --duration $duration src/$testcase.js
|
||||
docker run -t --network=host -v $PWD:/src -e URL=$url -e SLOW_QUERY=$slowQuery -e K6_OUT=$out -e API_KEY=$apiKey --rm -i loadimpact/k6:master run --vus $vus --duration $duration src/$testcase.js
|
||||
}
|
||||
|
||||
run "$@"
|
||||
|
Loading…
Reference in New Issue
Block a user