Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: test execution crd #4206

Merged
merged 23 commits into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 80 additions & 2 deletions api/v1/testkube.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,7 @@ paths:
- $ref: "#/components/parameters/ID"
- $ref: "#/components/parameters/Namespace"
- $ref: "#/components/parameters/LastNDays"
- $ref: "#/components/parameters/TestSuiteExecutionName"
tags:
- api
- test-suites
Expand Down Expand Up @@ -1131,7 +1132,7 @@ paths:
- $ref: "#/components/parameters/Namespace"
- $ref: "#/components/parameters/Selector"
- $ref: "#/components/parameters/ExecutionSelector"
- $ref: "#/components/parameters/ConcurrencyLevel"
- $ref: "#/components/parameters/ConcurrencyLevel"
tags:
- api
- tests
Expand Down Expand Up @@ -1847,6 +1848,7 @@ paths:
parameters:
- $ref: "#/components/parameters/ID"
- $ref: "#/components/parameters/Namespace"
- $ref: "#/components/parameters/TestExecutionName"
tags:
- api
- tests
Expand Down Expand Up @@ -3328,6 +3330,35 @@ components:
runningContext:
$ref: "#/components/schemas/RunningContext"
description: running context for the test suite execution
testSuiteExecutionName:
type: string
description: test suite execution name started the test suite execution

TestSuiteExecutionCR:
type: object
required:
- testSuite
properties:
testSuite:
$ref: "#/components/schemas/ObjectRef"
description: test suite name and namespace
executionRequest:
$ref: "#/components/schemas/TestSuiteExecutionRequest"
description: test suite execution request parameters
status:
$ref: "#/components/schemas/TestSuiteExecutionStatusCR"
description: test suite execution status

TestSuiteExecutionStatusCR:
type: object
description: test suite execution status
properties:
latestExecution:
$ref: "#/components/schemas/TestSuiteExecution"
generation:
type: integer
format: int64
description: test suite execution generation

TestSuiteExecutionStatus:
type: string
Expand Down Expand Up @@ -3556,6 +3587,32 @@ components:
status:
$ref: "#/components/schemas/TestStatus"

TestExecutionCR:
type: object
required:
- test
properties:
test:
$ref: "#/components/schemas/ObjectRef"
description: test name and namespace
executionRequest:
$ref: "#/components/schemas/ExecutionRequest"
description: test execution request parameters
status:
$ref: "#/components/schemas/TestExecutionStatusCR"
description: test execution status

TestExecutionStatusCR:
type: object
description: test execution status
properties:
latestExecution:
$ref: "#/components/schemas/Execution"
generation:
type: integer
format: int64
description: test execution generation

TestContent:
type: object
properties:
Expand Down Expand Up @@ -3857,7 +3914,10 @@ components:
containerShell:
type: string
description: shell used in container executor
example: "/bin/sh"
example: "/bin/sh"
testExecutionName:
type: string
description: test execution name started the test execution

Artifact:
type: object
Expand Down Expand Up @@ -4379,6 +4439,9 @@ components:
runningContext:
$ref: "#/components/schemas/RunningContext"
description: running context for the test execution
testExecutionName:
type: string
description: test execution name started the test execution

ExecutionUpdateRequest:
description: test execution request update body
Expand Down Expand Up @@ -4456,6 +4519,9 @@ components:
format: int32
description: number of tests run in parallel
example: 10
testSuiteExecutionName:
type: string
description: test suite execution name started the test suite execution

