Compare commits
39 Commits
imports-fo
...
benchmarks
Author | SHA1 | Date | |
---|---|---|---|
cde4e395e9 | |||
d19c692f81 | |||
d5d2be5672 | |||
8597db59f5 | |||
74fb9492bc | |||
defbafb55e | |||
e2ed7391bc | |||
8dcd0dcaa9 | |||
18eee1b722 | |||
d0f6c815c3 | |||
b13eba3b0a | |||
77fe4e9fe2 | |||
71fe8b4fb3 | |||
b14cb832b2 | |||
24b5296d88 | |||
41b7e50bc6 | |||
6b750d7c59 | |||
d268c28934 | |||
688404b6a5 | |||
cbd2425a5f | |||
877c264d59 | |||
2575b540fa | |||
0e0b76a62e | |||
6d625fd1d7 | |||
bd0630e300 | |||
ffb7d44024 | |||
7589b11f98 | |||
ad21dfa2bc | |||
95692f5a7c | |||
1f4ed1defa | |||
334b183465 | |||
1f789dd4c5 | |||
057e5747c9 | |||
8717a3aaab | |||
527173236a | |||
3e6eb6f248 | |||
6babf0f1c4 | |||
ca7cc30504 | |||
a7cb808cad |
7
.gitignore
vendored
7
.gitignore
vendored
@ -209,3 +209,10 @@ source_docs/
|
|||||||
|
|
||||||
### Golang ###
|
### Golang ###
|
||||||
/vendor/
|
/vendor/
|
||||||
|
|
||||||
|
### Benchmark ###
|
||||||
|
tests/benchmark/k6
|
||||||
|
tests/benchmark/prometheus
|
||||||
|
tests/benchmark/**/*.json
|
||||||
|
tests/benchmark/**/*.ndjson
|
||||||
|
tests/benchmark/**/*.html
|
||||||
|
17
Makefile
17
Makefile
@ -278,3 +278,20 @@ ci-bandit: ci--meta-debug
|
|||||||
|
|
||||||
ci-pending-migrations: ci--meta-debug
|
ci-pending-migrations: ci--meta-debug
|
||||||
ak makemigrations --check
|
ak makemigrations --check
|
||||||
|
|
||||||
|
#########################
|
||||||
|
## Benchmark
|
||||||
|
#########################
|
||||||
|
|
||||||
|
benchmark-fixtures-create:
|
||||||
|
tests/benchmark/fixtures.py create
|
||||||
|
|
||||||
|
benchmark-run:
|
||||||
|
docker compose -f tests/benchmark/docker-compose.yml up -d
|
||||||
|
sleep 5
|
||||||
|
tests/benchmark/run.sh
|
||||||
|
|
||||||
|
benchmark-fixtures-delete:
|
||||||
|
tests/benchmark/fixtures.py delete
|
||||||
|
|
||||||
|
benchmark: benchmark-fixtures-create benchmark-run benchmark-fixtures-delete
|
||||||
|
@ -4,6 +4,7 @@ services:
|
|||||||
postgresql:
|
postgresql:
|
||||||
container_name: postgres
|
container_name: postgres
|
||||||
image: docker.io/library/postgres:16
|
image: docker.io/library/postgres:16
|
||||||
|
command: "-c max_connections=500"
|
||||||
volumes:
|
volumes:
|
||||||
- db-data:/var/lib/postgresql/data
|
- db-data:/var/lib/postgresql/data
|
||||||
environment:
|
environment:
|
||||||
|
0
tests/benchmark/__init__.py
Normal file
0
tests/benchmark/__init__.py
Normal file
30
tests/benchmark/docker-compose.yml
Normal file
30
tests/benchmark/docker-compose.yml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
services:
|
||||||
|
prometheus:
|
||||||
|
image: quay.io/prometheus/prometheus:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
command:
|
||||||
|
- --enable-feature=native-histograms
|
||||||
|
- --web.enable-remote-write-receiver
|
||||||
|
- --config.file=/etc/prometheus/prometheus.yml
|
||||||
|
- --storage.tsdb.path=/prometheus
|
||||||
|
- --web.console.libraries=/usr/share/prometheus/console_libraries
|
||||||
|
- --web.console.templates=/usr/share/prometheus/consoles
|
||||||
|
ports:
|
||||||
|
- 127.0.0.1:9090:9090
|
||||||
|
volumes:
|
||||||
|
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
||||||
|
- ./prometheus:/prometheus
|
||||||
|
user: root
|
||||||
|
|
||||||
|
grafana:
|
||||||
|
image: grafana/grafana:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
GF_AUTH_ANONYMOUS_ENABLED: "true"
|
||||||
|
GF_AUTH_ANONYMOUS_ORG_ROLE: Admin
|
||||||
|
ports:
|
||||||
|
- 127.0.0.1:3000:3000
|
||||||
|
volumes:
|
||||||
|
- ./grafana/provisioning:/etc/grafana/provisioning:ro
|
||||||
|
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro
|
79
tests/benchmark/event_list.js
Normal file
79
tests/benchmark/event_list.js
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import exec from "k6/execution";
|
||||||
|
import http from "k6/http";
|
||||||
|
import { check } from "k6";
|
||||||
|
|
||||||
|
const host = __ENV.BENCH_HOST ? __ENV.BENCH_HOST : "localhost";
|
||||||
|
const VUs = __ENV.VUS ? __ENV.VUS : 8;
|
||||||
|
|
||||||
|
export const options = {
|
||||||
|
discardResponseBodies: true,
|
||||||
|
scenarios: Object.fromEntries(
|
||||||
|
[
|
||||||
|
// Number of events, page size
|
||||||
|
[1000, 100],
|
||||||
|
[10000, 20],
|
||||||
|
[10000, 100],
|
||||||
|
[100000, 100],
|
||||||
|
[1000000, 100],
|
||||||
|
].map((obj, i) => [
|
||||||
|
`${obj[0]}_${obj[1]}`,
|
||||||
|
{
|
||||||
|
executor: "constant-vus",
|
||||||
|
vus: VUs,
|
||||||
|
duration: "150s",
|
||||||
|
startTime: `${165 * i}s`,
|
||||||
|
env: {
|
||||||
|
EVENT_COUNT: `${obj[0]}`,
|
||||||
|
PAGE_SIZE: `${obj[1]}`,
|
||||||
|
},
|
||||||
|
tags: {
|
||||||
|
testid: `event_list_${obj[0]}_${obj[1]}`,
|
||||||
|
event_count: `${obj[0]}`,
|
||||||
|
page_size: `${obj[1]}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
const event_count = Number(__ENV.EVENT_COUNT);
|
||||||
|
const domain = `event-list-${event_count}.${host}:9000`;
|
||||||
|
const page_size = Number(__ENV.PAGE_SIZE);
|
||||||
|
const pages = Math.round(event_count / page_size);
|
||||||
|
const params = {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer akadmin",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "*/*",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pages <= 10) {
|
||||||
|
for (let page = 1; page <= pages; page++) {
|
||||||
|
let res = http.get(
|
||||||
|
http.url`http://${domain}/api/v3/events/events/?page=${page}&page_size=${page_size}`,
|
||||||
|
params,
|
||||||
|
);
|
||||||
|
check(res, {
|
||||||
|
"status is 200": (res) => res.status === 200,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let requests = [];
|
||||||
|
for (let page = 1; page <= pages; page++) {
|
||||||
|
requests.push([
|
||||||
|
"GET",
|
||||||
|
http.url`http://${domain}/api/v3/events/events/?page=${page}&page_size=${page_size}`,
|
||||||
|
null,
|
||||||
|
params,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
const responses = http.batch(requests);
|
||||||
|
for (let page = 1; page <= pages; page++) {
|
||||||
|
check(responses[page - 1], {
|
||||||
|
"status is 200": (res) => res.status === 200,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
345
tests/benchmark/fixtures.py
Executable file
345
tests/benchmark/fixtures.py
Executable file
@ -0,0 +1,345 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import random
|
||||||
|
import sys
|
||||||
|
from collections.abc import Iterable
|
||||||
|
from multiprocessing import Process
|
||||||
|
from os import environ
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
|
import django
|
||||||
|
|
||||||
|
environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings")
|
||||||
|
environ.setdefault("AUTHENTIK_BOOTSTRAP_PASSWORD", "akadmin")
|
||||||
|
environ.setdefault("AUTHENTIK_BOOTSTRAP_TOKEN", "akadmin")
|
||||||
|
environ.setdefault("AUTHENTIK_BOOTSTRAP_EMAIL", "akadmin@authentik.test")
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
from authentik.core.models import Application, Group, User
|
||||||
|
from authentik.crypto.models import CertificateKeyPair
|
||||||
|
from authentik.events.models import Event, EventAction
|
||||||
|
from authentik.flows.models import Flow
|
||||||
|
from authentik.policies.expression.models import ExpressionPolicy
|
||||||
|
from authentik.policies.models import PolicyBinding
|
||||||
|
from authentik.providers.oauth2.models import OAuth2Provider
|
||||||
|
from authentik.stages.authenticator_static.models import StaticToken
|
||||||
|
from authentik.tenants.models import Domain, Tenant
|
||||||
|
|
||||||
|
settings.CELERY["task_always_eager"] = True
|
||||||
|
|
||||||
|
host = environ.get("BENCH_HOST", "localhost")
|
||||||
|
|
||||||
|
|
||||||
|
class TestSuite:
|
||||||
|
TEST_NAME: str
|
||||||
|
TEST_CASES: Iterable[Iterable[int | str | bool]]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_testcases(cls):
|
||||||
|
return [cls(params) for params in cls.TEST_CASES]
|
||||||
|
|
||||||
|
def __init__(self, params: Iterable[int | str | bool]):
|
||||||
|
self.params = params
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return (
|
||||||
|
"-".join([self.TEST_NAME] + [str(param) for param in self.params])
|
||||||
|
.replace("_", "-")
|
||||||
|
.lower()
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def schema_name(self):
|
||||||
|
return f"t_{str(self).replace('-', '_')}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def domain_name(self):
|
||||||
|
return f"{str(self)}.{host}"
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
created = False
|
||||||
|
t = Tenant.objects.filter(schema_name=self.schema_name).first()
|
||||||
|
if not t:
|
||||||
|
created = True
|
||||||
|
t = Tenant.objects.create(schema_name=self.schema_name, name=uuid4())
|
||||||
|
Domain.objects.get_or_create(tenant=t, domain=self.domain_name)
|
||||||
|
if created:
|
||||||
|
with t:
|
||||||
|
self.create_data(*self.params)
|
||||||
|
|
||||||
|
def create_data(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
Tenant.objects.filter(schema_name=self.schema_name).delete()
|
||||||
|
|
||||||
|
|
||||||
|
class UserList(TestSuite):
|
||||||
|
TEST_NAME = "user-list"
|
||||||
|
TEST_CASES = [
|
||||||
|
(1000, 0, 0),
|
||||||
|
(10000, 0, 0),
|
||||||
|
(1000, 3, 0),
|
||||||
|
(10000, 3, 0),
|
||||||
|
(1000, 20, 0),
|
||||||
|
(10000, 20, 0),
|
||||||
|
(1000, 20, 3),
|
||||||
|
(10000, 20, 3),
|
||||||
|
]
|
||||||
|
|
||||||
|
def create_data(self, user_count: int, groups_per_user: int, parents_per_group: int):
|
||||||
|
Group.objects.bulk_create([Group(name=uuid4()) for _ in range(groups_per_user * 5)])
|
||||||
|
for group in Group.objects.exclude(name="authentik Admins"):
|
||||||
|
for _ in range(parents_per_group):
|
||||||
|
new_group = Group.objects.create(name=uuid4())
|
||||||
|
group.parent = new_group
|
||||||
|
group.save()
|
||||||
|
group = new_group
|
||||||
|
User.objects.bulk_create(
|
||||||
|
[
|
||||||
|
User(
|
||||||
|
username=uuid4(),
|
||||||
|
name=uuid4(),
|
||||||
|
)
|
||||||
|
for _ in range(user_count)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if groups_per_user:
|
||||||
|
for user in User.objects.exclude_anonymous().exclude(username="akadmin"):
|
||||||
|
user.ak_groups.set(
|
||||||
|
Group.objects.exclude(name="authentik Admins").order_by("?")[:groups_per_user]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class GroupList(TestSuite):
|
||||||
|
TEST_NAME = "group-list"
|
||||||
|
TEST_CASES = [
|
||||||
|
(1000, 0, False),
|
||||||
|
(10000, 0, False),
|
||||||
|
(1000, 1000, False),
|
||||||
|
(1000, 10000, False),
|
||||||
|
(1000, 0, True),
|
||||||
|
(10000, 0, True),
|
||||||
|
]
|
||||||
|
|
||||||
|
def create_data(self, group_count, users_per_group, with_parent):
|
||||||
|
User.objects.bulk_create(
|
||||||
|
[
|
||||||
|
User(
|
||||||
|
username=uuid4(),
|
||||||
|
name=uuid4(),
|
||||||
|
)
|
||||||
|
for _ in range(users_per_group * 5)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if with_parent:
|
||||||
|
parents = Group.objects.bulk_create([Group(name=uuid4()) for _ in range(group_count)])
|
||||||
|
groups = Group.objects.bulk_create(
|
||||||
|
[
|
||||||
|
Group(name=uuid4(), parent=(parents[i] if with_parent else None))
|
||||||
|
for i in range(group_count)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
if users_per_group:
|
||||||
|
for group in groups:
|
||||||
|
group.users.set(
|
||||||
|
User.objects.exclude_anonymous()
|
||||||
|
.exclude(username="akadmin")
|
||||||
|
.order_by("?")[:users_per_group]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Login(TestSuite):
|
||||||
|
TEST_NAME = "login"
|
||||||
|
TEST_CASES = [
|
||||||
|
("no-mfa",),
|
||||||
|
("with-mfa",),
|
||||||
|
]
|
||||||
|
|
||||||
|
def create_data(self, mfa: str):
|
||||||
|
user = User(username="test", name=uuid4())
|
||||||
|
user.set_password("verySecurePassword")
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
if mfa == "with-mfa":
|
||||||
|
device = user.staticdevice_set.create()
|
||||||
|
# Multiple token with same token for all the iterations in the test
|
||||||
|
device.token_set.bulk_create(
|
||||||
|
[StaticToken(device=device, token=f"staticToken") for _ in range(1_000_000)]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ProviderOauth2(TestSuite):
|
||||||
|
TEST_NAME = "provider-oauth2"
|
||||||
|
TEST_CASES = [
|
||||||
|
(2, 50, 2),
|
||||||
|
(0, 0, 0),
|
||||||
|
(10, 0, 0),
|
||||||
|
(100, 0, 0),
|
||||||
|
(0, 10, 0),
|
||||||
|
(0, 100, 0),
|
||||||
|
(0, 0, 10),
|
||||||
|
(0, 0, 100),
|
||||||
|
(10, 10, 10),
|
||||||
|
(100, 100, 100),
|
||||||
|
]
|
||||||
|
|
||||||
|
def create_data(
|
||||||
|
self, user_policies_count: int, group_policies_count: int, expression_policies_count: int
|
||||||
|
):
|
||||||
|
user = User(username="test", name=uuid4())
|
||||||
|
user.set_password("verySecurePassword")
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
provider = OAuth2Provider.objects.create(
|
||||||
|
name="test",
|
||||||
|
authorization_flow=Flow.objects.get(
|
||||||
|
slug="default-provider-authorization-implicit-consent"
|
||||||
|
),
|
||||||
|
signing_key=CertificateKeyPair.objects.get(name="authentik Self-signed Certificate"),
|
||||||
|
redirect_uris="http://test.localhost",
|
||||||
|
client_id="123456",
|
||||||
|
client_secret="123456",
|
||||||
|
)
|
||||||
|
application = Application.objects.create(slug="test", name="test", provider=provider)
|
||||||
|
|
||||||
|
User.objects.bulk_create(
|
||||||
|
[
|
||||||
|
User(
|
||||||
|
username=uuid4(),
|
||||||
|
name=uuid4(),
|
||||||
|
)
|
||||||
|
for _ in range(user_policies_count)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
PolicyBinding.objects.bulk_create(
|
||||||
|
[
|
||||||
|
PolicyBinding(
|
||||||
|
user=user,
|
||||||
|
target=application,
|
||||||
|
order=random.randint(1, 1_000_000),
|
||||||
|
)
|
||||||
|
for user in User.objects.exclude(username="akadmin").exclude_anonymous()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
Group.objects.bulk_create([Group(name=uuid4()) for _ in range(group_policies_count)])
|
||||||
|
PolicyBinding.objects.bulk_create(
|
||||||
|
[
|
||||||
|
PolicyBinding(
|
||||||
|
group=group,
|
||||||
|
target=application,
|
||||||
|
order=random.randint(1, 1_000_000),
|
||||||
|
)
|
||||||
|
for group in Group.objects.exclude(name="authentik Admins")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
user.ak_groups.set(Group.objects.exclude(name="authentik Admins").order_by("?")[:1])
|
||||||
|
|
||||||
|
[
|
||||||
|
ExpressionPolicy(
|
||||||
|
name=f"test-{uuid4()}",
|
||||||
|
expression="return True",
|
||||||
|
).save()
|
||||||
|
for _ in range(expression_policies_count)
|
||||||
|
]
|
||||||
|
PolicyBinding.objects.bulk_create(
|
||||||
|
[
|
||||||
|
PolicyBinding(
|
||||||
|
policy=policy,
|
||||||
|
target=application,
|
||||||
|
order=random.randint(1, 1_000_000),
|
||||||
|
)
|
||||||
|
for policy in ExpressionPolicy.objects.filter(name__startswith="test-")
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class EventList(TestSuite):
|
||||||
|
TEST_NAME = "event-list"
|
||||||
|
TEST_CASES = [
|
||||||
|
(1_000,),
|
||||||
|
(10_000,),
|
||||||
|
(100_000,),
|
||||||
|
(1_000_000,),
|
||||||
|
]
|
||||||
|
|
||||||
|
def create_data(self, event_count: int):
|
||||||
|
for _ in range(event_count // 1000):
|
||||||
|
Event.objects.bulk_create(
|
||||||
|
[
|
||||||
|
Event(
|
||||||
|
user={
|
||||||
|
"pk": str(uuid4()),
|
||||||
|
"name": str(uuid4()),
|
||||||
|
"username": str(uuid4()),
|
||||||
|
"email": f"{uuid4()}@example.org",
|
||||||
|
},
|
||||||
|
action="custom_benchmark",
|
||||||
|
app="tests_benchmarks",
|
||||||
|
context={
|
||||||
|
str(uuid4()): str(uuid4()),
|
||||||
|
str(uuid4()): str(uuid4()),
|
||||||
|
str(uuid4()): str(uuid4()),
|
||||||
|
str(uuid4()): str(uuid4()),
|
||||||
|
str(uuid4()): str(uuid4()),
|
||||||
|
},
|
||||||
|
client_ip="192.0.2.42",
|
||||||
|
)
|
||||||
|
for _ in range(1000)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class UserGroupCreate(TestSuite):
|
||||||
|
TEST_NAME = "user-group-create"
|
||||||
|
TEST_CASES = [
|
||||||
|
(),
|
||||||
|
]
|
||||||
|
|
||||||
|
def create_data(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def main(action: str, selected_suite: str | None = None):
|
||||||
|
testsuites = TestSuite.__subclasses__()
|
||||||
|
testcases = []
|
||||||
|
for testsuite in testsuites:
|
||||||
|
testcases += testsuite.get_testcases()
|
||||||
|
|
||||||
|
match action:
|
||||||
|
case "create":
|
||||||
|
to_create = []
|
||||||
|
for testcase in testcases:
|
||||||
|
if selected_suite and testcase.TEST_NAME != selected_suite:
|
||||||
|
continue
|
||||||
|
testcase.create()
|
||||||
|
# to_create.append(testcase)
|
||||||
|
# processes = [Process(target=testcase.create) for testcase in to_create]
|
||||||
|
# for p in processes:
|
||||||
|
# p.start()
|
||||||
|
# for p in processes:
|
||||||
|
# p.join()
|
||||||
|
case "list":
|
||||||
|
print(*[testsuite.TEST_NAME for testsuite in testsuites], sep="\n")
|
||||||
|
case "delete":
|
||||||
|
for testcase in testcases:
|
||||||
|
if selected_suite and testcase.TEST_NAME != selected_suite:
|
||||||
|
continue
|
||||||
|
testcase.delete()
|
||||||
|
case _:
|
||||||
|
print("Unknown action. Should be create, list or delete")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
action = "create"
|
||||||
|
else:
|
||||||
|
action = sys.argv[1]
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
testsuite = None
|
||||||
|
else:
|
||||||
|
testsuite = sys.argv[2]
|
||||||
|
main(action, testsuite)
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
apiVersion: 1
|
||||||
|
providers:
|
||||||
|
- name: default
|
||||||
|
folder: k6
|
||||||
|
type: file
|
||||||
|
options:
|
||||||
|
path: /var/lib/grafana/dashboards
|
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
apiVersion: 1
|
||||||
|
datasources:
|
||||||
|
- name: Prometheus
|
||||||
|
type: prometheus
|
||||||
|
access: proxy
|
||||||
|
orgId: 1
|
||||||
|
uid: prometheus
|
||||||
|
url: http://prometheus:9090
|
||||||
|
jsonData:
|
||||||
|
timeInterval: 1s
|
93
tests/benchmark/group_list.js
Normal file
93
tests/benchmark/group_list.js
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import exec from "k6/execution";
|
||||||
|
import http from "k6/http";
|
||||||
|
import { check } from "k6";
|
||||||
|
|
||||||
|
const host = __ENV.BENCH_HOST ? __ENV.BENCH_HOST : "localhost";
|
||||||
|
const VUs = __ENV.VUS ? __ENV.VUS : 8;
|
||||||
|
|
||||||
|
export const options = {
|
||||||
|
discardResponseBodies: true,
|
||||||
|
scenarios: Object.fromEntries(
|
||||||
|
[
|
||||||
|
// Number of groups, number of users per group, with parent, page size, include users
|
||||||
|
[1000, 0, false, 20, false],
|
||||||
|
[10000, 0, false, 20, false],
|
||||||
|
[1000, 0, false, 100, false],
|
||||||
|
[10000, 0, false, 100, false],
|
||||||
|
[1000, 1000, false, 100, false],
|
||||||
|
[1000, 10000, false, 100, false],
|
||||||
|
[1000, 1000, false, 100, true],
|
||||||
|
[1000, 10000, false, 100, true],
|
||||||
|
[1000, 0, true, 100, false],
|
||||||
|
[10000, 0, true, 100, false],
|
||||||
|
].map((obj, i) => [
|
||||||
|
`${obj[0]}_${obj[1]}_${obj[2] ? "with_parents" : "without_parents"}_${obj[3]}_${obj[4] ? "with_users" : "without_users"}`,
|
||||||
|
{
|
||||||
|
executor: "constant-vus",
|
||||||
|
vus: VUs,
|
||||||
|
duration: "150s",
|
||||||
|
startTime: `${165 * i}s`,
|
||||||
|
env: {
|
||||||
|
GROUP_COUNT: `${obj[0]}`,
|
||||||
|
USERS_PER_GROUP: `${obj[1]}`,
|
||||||
|
WITH_PARENTS: `${obj[2]}`,
|
||||||
|
PAGE_SIZE: `${obj[3]}`,
|
||||||
|
WITH_USERS: `${obj[4] ? "true" : "false"}`,
|
||||||
|
},
|
||||||
|
tags: {
|
||||||
|
testid: `group_list_${obj[0]}_${obj[1]}_${obj[2] ? "with_parents" : "without_parents"}_${obj[3]}_${obj[4] ? "with_users" : "without_users"}`,
|
||||||
|
group_count: `${obj[0]}`,
|
||||||
|
users_per_group: `${obj[1]}`,
|
||||||
|
with_parents: `${obj[2]}`,
|
||||||
|
page_size: `${obj[3]}`,
|
||||||
|
with_users: `${obj[4] ? "true" : "false"}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
const group_count = Number(__ENV.GROUP_COUNT);
|
||||||
|
const users_per_group = Number(__ENV.USERS_PER_GROUP);
|
||||||
|
const with_parents = __ENV.WITH_PARENTS;
|
||||||
|
const with_users = __ENV.WITH_USERS;
|
||||||
|
const domain = `group-list-${group_count}-${users_per_group}-${with_parents}.${host}:9000`;
|
||||||
|
const page_size = Number(__ENV.PAGE_SIZE);
|
||||||
|
const pages = Math.round(group_count / page_size);
|
||||||
|
const params = {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer akadmin",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "*/*",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pages <= 10) {
|
||||||
|
for (let page = 1; page <= pages; page++) {
|
||||||
|
let res = http.get(
|
||||||
|
http.url`http://${domain}/api/v3/core/groups/?page=${page}&page_size=${page_size}&include_users=${with_users}`,
|
||||||
|
params,
|
||||||
|
);
|
||||||
|
check(res, {
|
||||||
|
"status is 200": (res) => res.status === 200,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let requests = [];
|
||||||
|
for (let page = 1; page <= pages; page++) {
|
||||||
|
requests.push([
|
||||||
|
"GET",
|
||||||
|
http.url`http://${domain}/api/v3/core/groups/?page=${page}&page_size=${page_size}&include_users=${with_users}`,
|
||||||
|
null,
|
||||||
|
params,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
const responses = http.batch(requests);
|
||||||
|
for (let page = 1; page <= pages; page++) {
|
||||||
|
check(responses[page - 1], {
|
||||||
|
"status is 200": (res) => res.status === 200,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
78
tests/benchmark/login.js
Normal file
78
tests/benchmark/login.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import http from "k6/http";
|
||||||
|
import { check, fail } from "k6";
|
||||||
|
|
||||||
|
const host = __ENV.BENCH_HOST ? __ENV.BENCH_HOST : "localhost";
|
||||||
|
const VUs = __ENV.VUS ? __ENV.VUS : 8;
|
||||||
|
|
||||||
|
export const options = {
|
||||||
|
scenarios: Object.fromEntries(
|
||||||
|
["no-mfa", "with-mfa"].map((obj, i) => [
|
||||||
|
obj,
|
||||||
|
{
|
||||||
|
executor: "constant-vus",
|
||||||
|
vus: VUs,
|
||||||
|
duration: "150s",
|
||||||
|
startTime: `${165 * i}s`,
|
||||||
|
env: {
|
||||||
|
DOMAIN: `login-${obj}`,
|
||||||
|
},
|
||||||
|
tags: {
|
||||||
|
testid: `login-${obj}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
const domain = __ENV.DOMAIN;
|
||||||
|
const url = http.url`http://${domain}.${host}:9000/api/v3/flows/executor/default-authentication-flow/`;
|
||||||
|
const cookieJar = new http.CookieJar();
|
||||||
|
const params = {
|
||||||
|
jar: cookieJar,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "*/*",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let res = http.get(url, params);
|
||||||
|
let i = 0;
|
||||||
|
while (true) {
|
||||||
|
if (i > 10) {
|
||||||
|
fail("Test made more than 10 queries.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
check(res, {
|
||||||
|
"status is 200": (res) => res.status === 200,
|
||||||
|
});
|
||||||
|
if (res.status !== 200) {
|
||||||
|
fail("Endpoint did not return 200.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const component = res.json()["component"];
|
||||||
|
let payload = {};
|
||||||
|
if (component === "ak-stage-identification") {
|
||||||
|
payload = {
|
||||||
|
uid_field: "test",
|
||||||
|
};
|
||||||
|
} else if (component === "ak-stage-password") {
|
||||||
|
payload = {
|
||||||
|
password: "verySecurePassword",
|
||||||
|
};
|
||||||
|
} else if (component === "ak-stage-authenticator-validate") {
|
||||||
|
payload = {
|
||||||
|
code: "staticToken",
|
||||||
|
};
|
||||||
|
} else if (component === "xak-flow-redirect") {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
console.log(`Unknown component type: ${component}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload["component"] = component;
|
||||||
|
res = http.post(url, JSON.stringify(payload), params);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
13
tests/benchmark/prometheus.yml
Normal file
13
tests/benchmark/prometheus.yml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
global:
|
||||||
|
scrape_interval: 15s
|
||||||
|
evaluation_interval: 15s
|
||||||
|
external_labels:
|
||||||
|
cluster: benchmarks
|
||||||
|
prometheus: benchmarks
|
||||||
|
prometheus_replica: "0"
|
||||||
|
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: prometheus
|
||||||
|
static_configs:
|
||||||
|
- targets: ["localhost:9090"]
|
179
tests/benchmark/provider_oauth2.js
Normal file
179
tests/benchmark/provider_oauth2.js
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
import crypto from "k6/crypto";
|
||||||
|
import exec from "k6/execution";
|
||||||
|
import http from "k6/http";
|
||||||
|
import { check, fail } from "k6";
|
||||||
|
|
||||||
|
const host = __ENV.BENCH_HOST ? __ENV.BENCH_HOST : "localhost";
|
||||||
|
const VUs = __ENV.VUS ? __ENV.VUS : 8;
|
||||||
|
|
||||||
|
const testcases = [
|
||||||
|
[2, 50, 2],
|
||||||
|
[0, 0, 0],
|
||||||
|
[10, 0, 0],
|
||||||
|
[100, 0, 0],
|
||||||
|
[0, 10, 0],
|
||||||
|
[0, 100, 0],
|
||||||
|
[0, 0, 10],
|
||||||
|
[0, 0, 100],
|
||||||
|
[10, 10, 10],
|
||||||
|
[100, 100, 100],
|
||||||
|
];
|
||||||
|
|
||||||
|
export const options = {
|
||||||
|
setupTimeout: "10m",
|
||||||
|
scenarios: Object.fromEntries(
|
||||||
|
testcases.map((obj, i) => [
|
||||||
|
`${obj[0]}_${obj[1]}_${obj[2]}`,
|
||||||
|
{
|
||||||
|
executor: "constant-vus",
|
||||||
|
vus: VUs,
|
||||||
|
duration: "150s",
|
||||||
|
startTime: `${165 * i}s`,
|
||||||
|
env: {
|
||||||
|
USER_POLICIES_COUNT: `${obj[0]}`,
|
||||||
|
GROUP_POLICIES_COUNT: `${obj[1]}`,
|
||||||
|
EXPRESSION_POLICIES_COUNT: `${obj[2]}`,
|
||||||
|
},
|
||||||
|
tags: {
|
||||||
|
testid: `provider-oauth2-${obj[0]}_${obj[1]}_${obj[2]}`,
|
||||||
|
user_policies_count: `${obj[0]}`,
|
||||||
|
group_policies_count: `${obj[1]}`,
|
||||||
|
expression_policies_count: `${obj[2]}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export function setup() {
|
||||||
|
let cookies = {};
|
||||||
|
for (let vu = 0; vu < VUs; vu++) {
|
||||||
|
cookies[vu] = {};
|
||||||
|
for (const testcase of testcases) {
|
||||||
|
const user_policies_count = testcase[0];
|
||||||
|
const group_policies_count = testcase[1];
|
||||||
|
const expression_policies_count = testcase[2];
|
||||||
|
const domain = `provider-oauth2-${user_policies_count}-${group_policies_count}-${expression_policies_count}.${host}:9000`;
|
||||||
|
const url = http.url`http://${domain}/api/v3/flows/executor/default-authentication-flow/`;
|
||||||
|
const params = {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "*/*",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
http.cookieJar().clear(`http://${domain}`);
|
||||||
|
let res = http.get(url, params);
|
||||||
|
let i = 0;
|
||||||
|
while (true) {
|
||||||
|
if (i > 10) {
|
||||||
|
fail("Test made more than 10 queries.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
check(res, {
|
||||||
|
"status is 200": (res) => res.status === 200,
|
||||||
|
});
|
||||||
|
if (res.status !== 200) {
|
||||||
|
fail("Endpoint did not return 200.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const component = res.json()["component"];
|
||||||
|
let payload = {};
|
||||||
|
if (component === "ak-stage-identification") {
|
||||||
|
payload = {
|
||||||
|
uid_field: "test",
|
||||||
|
};
|
||||||
|
} else if (component === "ak-stage-password") {
|
||||||
|
payload = {
|
||||||
|
password: "verySecurePassword",
|
||||||
|
};
|
||||||
|
} else if (component === "xak-flow-redirect") {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
fail(`Unknown component type: ${component}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload["component"] = component;
|
||||||
|
res = http.post(url, JSON.stringify(payload), params);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
cookies[vu][domain] = http
|
||||||
|
.cookieJar()
|
||||||
|
.cookiesForURL(`http://${domain}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { cookies };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function (data) {
|
||||||
|
// Restore cookies
|
||||||
|
let jar = http.cookieJar();
|
||||||
|
const vu = exec.vu.idInTest % VUs;
|
||||||
|
Object.keys(data.cookies[vu]).forEach((domain) => {
|
||||||
|
Object.keys(data.cookies[vu][domain]).forEach((key) => {
|
||||||
|
jar.set(`http://${domain}`, key, data.cookies[vu][domain][key][0]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const user_policies_count = Number(__ENV.USER_POLICIES_COUNT);
|
||||||
|
const group_policies_count = Number(__ENV.GROUP_POLICIES_COUNT);
|
||||||
|
const expression_policies_count = Number(__ENV.EXPRESSION_POLICIES_COUNT);
|
||||||
|
const domain = `provider-oauth2-${user_policies_count}-${group_policies_count}-${expression_policies_count}.${host}:9000`;
|
||||||
|
const params = {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "*/*",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const random = (length = 32) => {
|
||||||
|
let chars =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
let str = "";
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
str += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = random(32);
|
||||||
|
const nonce = random(32);
|
||||||
|
const code_verifier = random(64);
|
||||||
|
const code_challenge = crypto.sha256(code_verifier, "base64");
|
||||||
|
const urlParams = {
|
||||||
|
response_type: "code",
|
||||||
|
scope: "openid profile email",
|
||||||
|
client_id: "123456",
|
||||||
|
redirect_uri: "http://test.localhost",
|
||||||
|
state: state,
|
||||||
|
nonce: nonce,
|
||||||
|
code_challenge: code_challenge,
|
||||||
|
code_challenge_method: "S256",
|
||||||
|
};
|
||||||
|
|
||||||
|
let url = http.url`http://${domain}/application/o/authorize/?${Object.entries(
|
||||||
|
urlParams,
|
||||||
|
)
|
||||||
|
.map((kv) => kv.map(encodeURIComponent).join("="))
|
||||||
|
.join("&")}`;
|
||||||
|
let res = http.get(url, params);
|
||||||
|
check(res, {
|
||||||
|
"status is 200": (res) => res.status === 200,
|
||||||
|
});
|
||||||
|
if (res.status !== 200) {
|
||||||
|
fail("Endpoint did not return 200.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
url = http.url`http://${domain}/api/v3/flows/executor/default-provider-authorization-implicit-consent/`;
|
||||||
|
res = http.get(url, params);
|
||||||
|
check(res, {
|
||||||
|
"status is 200": (res) => res.status === 200,
|
||||||
|
"last redirect is present": (res) => res.json()["type"] === "redirect",
|
||||||
|
});
|
||||||
|
if (res.status !== 200) {
|
||||||
|
fail("Endpoint did not return 200.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
32
tests/benchmark/run.sh
Executable file
32
tests/benchmark/run.sh
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BASE_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
|
||||||
|
|
||||||
|
function _k6 {
|
||||||
|
local filename="${1}"
|
||||||
|
|
||||||
|
K6_PROMETHEUS_RW_SERVER_URL=${PROMETHEUS_REMOTE_WRITE_ENDPOINT:-http://localhost:9090/api/v1/write} \
|
||||||
|
K6_PROMETHEUS_RW_TREND_AS_NATIVE_HISTOGRAM=true \
|
||||||
|
K6_PROMETHEUS_RW_PUSH_INTERVAL=1s \
|
||||||
|
k6 run \
|
||||||
|
--out experimental-prometheus-rw \
|
||||||
|
--out "json=${filename%.*}.json" \
|
||||||
|
"${@}"
|
||||||
|
}
|
||||||
|
|
||||||
|
filename=""
|
||||||
|
if [ "${#}" -ge 1 ]; then
|
||||||
|
filename="${1:-}"
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ -f "${filename}" ]; then
|
||||||
|
_k6 "${filename}" "${@}"
|
||||||
|
else
|
||||||
|
find "${BASE_DIR}" -name '*.js' | while read -r f; do
|
||||||
|
_k6 "${f}" "${@}"
|
||||||
|
done
|
||||||
|
fi
|
68
tests/benchmark/user_group_create.js
Normal file
68
tests/benchmark/user_group_create.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import exec from "k6/execution";
|
||||||
|
import http from "k6/http";
|
||||||
|
import { check } from "k6";
|
||||||
|
|
||||||
|
const host = __ENV.BENCH_HOST ? __ENV.BENCH_HOST : "localhost";
|
||||||
|
const VUs = __ENV.VUS ? __ENV.VUS : 8;
|
||||||
|
|
||||||
|
export const options = {
|
||||||
|
vus: VUs,
|
||||||
|
duration: "150s",
|
||||||
|
tags: {
|
||||||
|
testid: `user-group-create`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
const domain = `user-group-create.${host}:9000`;
|
||||||
|
const params = {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer akadmin",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "*/*",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const random = (length = 32) => {
|
||||||
|
let chars =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
let str = "";
|
||||||
|
for (let i = 0; i < length; i++) {
|
||||||
|
str += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
};
|
||||||
|
|
||||||
|
let user_res = http.post(
|
||||||
|
http.url`http://${domain}/api/v3/core/users/`,
|
||||||
|
JSON.stringify({
|
||||||
|
username: random(16),
|
||||||
|
name: random(16),
|
||||||
|
}),
|
||||||
|
params,
|
||||||
|
);
|
||||||
|
check(user_res, {
|
||||||
|
"user status is 201": (res) => res.status === 201,
|
||||||
|
});
|
||||||
|
|
||||||
|
let group_res = http.post(
|
||||||
|
http.url`http://${domain}/api/v3/core/groups/`,
|
||||||
|
JSON.stringify({
|
||||||
|
name: random(16),
|
||||||
|
}),
|
||||||
|
params,
|
||||||
|
);
|
||||||
|
check(group_res, {
|
||||||
|
"group status is 201": (res) => res.status === 201,
|
||||||
|
});
|
||||||
|
|
||||||
|
let user_group_res = http.post(
|
||||||
|
http.url`http://${domain}/api/v3/core/groups/${group_res.json()["pk"]}/add_user/`,
|
||||||
|
JSON.stringify({
|
||||||
|
pk: user_res.json()["pk"],
|
||||||
|
}),
|
||||||
|
params,
|
||||||
|
);
|
||||||
|
check(user_group_res, {
|
||||||
|
"user group status is 204": (res) => res.status === 204,
|
||||||
|
});
|
||||||
|
}
|
99
tests/benchmark/user_list.js
Normal file
99
tests/benchmark/user_list.js
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import exec from "k6/execution";
|
||||||
|
import http from "k6/http";
|
||||||
|
import { check } from "k6";
|
||||||
|
|
||||||
|
const host = __ENV.BENCH_HOST ? __ENV.BENCH_HOST : "localhost";
|
||||||
|
const VUs = __ENV.VUS ? __ENV.VUS : 8;
|
||||||
|
|
||||||
|
export const options = {
|
||||||
|
discardResponseBodies: true,
|
||||||
|
scenarios: Object.fromEntries(
|
||||||
|
[
|
||||||
|
// Number of users, number of groups per user, number of parents per group, page size, with groups
|
||||||
|
[1000, 0, 0, 20, true],
|
||||||
|
[10000, 0, 0, 20, true],
|
||||||
|
[1000, 0, 0, 20, false],
|
||||||
|
[10000, 0, 0, 20, false],
|
||||||
|
[1000, 0, 0, 100, true],
|
||||||
|
[10000, 0, 0, 100, true],
|
||||||
|
[1000, 3, 0, 20, true],
|
||||||
|
[10000, 3, 0, 20, true],
|
||||||
|
[1000, 20, 0, 20, true],
|
||||||
|
[10000, 20, 0, 20, true],
|
||||||
|
[1000, 20, 3, 20, true],
|
||||||
|
[10000, 20, 3, 20, true],
|
||||||
|
[1000, 20, 0, 20, false],
|
||||||
|
[10000, 20, 0, 20, false],
|
||||||
|
[1000, 20, 3, 20, false],
|
||||||
|
[10000, 20, 3, 20, false],
|
||||||
|
].map((obj, i) => [
|
||||||
|
`${obj[0]}_${obj[1]}_${obj[2]}_${obj[3]}_${obj[4] ? "with_groups" : "without_groups"}`,
|
||||||
|
{
|
||||||
|
executor: "constant-vus",
|
||||||
|
vus: VUs,
|
||||||
|
duration: "150s",
|
||||||
|
startTime: `${165 * i}s`,
|
||||||
|
env: {
|
||||||
|
USER_COUNT: `${obj[0]}`,
|
||||||
|
GROUPS_PER_USER: `${obj[1]}`,
|
||||||
|
PARENTS_PER_GROUP: `${obj[2]}`,
|
||||||
|
PAGE_SIZE: `${obj[3]}`,
|
||||||
|
WITH_GROUPS: `${obj[4] ? "true" : "false"}`,
|
||||||
|
},
|
||||||
|
tags: {
|
||||||
|
testid: `user_list_${obj[0]}_${obj[1]}_${obj[2]}_${obj[3]}_${obj[4] ? "with_groups" : "without_groups"}`,
|
||||||
|
user_count: `${obj[0]}`,
|
||||||
|
groups_per_user: `${obj[1]}`,
|
||||||
|
parents_per_group: `${obj[2]}`,
|
||||||
|
page_size: `${obj[3]}`,
|
||||||
|
with_groups: `${obj[4] ? "true" : "false"}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
const user_count = Number(__ENV.USER_COUNT);
|
||||||
|
const groups_per_user = Number(__ENV.GROUPS_PER_USER);
|
||||||
|
const parents_per_group = Number(__ENV.PARENTS_PER_GROUP);
|
||||||
|
const with_groups = __ENV.WITH_GROUPS;
|
||||||
|
const domain = `user-list-${user_count}-${groups_per_user}-${parents_per_group}.${host}:9000`;
|
||||||
|
const page_size = Number(__ENV.PAGE_SIZE);
|
||||||
|
const pages = Math.round(user_count / page_size);
|
||||||
|
const params = {
|
||||||
|
headers: {
|
||||||
|
Authorization: "Bearer akadmin",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "*/*",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pages <= 10) {
|
||||||
|
for (let page = 1; page <= pages; page++) {
|
||||||
|
let res = http.get(
|
||||||
|
http.url`http://${domain}/api/v3/core/users/?page=${page}&page_size=${page_size}&include_groups=${with_groups}`,
|
||||||
|
params,
|
||||||
|
);
|
||||||
|
check(res, {
|
||||||
|
"status is 100": (res) => res.status === 200,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let requests = [];
|
||||||
|
for (let page = 1; page <= pages; page++) {
|
||||||
|
requests.push([
|
||||||
|
"GET",
|
||||||
|
http.url`http://${domain}/api/v3/core/users/?page=${page}&page_size=${page_size}&include_groups=${with_groups}`,
|
||||||
|
null,
|
||||||
|
params,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
const responses = http.batch(requests);
|
||||||
|
for (let page = 1; page <= pages; page++) {
|
||||||
|
check(responses[page - 1], {
|
||||||
|
"status is 200": (res) => res.status === 200,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user