From 7df17c5fa5b1105b6af172223b69e98b91570887 Mon Sep 17 00:00:00 2001 From: sabevzenko Date: Mon, 20 May 2024 11:18:40 +0300 Subject: [PATCH 1/3] pandora scenario: local block docs 7eb87e73be643c6cd89eacda49777b507ce609d4 --- .../unreleased/Added-20240517-144818.yaml | 3 + .../unreleased/Added-20240517-144851.yaml | 3 + .mapping.json | 4 + README.md | 9 +- .../providers/scenario/config/config.go | 1 + .../providers/scenario/grpc/provider.go | 2 +- .../providers/scenario/http/provider.go | 2 +- .../providers/scenario/test/decode_test.go | 9 +- .../scenario/testdata/http_payload.yaml | 9 +- docs/eng/scenario-grpc-generator.md | 27 ++++- docs/eng/scenario-http-generator.md | 30 +++++- docs/eng/scenario/functions.md | 22 ++++ docs/eng/scenario/locals.md | 100 ++++++++++++++++++ docs/rus/scenario-grpc-generator.md | 27 ++++- docs/rus/scenario-http-generator.md | 30 +++++- docs/rus/scenario/functions.md | 21 ++++ docs/rus/scenario/locals.md | 100 ++++++++++++++++++ 17 files changed, 367 insertions(+), 32 deletions(-) create mode 100644 .changes/unreleased/Added-20240517-144818.yaml create mode 100644 .changes/unreleased/Added-20240517-144851.yaml create mode 100644 docs/eng/scenario/locals.md create mode 100644 docs/rus/scenario/locals.md diff --git a/.changes/unreleased/Added-20240517-144818.yaml b/.changes/unreleased/Added-20240517-144818.yaml new file mode 100644 index 000000000..f1b861409 --- /dev/null +++ b/.changes/unreleased/Added-20240517-144818.yaml @@ -0,0 +1,3 @@ +kind: Added +body: scenario config local block in yaml +time: 2024-05-17T14:48:18.485698+02:00 diff --git a/.changes/unreleased/Added-20240517-144851.yaml b/.changes/unreleased/Added-20240517-144851.yaml new file mode 100644 index 000000000..a9b280e96 --- /dev/null +++ b/.changes/unreleased/Added-20240517-144851.yaml @@ -0,0 +1,3 @@ +kind: Added +body: scenario config local block documentation +time: 2024-05-17T14:48:51.970879+02:00 diff --git a/.mapping.json b/.mapping.json index da0684284..e40dde03a 100644 --- a/.mapping.json +++ b/.mapping.json @@ -1,6 +1,8 @@ { ".changes/header.tpl.md":"load/projects/pandora/.changes/header.tpl.md", ".changes/unreleased/.gitkeep":"load/projects/pandora/.changes/unreleased/.gitkeep", + ".changes/unreleased/Added-20240517-144818.yaml":"load/projects/pandora/.changes/unreleased/Added-20240517-144818.yaml", + ".changes/unreleased/Added-20240517-144851.yaml":"load/projects/pandora/.changes/unreleased/Added-20240517-144851.yaml", ".changes/v0.5.04.md":"load/projects/pandora/.changes/v0.5.04.md", ".changes/v0.5.05.md":"load/projects/pandora/.changes/v0.5.05.md", ".changes/v0.5.06.md":"load/projects/pandora/.changes/v0.5.06.md", @@ -273,6 +275,7 @@ "docs/eng/scenario-grpc-generator.md":"load/projects/pandora/docs/eng/scenario-grpc-generator.md", "docs/eng/scenario-http-generator.md":"load/projects/pandora/docs/eng/scenario-http-generator.md", "docs/eng/scenario/functions.md":"load/projects/pandora/docs/eng/scenario/functions.md", + "docs/eng/scenario/locals.md":"load/projects/pandora/docs/eng/scenario/locals.md", "docs/eng/scenario/variable_source.md":"load/projects/pandora/docs/eng/scenario/variable_source.md", "docs/eng/startup.md":"load/projects/pandora/docs/eng/startup.md", "docs/eng/tutorial.md":"load/projects/pandora/docs/eng/tutorial.md", @@ -304,6 +307,7 @@ "docs/rus/scenario-grpc-generator.md":"load/projects/pandora/docs/rus/scenario-grpc-generator.md", "docs/rus/scenario-http-generator.md":"load/projects/pandora/docs/rus/scenario-http-generator.md", "docs/rus/scenario/functions.md":"load/projects/pandora/docs/rus/scenario/functions.md", + "docs/rus/scenario/locals.md":"load/projects/pandora/docs/rus/scenario/locals.md", "docs/rus/scenario/variable_source.md":"load/projects/pandora/docs/rus/scenario/variable_source.md", "docs/rus/startup.md":"load/projects/pandora/docs/rus/startup.md", "docs/rus/tutorial.md":"load/projects/pandora/docs/rus/tutorial.md", diff --git a/README.md b/README.md index 4a3cd77fc..5d26d2cfa 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,9 @@ Pandora is a high-performance load generator in Go language. It has built-in HTTP(S) and HTTP/2 support and you can write your own load scenarios in Go, compiling them just before your test. +## Documentation +[Documentation](https://yandex.github.io/pandora/) + ## How to start ### Binary releases @@ -71,9 +74,3 @@ Create changelog release file - `changie batch v0.5.21` Same for next version - `changie batch $(changie next patch)` Merge to main CHANGELOG.md file - `changie merge` - -## Documentation -[Documentation](https://yandex.github.io/pandora/) - -## Old Documentation -[ReadTheDocs](https://yandexpandora.readthedocs.io/) diff --git a/components/providers/scenario/config/config.go b/components/providers/scenario/config/config.go index a8bbe05ae..71e17cc2b 100644 --- a/components/providers/scenario/config/config.go +++ b/components/providers/scenario/config/config.go @@ -13,6 +13,7 @@ import ( // AmmoConfig is a config for dynamic converting from map[string]interface{} type AmmoConfig struct { + Locals map[string]any VariableSources []vs.VariableSource `config:"variable_sources"` Requests []RequestConfig Calls []CallConfig diff --git a/components/providers/scenario/grpc/provider.go b/components/providers/scenario/grpc/provider.go index bb0f1fa78..f8b26e7d4 100644 --- a/components/providers/scenario/grpc/provider.go +++ b/components/providers/scenario/grpc/provider.go @@ -15,7 +15,7 @@ var _ core.Provider = (*scenario.Provider[*gun.Scenario])(nil) const defaultSinkSize = 100 func NewProvider(fs afero.Fs, conf scenario.ProviderConfig) (core.Provider, error) { - const op = "config.NewProvider" + const op = "scenario_grpc.NewProvider" ammoCfg, err := config.ReadAmmoConfig(fs, conf.File) if err != nil { return nil, fmt.Errorf("%s ReadAmmoConfig %w", op, err) diff --git a/components/providers/scenario/http/provider.go b/components/providers/scenario/http/provider.go index 607df371d..e3021e8ec 100644 --- a/components/providers/scenario/http/provider.go +++ b/components/providers/scenario/http/provider.go @@ -15,7 +15,7 @@ var _ core.Provider = (*scenario.Provider[*gun.Scenario])(nil) const defaultSinkSize = 100 func NewProvider(fs afero.Fs, conf scenario.ProviderConfig) (core.Provider, error) { - const op = "scenario.NewProvider" + const op = "scenario_http.NewProvider" ammoCfg, err := config.ReadAmmoConfig(fs, conf.File) if err != nil { return nil, fmt.Errorf("%s ReadAmmoConfig %w", op, err) diff --git a/components/providers/scenario/test/decode_test.go b/components/providers/scenario/test/decode_test.go index 110a8fff9..14828366d 100644 --- a/components/providers/scenario/test/decode_test.go +++ b/components/providers/scenario/test/decode_test.go @@ -6,6 +6,7 @@ import ( "github.com/spf13/afero" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/yandex/pandora/components/providers/scenario/config" _import "github.com/yandex/pandora/components/providers/scenario/import" "github.com/yandex/pandora/core/plugin/pluginconfig" @@ -22,12 +23,14 @@ func Test_ReadConfig_YamlAndHclSameResult(t *testing.T) { t.Run("http", func(t *testing.T) { fromHCL, err := config.ReadAmmoConfig(testFS, "../testdata/http_payload.hcl") - assert.NoError(t, err) + require.NoError(t, err) + fromHCL.Locals = nil fromYaml, err := config.ReadAmmoConfig(testFS, "../testdata/http_payload.yaml") - assert.NoError(t, err) + require.NoError(t, err) + fromYaml.Locals = nil - assert.Equal(t, fromHCL, fromYaml) + require.Equal(t, fromHCL, fromYaml) }) } diff --git a/components/providers/scenario/testdata/http_payload.yaml b/components/providers/scenario/testdata/http_payload.yaml index 3141f1858..614be4ba5 100644 --- a/components/providers/scenario/testdata/http_payload.yaml +++ b/components/providers/scenario/testdata/http_payload.yaml @@ -1,3 +1,7 @@ +locals: + global-headers: &global-headers + Content-Type: application/json + Useragent: Yandex variable_sources: - name: users type: file/csv @@ -20,9 +24,8 @@ requests: - name: auth_req method: POST uri: /auth - headers: &global-headers - Content-Type: application/json - Useragent: Yandex + headers: + <<: *global-headers tag: auth body: | {"user_id": {{.request.auth_req.preprocessor.user_id}}} diff --git a/docs/eng/scenario-grpc-generator.md b/docs/eng/scenario-grpc-generator.md index b946eb3b3..cdc2add3e 100644 --- a/docs/eng/scenario-grpc-generator.md +++ b/docs/eng/scenario-grpc-generator.md @@ -11,6 +11,7 @@ - [General principle](#general-principle) - [HCL example](#hcl-example) - [YAML example](#yaml-example) + - [Locals](#locals) - [Features](#features) - [Calls](#calls) - [Templater](#templater) @@ -87,6 +88,18 @@ The Call is a gRPC call. It has standard gRPC call fields plus additional ones. ### HCL example ```terraform +locals { + common_meta = { + "metadata" = "server.proto" + } + next = "next" +} +locals { + auth_meta = merge(local.common_meta, { + authorization = "{{.request.auth_req.postprocessor.token}}" + }) + next = "next" +} variable_source "users" "file/csv" { file = "users.csv" fields = ["user_id", "login", "pass"] @@ -106,9 +119,7 @@ variable_source "variables" "variables" { call "auth_req" { call = "target.TargetService.Auth" tag = "auth" - metadata = { - "metadata" = "server.proto" - } + metadata = local.auth_meta preprocessor "prepare" { mapping = { user = "source.users[next]" @@ -121,7 +132,6 @@ EOF payload = ["token"] status_code = 200 } -}} } scenario "scenario_name" { @@ -139,6 +149,9 @@ You can also see an example in the tests https://github.com/yandex/pandora/blob/ ### YAML example ```yaml +locals: + my-meta: &global-meta + metadata: "server.proto" variable_sources: - type: "file/csv" name: "users" @@ -155,7 +168,7 @@ calls: tag: auth method: POST metadata: - metadata: "server.proto" + <<: *global-meta preprocessors: - type: prepare mapping: @@ -175,6 +188,10 @@ scenarios: ] ``` +### Locals + +Про блок locals смотрите в отдельной [статье Locals](scenario/locals.md) + ## Features ### Calls diff --git a/docs/eng/scenario-http-generator.md b/docs/eng/scenario-http-generator.md index edeb95424..1b458282b 100644 --- a/docs/eng/scenario-http-generator.md +++ b/docs/eng/scenario-http-generator.md @@ -11,6 +11,7 @@ - [General principle](#general-principle) - [HCL example](#hcl-example) - [YAML example](#yaml-example) + - [Locals](#locals) - [Features](#features) - [Requests](#requests) - [Templater](#templater) @@ -97,6 +98,19 @@ Request - HTTP request. Has the standard HTTP request fields plus additional fie ### HCL example ```terraform +locals { + common_headers = { + Content-Type = "application/json" + Useragent = "Yandex" + } + next = "next" +} +locals { + auth_headers = merge(local.common_headers, { + Authorization = "Bearer {{.request.auth_req.postprocessor.token}}" + }) + next = "next" +} variable_source "source_name" "file/csv" { file = "file.csv" fields = ["id", "name"] @@ -107,9 +121,9 @@ variable_source "source_name" "file/csv" { request "request_name" { method = "POST" uri = "/uri" - headers = { - HeaderName = "header value" - } + headers = merge(local.common_headers, { + Authorization = "Bearer {{.request.auth_req.postprocessor.token}}" + }) tag = "tag" body = < @@ -144,6 +158,10 @@ scenario "scenario_name" { ### YAML example ```yaml +locals: + my-headers: &global-headers + Content-Type: application/json + Useragent: Yandex variable_sources: - type: "file/csv" name: "source_name" @@ -157,7 +175,7 @@ requests: uri: '/uri' method: POST headers: - Header-Name: "header value" + <<: *global-headers tag: tag body: '' preprocessor: @@ -179,6 +197,10 @@ scenarios: ] ``` +### Locals + +See [Locals article](scenario/locals.md) + ## Features ### Requests diff --git a/docs/eng/scenario/functions.md b/docs/eng/scenario/functions.md index 3e0026b3e..357166ac2 100644 --- a/docs/eng/scenario/functions.md +++ b/docs/eng/scenario/functions.md @@ -135,6 +135,28 @@ preprocessor { } ``` +# HCL functions + +You can use follow function + +- [coalesce](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/coalesce) +- [coalescelist](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/coalescelist) +- [compact](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/compact) +- [concat](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/concat) +- [distinct](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/distinct) +- [element](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/element) +- [flatten](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/flatten) +- [index](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/index-fn) +- [keys](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/keys) +- [lookup](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/lookup) +- [merge](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/merge) +- [reverse](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/reverse) +- [slice](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/slice) +- [sort](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/sort) +- [split](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/string/split) +- [values](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/values) +- [zipmap](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/zipmap) + --- diff --git a/docs/eng/scenario/locals.md b/docs/eng/scenario/locals.md new file mode 100644 index 000000000..bbc9f82a3 --- /dev/null +++ b/docs/eng/scenario/locals.md @@ -0,0 +1,100 @@ +[Home](../../index.md) + +--- + +# Locals + +Foreword: + +Creating a script from HCL consists of two stages: +- Parsing stage - converts the HCL file into the internal structure of the generator. +- Execution stage - involves the steps of: + - Preprocessing + - Templating + - Postprocessing + +This article focuses on the parsing stage. + +## HCL + +Just like in Terraform, you can use the `locals` block, which allows you to create additional variables. +It is important to note that these variables are only utilized during the parsing of HCL and cannot be used +during the execution stage. + +### Functions + +You can use [HCL functions](functions.md#hcl-functions). + +### Example of Use + +You can use `locals` variables to define common headers. + +Note the use of the `merge()` function. + +```hcl +locals { + common_headers = { + Content-Type = "application/json" + Useragent = "Yandex" + } + next = "next" +} +locals { + // Merge the new variable with the local variable local.common_headers + auth_headers = merge(local.common_headers, { + Authorization = "Bearer {{.request.auth_req.postprocessor.token}}" + }) + next = "next" +} + +request "list_req" { + // Merge the new variable with the local variable local.common_headers + method = "GET" + headers = merge(local.common_headers, { + Authorization = "Bearer {{.request.auth_req.postprocessor.token}}" + }) + tag = "list" + uri = "/list" + + postprocessor "var/jsonpath" { + mapping = { + item_id = "$.items[0]" + items = "$.items" + } + } +} +``` + +## YAML + +In YAML format, you can use anchors. + +For common variables, you can use the `locals` helper block. + +```yaml +locals: + global-headers: &global-headers + Content-Type: application/json + Useragent: Yandex + +requests: + - name: auth_req + headers: + <<: *global-headers + - name: list_req + headers: &auth-headers + <<: *global-headers + Authorization: Bearer {{.request.auth_req.postprocessor.token}} + - name: order_req + headers: + <<: *auth-headers +``` + +--- + +- [Scenario generator / HTTP](../scenario-http-generator.md) +- [Scenario generator / gRPC](../scenario-grpc-generator.md) + +--- + +[Home](../../index.md) diff --git a/docs/rus/scenario-grpc-generator.md b/docs/rus/scenario-grpc-generator.md index e708725d5..3032476e4 100644 --- a/docs/rus/scenario-grpc-generator.md +++ b/docs/rus/scenario-grpc-generator.md @@ -11,6 +11,7 @@ - [Общий принцип](#общий-принцип) - [HCL пример](#hcl-пример) - [YAML пример](#yaml-пример) + - [Locals](#locals) - [Возможности](#возможности) - [Вызовы](#вызовы) - [Шаблонизатор](#шаблонизатор) @@ -87,6 +88,18 @@ ammo: ### HCL пример ```terraform +locals { + common_meta = { + "metadata" = "server.proto" + } + next = "next" +} +locals { + auth_meta = merge(local.common_meta, { + authorization = "{{.request.auth_req.postprocessor.token}}" + }) + next = "next" +} variable_source "users" "file/csv" { file = "users.csv" fields = ["user_id", "login", "pass"] @@ -106,9 +119,7 @@ variable_source "variables" "variables" { call "auth_req" { call = "target.TargetService.Auth" tag = "auth" - metadata = { - "metadata" = "server.proto" - } + metadata = local.auth_meta preprocessor "prepare" { mapping = { user = "source.users[next]" @@ -121,7 +132,6 @@ EOF payload = ["token"] status_code = 200 } -}} } scenario "scenario_name" { @@ -139,6 +149,9 @@ scenario "scenario_name" { ### YAML пример ```yaml +locals: + my-meta: &global-meta + metadata: "server.proto" variable_sources: - type: "file/csv" name: "users" @@ -155,7 +168,7 @@ calls: tag: auth method: POST metadata: - metadata: "server.proto" + <<: *global-meta preprocessors: - type: prepare mapping: @@ -175,6 +188,10 @@ scenarios: ] ``` +### Locals + +Про блок locals смотрите в отдельной [статье Locals](scenario/locals.md) + ## Возможности ### Вызовы diff --git a/docs/rus/scenario-http-generator.md b/docs/rus/scenario-http-generator.md index d3e4bb156..bc1d325f0 100644 --- a/docs/rus/scenario-http-generator.md +++ b/docs/rus/scenario-http-generator.md @@ -11,6 +11,7 @@ - [Общий принцип](#общий-принцип) - [HCL пример](#hcl-пример) - [YAML пример](#yaml-пример) + - [Locals](#locals) - [Возможности](#возможности) - [Запросы](#запросы) - [Шаблонизатор](#шаблонизатор) @@ -97,6 +98,19 @@ ammo: ### HCL пример ```terraform +locals { + common_headers = { + Content-Type = "application/json" + Useragent = "Yandex" + } + next = "next" +} +locals { + auth_headers = merge(local.common_headers, { + Authorization = "Bearer {{.request.auth_req.postprocessor.token}}" + }) + next = "next" +} variable_source "source_name" "file/csv" { file = "file.csv" fields = ["id", "name"] @@ -107,9 +121,9 @@ variable_source "source_name" "file/csv" { request "request_name" { method = "POST" uri = "/uri" - headers = { - HeaderName = "header value" - } + headers = merge(local.common_headers, { + Authorization = "Bearer {{.request.auth_req.postprocessor.token}}" + }) tag = "tag" body = < @@ -147,6 +161,10 @@ scenario "scenario_name" { ### YAML пример ```yaml +locals: + my-headers: &global-headers + Content-Type: application/json + Useragent: Yandex variable_sources: - type: "file/csv" name: "source_name" @@ -160,7 +178,7 @@ requests: uri: '/uri' method: POST headers: - Header-Name: "header value" + <<: *global-headers tag: tag body: '' preprocessor: @@ -182,6 +200,10 @@ scenarios: ] ``` +### Locals + +Про блок locals смотрите в отдельной [статье Locals](scenario/locals.md) + ## Возможности ### Запросы diff --git a/docs/rus/scenario/functions.md b/docs/rus/scenario/functions.md index 86fb38ef9..b3774821c 100644 --- a/docs/rus/scenario/functions.md +++ b/docs/rus/scenario/functions.md @@ -137,6 +137,27 @@ preprocessor { } ``` +# Функции HCL + +При парсинге HCL доступны следующие функции + +- [coalesce](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/coalesce) +- [coalescelist](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/coalescelist) +- [compact](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/compact) +- [concat](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/concat) +- [distinct](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/distinct) +- [element](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/element) +- [flatten](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/flatten) +- [index](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/index-fn) +- [keys](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/keys) +- [lookup](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/lookup) +- [merge](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/merge) +- [reverse](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/reverse) +- [slice](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/slice) +- [sort](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/sort) +- [split](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/string/split) +- [values](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/values) +- [zipmap](https://developer.hashicorp.com/packer/docs/templates/hcl_templates/functions/collection/zipmap) --- diff --git a/docs/rus/scenario/locals.md b/docs/rus/scenario/locals.md new file mode 100644 index 000000000..fe4160d5b --- /dev/null +++ b/docs/rus/scenario/locals.md @@ -0,0 +1,100 @@ +[Домой](../index.md) + +--- + +# Locals + +Предисловие: + +Формирование сценария из hcl состоит из 2-х этапов: +- этап парсинга - преобразовывает hcl файл в внутреннюю структуру генератора +- этап выполнения - выполнение шагов: + - препроцессинга + - шаблонизации + - постпроцессинга + +В данной статье рассматривается этап парсинга. + +## HCL + +Так же как и в terraform вы можете использовать блок `locals`, который вы можете использовать для создания +дополнительных переменных. Важно, что данные переменные будут использоваться только при парсинге HCL и их нельзя +использовать на этапе выполнения. + +### Функции + +Вы можете использовать [функции HCL](functions.md#функции-hcl) + +### Пример использования + +Вы можете использовать переменные locals для определения общих заголовков. + +Обратите внимание на использование функции `merge()` + +```hcl +locals { + common_headers = { + Content-Type = "application/json" + Useragent = "Yandex" + } + next = "next" +} +locals { + // смержим новую переменную с локальной переменной local.common_headers + auth_headers = merge(local.common_headers, { + Authorization = "Bearer {{.request.auth_req.postprocessor.token}}" + }) + next = "next" +} + +request "list_req" { + // смержим новую переменную с локальной переменной local.common_headers + method = "GET" + headers = merge(local.common_headers, { + Authorization = "Bearer {{.request.auth_req.postprocessor.token}}" + }) + tag = "list" + uri = "/list" + + postprocessor "var/jsonpath" { + mapping = { + item_id = "$.items[0]" + items = "$.items" + } + } +} +``` + +## YAML + +В yaml формате вы можете использовать якоря. + +Для общих переменных можно использовать вспомогательный блок locals + +```yaml +locals: + global-headers: &global-headers + Content-Type: application/json + Useragent: Yandex + +requests: + - name: auth_req + headers: + <<: *global-headers + - name: list_req + headers: &auth-headers + <<: *global-headers + Authorization: Bearer {{.request.auth_req.postprocessor.token}} + - name: order_req + headers: + <<: *auth-headers +``` + +--- + +- [Сценарный генератор / HTTP](../scenario-http-generator.md) +- [Сценарный генератор / gRPC](../scenario-grpc-generator.md) + +--- + +[Домой](../index.md) From 8740306aa4f8b8dd01a411c40bb647bbead5efbf Mon Sep 17 00:00:00 2001 From: sabevzenko Date: Wed, 22 May 2024 13:34:51 +0300 Subject: [PATCH 2/3] reflect metadata simpler format and docs e32c147aa6e274c81a60a9bd344a947d3c907c2b --- .changes/unreleased/Added-20240517-144818.yaml | 3 --- .changes/unreleased/Added-20240517-144851.yaml | 3 --- .mapping.json | 2 -- CHANGELOG.md | 7 +++++++ cli/cli.go | 2 +- components/guns/grpc/core.go | 16 ++++++++-------- components/guns/grpc/scenario/core.go | 14 +++++++------- docs/eng/grpc-generator.md | 4 ++++ docs/rus/grpc-generator.md | 4 ++++ tests/acceptance/config_model.go | 12 +++++------- tests/acceptance/grpc_test.go | 6 ++---- tests/acceptance/testdata/grpc/base.yaml | 2 ++ 12 files changed, 40 insertions(+), 35 deletions(-) delete mode 100644 .changes/unreleased/Added-20240517-144818.yaml delete mode 100644 .changes/unreleased/Added-20240517-144851.yaml diff --git a/.changes/unreleased/Added-20240517-144818.yaml b/.changes/unreleased/Added-20240517-144818.yaml deleted file mode 100644 index f1b861409..000000000 --- a/.changes/unreleased/Added-20240517-144818.yaml +++ /dev/null @@ -1,3 +0,0 @@ -kind: Added -body: scenario config local block in yaml -time: 2024-05-17T14:48:18.485698+02:00 diff --git a/.changes/unreleased/Added-20240517-144851.yaml b/.changes/unreleased/Added-20240517-144851.yaml deleted file mode 100644 index a9b280e96..000000000 --- a/.changes/unreleased/Added-20240517-144851.yaml +++ /dev/null @@ -1,3 +0,0 @@ -kind: Added -body: scenario config local block documentation -time: 2024-05-17T14:48:51.970879+02:00 diff --git a/.mapping.json b/.mapping.json index e40dde03a..b9c23acca 100644 --- a/.mapping.json +++ b/.mapping.json @@ -1,8 +1,6 @@ { ".changes/header.tpl.md":"load/projects/pandora/.changes/header.tpl.md", ".changes/unreleased/.gitkeep":"load/projects/pandora/.changes/unreleased/.gitkeep", - ".changes/unreleased/Added-20240517-144818.yaml":"load/projects/pandora/.changes/unreleased/Added-20240517-144818.yaml", - ".changes/unreleased/Added-20240517-144851.yaml":"load/projects/pandora/.changes/unreleased/Added-20240517-144851.yaml", ".changes/v0.5.04.md":"load/projects/pandora/.changes/v0.5.04.md", ".changes/v0.5.05.md":"load/projects/pandora/.changes/v0.5.05.md", ".changes/v0.5.06.md":"load/projects/pandora/.changes/v0.5.06.md", diff --git a/CHANGELOG.md b/CHANGELOG.md index cfbfb0e42..ecf26ae85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), and is generated by [Changie](https://github.com/miniscruff/changie). +## v0.5.26 - 2024-05-21 +### Added +* scenario config local block in yaml +* scenario config local block documentation +### Changed +* reflect metadata simpler format and docs + ## v0.5.25 - 2024-05-16 ### Fixed * randInt function without args in preprocessor diff --git a/cli/cli.go b/cli/cli.go index 4b9c6979b..809972adf 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -25,7 +25,7 @@ import ( "go.uber.org/zap/zapcore" ) -const Version = "0.5.25" +const Version = "0.5.26" const defaultConfigFile = "load" const stdinConfigSelector = "-" diff --git a/components/guns/grpc/core.go b/components/guns/grpc/core.go index 08f2ab8ad..28d69759f 100644 --- a/components/guns/grpc/core.go +++ b/components/guns/grpc/core.go @@ -43,13 +43,13 @@ type GrpcDialOptions struct { } type GunConfig struct { - Target string `validate:"required"` - ReflectPort int64 `config:"reflect_port"` - ReflectMetadata metadata.MD `config:"reflect_metadata"` - Timeout time.Duration `config:"timeout"` // grpc request timeout - TLS bool `config:"tls"` - DialOptions GrpcDialOptions `config:"dial_options"` - AnswLog AnswLogConfig `config:"answlog"` + Target string `validate:"required"` + ReflectPort int64 `config:"reflect_port"` + ReflectMetadata map[string]string `config:"reflect_metadata"` + Timeout time.Duration `config:"timeout"` // grpc request timeout + TLS bool `config:"tls"` + DialOptions GrpcDialOptions `config:"dial_options"` + AnswLog AnswLogConfig `config:"answlog"` SharedClient struct { ClientNumber int `config:"client-number,omitempty"` Enabled bool `config:"enabled"` @@ -111,7 +111,7 @@ func (g *Gun) prepareMethodList(opts *warmup.Options) (map[string]desc.MethodDes } defer conn.Close() - refCtx := metadata.NewOutgoingContext(context.Background(), g.Conf.ReflectMetadata) + refCtx := metadata.NewOutgoingContext(context.Background(), metadata.New(g.Conf.ReflectMetadata)) refClient := grpcreflect.NewClientAuto(refCtx, conn) listServices, err := refClient.ListServices() if err != nil { diff --git a/components/guns/grpc/scenario/core.go b/components/guns/grpc/scenario/core.go index bed051bfe..684f6b74b 100644 --- a/components/guns/grpc/scenario/core.go +++ b/components/guns/grpc/scenario/core.go @@ -21,13 +21,13 @@ import ( const defaultTimeout = time.Second * 15 type GunConfig struct { - Target string `validate:"required"` - ReflectPort int64 `config:"reflect_port"` - ReflectMetadata metadata.MD `config:"reflect_metadata"` - Timeout time.Duration `config:"timeout"` // grpc request timeout - TLS bool `config:"tls"` - DialOptions GrpcDialOptions `config:"dial_options"` - AnswLog AnswLogConfig `config:"answlog"` + Target string `validate:"required"` + ReflectPort int64 `config:"reflect_port"` + ReflectMetadata map[string]string `config:"reflect_metadata"` + Timeout time.Duration `config:"timeout"` // grpc request timeout + TLS bool `config:"tls"` + DialOptions GrpcDialOptions `config:"dial_options"` + AnswLog AnswLogConfig `config:"answlog"` } type GrpcDialOptions struct { diff --git a/docs/eng/grpc-generator.md b/docs/eng/grpc-generator.md index fc13bdca1..373156b66 100644 --- a/docs/eng/grpc-generator.md +++ b/docs/eng/grpc-generator.md @@ -12,6 +12,9 @@ gun: target: '[hostname]:443' timeout: 15s # Grpc request timeout. Default: 15s tls: false # If true, Pandora accepts any certificate presented by the server and any host name in that certificate. Default: false + reflect_port: 8000 # If your reflection service is located on a port other than the main server + reflect_metadata: # Separate metadata data for reflection service + auth: Token shared-client: enabled: false # If TRUE, the generator will use a common transport client for all instances client-number: 1 # The number of shared clients can be increased. The default is 1 @@ -53,6 +56,7 @@ But to unify reports it converts them into HTTP codes. # References +- [Scenario generator / gRPC](scenario-grpc-generator.md) - Best practices - [RPS per instance](best_practices/rps-per-instance.md) - [Shared client](best_practices/shared-client.md) diff --git a/docs/rus/grpc-generator.md b/docs/rus/grpc-generator.md index 55b6e022d..b93abae71 100644 --- a/docs/rus/grpc-generator.md +++ b/docs/rus/grpc-generator.md @@ -12,6 +12,9 @@ gun: target: '[hostname]:443' timeout: 15s # Таймаут для запросов gRPC. По умолчанию: 15s tls: false # Если true, Pandora принимает любой сертификат, представленный сервером, и любое имя хоста в этом сертификате. По умолчанию: false + reflect_port: 8000 # Если ваш рефлекшн сервис находится на отличном от основного сервера порту + reflect_metadata: # Отдельные metadata данные для рефлекшн сервис + auth: Token shared-client: enabled: true # Если TRUE, генератор будет использовать общий транспортный клиент для всех инстансов client-number: 1 # Количество общих клиентов можно увеличить. По умолчанию 1 @@ -53,6 +56,7 @@ gun: # Смотри так же +- [Сценарный генератор / gRPC](scenario-grpc-generator.md) - Практики использования - [RPS на инстанс](best_practices/rps-per-instance.md) - [Общий транспорт](best_practices/shared-client.md) diff --git a/tests/acceptance/config_model.go b/tests/acceptance/config_model.go index b16b3b6ef..82c372629 100644 --- a/tests/acceptance/config_model.go +++ b/tests/acceptance/config_model.go @@ -1,7 +1,5 @@ package acceptance -import "google.golang.org/grpc/metadata" - type PandoraConfigLog struct { Level string `yaml:"level"` } @@ -13,11 +11,11 @@ type PandoraConfigMonitoring struct { ExpVar PandoraConfigMonitoringExpVar `yaml:"expvar"` } type PandoraConfigGRPCGun struct { - Type string `yaml:"type"` - Target string `yaml:"target"` - TLS bool `yaml:"tls"` - ReflectPort *int64 `yaml:"reflect_port,omitempty"` - ReflectMetadata *metadata.MD `yaml:"reflect_metadata,omitempty"` + Type string `yaml:"type"` + Target string `yaml:"target"` + TLS bool `yaml:"tls"` + ReflectPort *int64 `yaml:"reflect_port,omitempty"` + ReflectMetadata map[string]string `yaml:"reflect_metadata,omitempty"` SharedClient struct { ClientNumber int `yaml:"client-number,omitempty"` Enabled bool `yaml:"enabled"` diff --git a/tests/acceptance/grpc_test.go b/tests/acceptance/grpc_test.go index 1c548c2cf..cefe5e33b 100644 --- a/tests/acceptance/grpc_test.go +++ b/tests/acceptance/grpc_test.go @@ -165,8 +165,7 @@ func TestCheckGRPCReflectServer(t *testing.T) { { name: "success", conf: parseFileContentToCliConfig(t, baseFile, func(c *PandoraConfigGRPC) { - md := metadata.New(map[string]string{metadataKey: metadataValue}) - c.Pools[0].Gun.ReflectMetadata = &md + c.Pools[0].Gun.ReflectMetadata = map[string]string{metadataKey: metadataValue} }), }, { @@ -177,8 +176,7 @@ func TestCheckGRPCReflectServer(t *testing.T) { { name: "wrong metadata value", conf: parseFileContentToCliConfig(t, baseFile, func(c *PandoraConfigGRPC) { - md := metadata.New(map[string]string{metadataKey: "wrong-value"}) - c.Pools[0].Gun.ReflectMetadata = &md + c.Pools[0].Gun.ReflectMetadata = map[string]string{metadataKey: "wrong-value"} }), err: wrongMDValueError, }, diff --git a/tests/acceptance/testdata/grpc/base.yaml b/tests/acceptance/testdata/grpc/base.yaml index 3c984e272..6b3416205 100644 --- a/tests/acceptance/testdata/grpc/base.yaml +++ b/tests/acceptance/testdata/grpc/base.yaml @@ -5,6 +5,8 @@ pools: target: localhost:18888 tls: false use-shared-client: false + reflect_metadata: + auth: Token ammo: type: grpc/json file: testdata/grpc/grpc.payload From 9cb91f57e53307f6819ae08ac11d96e66eb17222 Mon Sep 17 00:00:00 2001 From: sabevzenko Date: Wed, 22 May 2024 14:21:26 +0300 Subject: [PATCH 3/3] changie 6e48dd5f0e4cbd57d26eccad955b4f2dc81b4ad8 --- .changes/v0.5.26.md | 6 ++++++ .mapping.json | 1 + 2 files changed, 7 insertions(+) create mode 100644 .changes/v0.5.26.md diff --git a/.changes/v0.5.26.md b/.changes/v0.5.26.md new file mode 100644 index 000000000..0bc6f3846 --- /dev/null +++ b/.changes/v0.5.26.md @@ -0,0 +1,6 @@ +## v0.5.26 - 2024-05-21 +### Added +* scenario config local block in yaml +* scenario config local block documentation +### Changed +* reflect metadata simpler format and docs diff --git a/.mapping.json b/.mapping.json index b9c23acca..123e1e713 100644 --- a/.mapping.json +++ b/.mapping.json @@ -23,6 +23,7 @@ ".changes/v0.5.23.md":"load/projects/pandora/.changes/v0.5.23.md", ".changes/v0.5.24.md":"load/projects/pandora/.changes/v0.5.24.md", ".changes/v0.5.25.md":"load/projects/pandora/.changes/v0.5.25.md", + ".changes/v0.5.26.md":"load/projects/pandora/.changes/v0.5.26.md", ".changie.yaml":"load/projects/pandora/.changie.yaml", ".github/workflows/release.yml":"load/projects/pandora/.github/workflows/release.yml", ".github/workflows/test.yml":"load/projects/pandora/.github/workflows/test.yml",