TestSuiteExecutionUpdateRequest:
description: test suite execution update request body
Expand Down Expand Up @@ -5374,6 +5440,18 @@ components:
schema:
type: integer
default: 10
TestExecutionName:
in: query
name: testExecutionName
schema:
type: string
description: test execution name stated the test execution
TestSuiteExecutionName:
in: query
name: testSuiteExecutionName
schema:
type: string
description: test suite execution name stated the test suite execution
Namespace:
in: query
name: namespace
Expand Down
7 changes: 7 additions & 0 deletions cmd/api-server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ import (
kubeclient "github.com/kubeshop/testkube-operator/client"
executorsclientv1 "github.com/kubeshop/testkube-operator/client/executors/v1"
scriptsclient "github.com/kubeshop/testkube-operator/client/scripts/v2"
testexecutionsclientv1 "github.com/kubeshop/testkube-operator/client/testexecutions/v1"
testsclientv1 "github.com/kubeshop/testkube-operator/client/tests"
testsclientv3 "github.com/kubeshop/testkube-operator/client/tests/v3"
testsourcesclientv1 "github.com/kubeshop/testkube-operator/client/testsources/v1"
testsuiteexecutionsclientv1 "github.com/kubeshop/testkube-operator/client/testsuiteexecutions/v1"
testsuitesclientv2 "github.com/kubeshop/testkube-operator/client/testsuites/v2"
testsuitesclientv3 "github.com/kubeshop/testkube-operator/client/testsuites/v3"
apiv1 "github.com/kubeshop/testkube/internal/app/api/v1"
Expand Down Expand Up @@ -159,6 +161,8 @@ func main() {
testsuitesClientV2 := testsuitesclientv2.NewClient(kubeClient, cfg.TestkubeNamespace)
testsuitesClientV3 := testsuitesclientv3.NewClient(kubeClient, cfg.TestkubeNamespace)
testsourcesClient := testsourcesclientv1.NewClient(kubeClient, cfg.TestkubeNamespace)
testExecutionsClient := testexecutionsclientv1.NewClient(kubeClient, cfg.TestkubeNamespace)
testsuiteExecutionsClient := testsuiteexecutionsclientv1.NewClient(kubeClient, cfg.TestkubeNamespace)

clientset, err := k8sclient.ConnectToK8s()
if err != nil {
Expand Down Expand Up @@ -316,6 +320,7 @@ func main() {
configMapConfig,
testsClientV3,
clientset,
testExecutionsClient,
cfg.TestkubeRegistry,
cfg.TestkubePodStartTimeout,
clusterId,
Expand All @@ -340,6 +345,7 @@ func main() {
configMapConfig,
executorsClient,
testsClientV3,
testExecutionsClient,
cfg.TestkubeRegistry,
cfg.TestkubePodStartTimeout,
clusterId,
Expand All @@ -363,6 +369,7 @@ func main() {
log.DefaultLogger,
configMapConfig,
configMapClient,
testsuiteExecutionsClient,
)

slackLoader, err := newSlackLoader(cfg)
Expand Down
16 changes: 9 additions & 7 deletions docs/docs/articles/crds.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ kubectl get crds -n testkube

```sh title="Expected output:"
NAME CREATED AT
executors.executor.testkube.io 2023-06-15T14:49:11Z
scripts.tests.testkube.io 2023-06-15T14:49:11Z
tests.tests.testkube.io 2023-06-15T14:49:11Z
testsources.tests.testkube.io 2023-06-15T14:49:11Z
testsuites.tests.testkube.io 2023-06-15T14:49:11Z
testtriggers.tests.testkube.io 2023-06-15T14:49:11Z
webhooks.executor.testkube.io 2023-06-15T14:49:11Z
executors.executor.testkube.io 2023-06-15T14:49:11Z
scripts.tests.testkube.io 2023-06-15T14:49:11Z
testexecutions.tests.testkube.io 2023-06-15T14:49:11Z
tests.tests.testkube.io 2023-06-15T14:49:11Z
testsources.tests.testkube.io 2023-06-15T14:49:11Z
testsuiteexecutions.tests.testkube.io 2023-06-15T14:49:11Z
testsuites.tests.testkube.io 2023-06-15T14:49:11Z
testtriggers.tests.testkube.io 2023-06-15T14:49:11Z
webhooks.executor.testkube.io 2023-06-15T14:49:11Z
```

To check details on one of the CRDs, use `describe`:
Expand Down
69 changes: 69 additions & 0 deletions docs/docs/articles/test-executions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Test and Test Suite Execution CRDs

Testkube allows you to automatically run tests and test suites by creating or updating Test or Test Suite Execution CRDs.

## What is a Testkube Execution CRDs?
vsukhin marked this conversation as resolved.
Show resolved Hide resolved

In generic terms, an _Execution_ defines a _test_ or _testsuite_ which will be executed when CRD is created or updated. For example, we could define a _TestExecution_ which _runs_ a _Test_ when a _TestExecution_ gets _modified_.

#### Selecting Resource

Names are used when we want to select a specific resource.

```yaml
test:
name: Testkube test name
```

or

```yaml
testSuite:
name: Testkube test suite name
```

### Execution Request

Execution Request allows to define execution parameters for each specific resource.
vsukhin marked this conversation as resolved.
Show resolved Hide resolved

## Example

Here are examples for a **Test Execution** *testexecution-example* which runs the **Test** *test-example*
when a **Test Execution** is created or updated and a **Test Suite Execution** *testsuiteexecution-example*
which runs the **Test Suite** *testsuite-example * when a **Test Suite Execution** is created or updated.

```yaml
apiVersion: tests.testkube.io/v1
kind: TestExecution
metadata:
name: testexecution-example
spec:
test:
name: test-example
executionRequest:
variables:
VAR_TEST:
name: VAR_TEST
value: "ANY"
type: basic
```

```yaml
apiVersion: tests.testkube.io/v1
kind: TestSuiteExecution
metadata:
name: testsuiteexecution-example
spec:
testSuite:
name: testsuite-example
executionRequest:
variables:
VAR_TEST:
name: VAR_TEST
value: "ANY"
type: basic
```

## Architecture

Testkube uses Kubernets Operator to reconcile Test and Test Suite Execution CRDs state and run corresponding test and test suite when resource generation is changed.
vsukhin marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 4 additions & 0 deletions docs/redirects.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ const redirects = [
from: "/concepts/test-sources",
to: "/articles/test-sources",
},
{
from: "/concepts/test-executions",
to: "/articles/test-executions",
},
{
from: [
"/guides/going-to-production/exposing-testkube/overview",
Expand Down
1 change: 1 addition & 0 deletions docs/sidebars.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const sidebars = {
"articles/test-triggers",
"articles/webhooks",
"articles/test-sources",
"articles/test-executions",
],
},
{
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ require (
github.com/gorilla/websocket v1.5.0
github.com/joshdk/go-junit v1.0.0
github.com/kelseyhightower/envconfig v1.4.0
github.com/kubeshop/testkube-operator v1.10.8-0.20230706105320-8815bd839764
github.com/kubeshop/testkube-operator v1.10.8-0.20230810132521-4808cf664f7e
github.com/minio/minio-go/v7 v7.0.47
github.com/montanaflynn/stats v0.6.6
github.com/moogar0880/problems v0.1.1
Expand Down Expand Up @@ -78,6 +78,7 @@ require (
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-logr/zapr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.1 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
Expand Down
22 changes: 22 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ github.com/aymanbagabas/go-osc52 v1.2.1 h1:q2sWUyDcozPLcLabEMd+a+7Ea2DitxZVN9hTx
github.com/aymanbagabas/go-osc52 v1.2.1/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
Expand Down Expand Up @@ -208,9 +209,11 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A=
github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8=
Expand Down Expand Up @@ -389,6 +392,20 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kubeshop/testkube-operator v1.10.8-0.20230706105320-8815bd839764 h1:r6JErrRK9Tpzi/JlwAKMeaBlJIkFyZVYtDbd2UA0QP4=
github.com/kubeshop/testkube-operator v1.10.8-0.20230706105320-8815bd839764/go.mod h1:6Rs8MugOzaMcthGzobf6GBlRzbOFiK/GJiuYN6MCfEw=
github.com/kubeshop/testkube-operator v1.10.8-0.20230726181828-3b9d1b2cba71 h1:7HIWhpJiLuXO1+90baDBvBNNE51j0Frz05vbtxMbNKI=
github.com/kubeshop/testkube-operator v1.10.8-0.20230726181828-3b9d1b2cba71/go.mod h1:ELhxGeqtRRihizW+4yd4wT+3QFCdg2JvDANqXkpAWdk=
github.com/kubeshop/testkube-operator v1.10.8-0.20230801130705-c12432823829 h1:FGAFZ/uBxpxwCagWEFZsLkneRDS7CUgWZ/mhMqG7WZQ=
github.com/kubeshop/testkube-operator v1.10.8-0.20230801130705-c12432823829/go.mod h1:ELhxGeqtRRihizW+4yd4wT+3QFCdg2JvDANqXkpAWdk=
github.com/kubeshop/testkube-operator v1.10.8-0.20230801134951-f927998a7367 h1:WMfr/9G6ioyij12K0l6STIC46PlmCuY8X0gs+uZQIRE=
github.com/kubeshop/testkube-operator v1.10.8-0.20230801134951-f927998a7367/go.mod h1:ELhxGeqtRRihizW+4yd4wT+3QFCdg2JvDANqXkpAWdk=
github.com/kubeshop/testkube-operator v1.10.8-0.20230803134239-5e8e729b0cd2 h1:utq0ZU34uUFlS7X7y7ZFyxsSxtIptLSdjaFDUTKUtxA=
github.com/kubeshop/testkube-operator v1.10.8-0.20230803134239-5e8e729b0cd2/go.mod h1:ELhxGeqtRRihizW+4yd4wT+3QFCdg2JvDANqXkpAWdk=
github.com/kubeshop/testkube-operator v1.10.8-0.20230803181918-bb833ffe3256 h1:PLHBpNNtqxBKdA1Wj5fwELejEPOzZJD8JmiANBQQhKk=
github.com/kubeshop/testkube-operator v1.10.8-0.20230803181918-bb833ffe3256/go.mod h1:ELhxGeqtRRihizW+4yd4wT+3QFCdg2JvDANqXkpAWdk=
github.com/kubeshop/testkube-operator v1.10.8-0.20230809185112-22328f643146 h1:kJ0nbwdMPM0lf9MO7diHJWA3rX9QGDa4nlC4z6nBu1w=
github.com/kubeshop/testkube-operator v1.10.8-0.20230809185112-22328f643146/go.mod h1:ELhxGeqtRRihizW+4yd4wT+3QFCdg2JvDANqXkpAWdk=
github.com/kubeshop/testkube-operator v1.10.8-0.20230810132521-4808cf664f7e h1:Ud63CIX4XIV8BY0HtEHRqn8ls30xDE0Whv8g4oQeLNU=
github.com/kubeshop/testkube-operator v1.10.8-0.20230810132521-4808cf664f7e/go.mod h1:ELhxGeqtRRihizW+4yd4wT+3QFCdg2JvDANqXkpAWdk=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
Expand Down Expand Up @@ -636,11 +653,15 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
Expand Down Expand Up @@ -871,6 +892,7 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
Expand Down
1 change: 1 addition & 0 deletions internal/app/api/v1/executions.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ func (s *TestkubeAPI) ExecuteTestsHandler() fiber.Handler {
}
var results []testkube.Execution
if len(tests) != 0 {
request.TestExecutionName = c.Query("testExecutionName")
concurrencyLevel, err := strconv.Atoi(c.Query("concurrency", strconv.Itoa(scheduler.DefaultConcurrencyLevel)))
if err != nil {
return s.Error(c, http.StatusBadRequest, fmt.Errorf("%s: can't detect concurrency level: %w", errPrefix, err))
Expand Down
Loading
Loading