From 7713c5652dd7c2c0c39389a33145642a88063078 Mon Sep 17 00:00:00 2001 From: Sebastian Choren Date: Mon, 3 Jul 2023 18:22:39 -0300 Subject: [PATCH 1/4] implement test resource client --- cli/cmd/common.go | 34 +++++++++++++++++++++++++++++++ cli/cmd/config.go | 51 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 cli/cmd/common.go diff --git a/cli/cmd/common.go b/cli/cmd/common.go new file mode 100644 index 0000000000..7fc486868f --- /dev/null +++ b/cli/cmd/common.go @@ -0,0 +1,34 @@ +package cmd + +import ( + "fmt" + "time" + + "github.com/Jeffail/gabs/v2" +) + +func formatItemDate(item *gabs.Container, path string) error { + rawDate := item.Path(path).Data() + if rawDate == nil { + return nil + } + dateStr := rawDate.(string) + // if field is empty, do nothing + if dateStr == "" { + return nil + } + + date, err := time.Parse(time.RFC3339, dateStr) + if err != nil { + return fmt.Errorf("failed to parse datetime field '%s' (value '%s'): %s", path, dateStr, err) + } + + if date.IsZero() { + // sometime the date comes like 0000-00-00T00:00:00Z... show nothing in that case + item.SetP("", path) + return nil + } + + item.SetP(date.Format(time.DateTime), path) + return nil +} diff --git a/cli/cmd/config.go b/cli/cmd/config.go index 2f9440ee73..1f8946054b 100644 --- a/cli/cmd/config.go +++ b/cli/cmd/config.go @@ -6,7 +6,6 @@ import ( "net/http" "os" "strings" - "time" "github.com/Jeffail/gabs/v2" "github.com/kubeshop/tracetest/cli/actions" @@ -158,19 +157,45 @@ var resources = resourcemanager.NewRegistry(). // set spec.summary.steps to the number of steps in the transaction item.SetP(len(item.Path("spec.steps").Children()), "spec.summary.steps") - // if lastRun.time is not empty, show it in a nicer format - lastRunTime := item.Path("spec.summary.lastRun.time").Data().(string) - if lastRunTime != "" { - date, err := time.Parse(time.RFC3339, lastRunTime) - if err != nil { - return fmt.Errorf("failed to parse last run time: %s", err) - } - if date.IsZero() { - item.SetP("", "spec.summary.lastRun.time") - } else { - item.SetP(date.Format(time.DateTime), "spec.summary.lastRun.time") - } + if err := formatItemDate(item, "spec.summary.lastRun.time"); err != nil { + return err } + + return nil + }, + }), + ), + ). + Register( + resourcemanager.NewClient( + httpClient, + "test", "tests", + resourcemanager.WithTableConfig(resourcemanager.TableConfig{ + Cells: []resourcemanager.TableCellConfig{ + {Header: "ID", Path: "spec.id"}, + {Header: "NAME", Path: "spec.name"}, + {Header: "VERSION", Path: "spec.version"}, + {Header: "TRIGGER TYPE", Path: "spec.trigger.type"}, + {Header: "RUNS", Path: "spec.summary.runs"}, + {Header: "LAST RUN TIME", Path: "spec.summary.lastRun.time"}, + {Header: "LAST RUN SUCCESSES", Path: "spec.summary.lastRun.passes"}, + {Header: "LAST RUN FAILURES", Path: "spec.summary.lastRun.fails"}, + {Header: "URL", Path: "spec.url"}, + }, + ItemModifier: func(item *gabs.Container) error { + // set spec.summary.steps to the number of steps in the transaction + id, ok := item.Path("spec.id").Data().(string) + if !ok { + return fmt.Errorf("test id '%s' is not a string", id) + } + + url := cliConfig.URL() + "/test/" + id + item.SetP(url, "spec.url") + + if err := formatItemDate(item, "spec.summary.lastRun.time"); err != nil { + return err + } + return nil }, }), From e006d32594094fc2e864bf679d5a6e6938ef0ef8 Mon Sep 17 00:00:00 2001 From: Sebastian Choren Date: Tue, 4 Jul 2023 12:50:25 -0300 Subject: [PATCH 2/4] add tests --- .../testscenarios/test/test/list_test_test.go | 213 ++++++++++++++++++ .../test/test/resources/api.proto | 37 +++ .../test/test/resources/environment-file.yaml | 11 + .../grpc-trigger-embedded-protobuf.yaml | 60 +++++ .../grpc-trigger-reference-protobuf.yaml | 22 ++ .../http-trigger-with-environment-file.yaml | 26 +++ .../test/test/resources/import.yaml | 14 ++ .../test/test/resources/list.yaml | 13 ++ .../test/run_test_with_grpc_trigger_test.go | 55 +++++ ..._http_trigger_and_environment_file_test.go | 95 ++++++++ .../cli-e2etest/testscenarios/types/test.go | 84 +++++++ 11 files changed, 630 insertions(+) create mode 100644 testing/cli-e2etest/testscenarios/test/test/list_test_test.go create mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/api.proto create mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/environment-file.yaml create mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-embedded-protobuf.yaml create mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-reference-protobuf.yaml create mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/http-trigger-with-environment-file.yaml create mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/import.yaml create mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/list.yaml create mode 100644 testing/cli-e2etest/testscenarios/test/test/run_test_with_grpc_trigger_test.go create mode 100644 testing/cli-e2etest/testscenarios/test/test/run_test_with_http_trigger_and_environment_file_test.go create mode 100644 testing/cli-e2etest/testscenarios/types/test.go diff --git a/testing/cli-e2etest/testscenarios/test/test/list_test_test.go b/testing/cli-e2etest/testscenarios/test/test/list_test_test.go new file mode 100644 index 0000000000..f5896a3840 --- /dev/null +++ b/testing/cli-e2etest/testscenarios/test/test/list_test_test.go @@ -0,0 +1,213 @@ +package test + +import ( + "fmt" + "testing" + + "github.com/davecgh/go-spew/spew" + "github.com/kubeshop/tracetest/cli-e2etest/environment" + "github.com/kubeshop/tracetest/cli-e2etest/helpers" + "github.com/kubeshop/tracetest/cli-e2etest/testscenarios/types" + "github.com/kubeshop/tracetest/cli-e2etest/tracetestcli" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func addListTestsPreReqs(t *testing.T, env environment.Manager) { + cliConfig := env.GetCLIConfigPath(t) + + // Given I am a Tracetest CLI user + // And I have my server recently created + + // When I try to set up a new test + // Then it should be applied with success + newTestPath := env.GetTestResourcePath(t, "list") + + // TODO: using test run as apply test is not yet implemented + // result := tracetestcli.Exec(t, fmt.Sprintf("apply test --file %s", newTestPath), tracetestcli.WithCLIConfig(cliConfig)) + result := tracetestcli.Exec(t, fmt.Sprintf("test run --definition %s", newTestPath), tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) + + // When I try to set up a another test + // Then it should be applied with success + anotherTestPath := env.GetTestResourcePath(t, "import") + + // TODO: using test run as apply test is not yet implemented + // result = tracetestcli.Exec(t, fmt.Sprintf("apply test --file %s", anotherTestPath), tracetestcli.WithCLIConfig(cliConfig)) + result = tracetestcli.Exec(t, fmt.Sprintf("test run --definition %s", anotherTestPath), tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) +} + +func TestListTests(t *testing.T) { + // instantiate require with testing helper + require := require.New(t) + assert := assert.New(t) + + // setup isolated e2e test + env := environment.CreateAndStart(t) + defer env.Close(t) + + cliConfig := env.GetCLIConfigPath(t) + + t.Run("list no tests", func(t *testing.T) { + // Given I am a Tracetest CLI user + // And I have my server recently created + // And there is no envs + result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection asc --output yaml", tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) + + testVarsList := helpers.UnmarshalYAMLSequence[types.TestResource](t, result.StdOut) + require.Len(testVarsList, 0) + }) + + addListTestsPreReqs(t, env) + + t.Run("list with invalid sortBy field", func(t *testing.T) { + // Given I am a Tracetest CLI user + // And I have my server recently created + + // When I try to list these tests by an invalid field + // Then I should receive an error + result := tracetestcli.Exec(t, "list test --sortBy id --output yaml", tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 1) + require.Contains(result.StdErr, "invalid sort field: id") // TODO: think on how to improve this error handling + }) + + t.Run("list with YAML format", func(t *testing.T) { + // Given I am a Tracetest CLI user + // And I have 2 existing tests + + // When I try to list these tests by a valid field and in YAML format + // Then I should receive 2 tests + result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection desc --output yaml", tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) + + testVarsList := helpers.UnmarshalYAMLSequence[types.TestResource](t, result.StdOut) + require.Len(testVarsList, 2) + importTest := testVarsList[0] + spew.Dump(importTest) + assert.Equal("Test", importTest.Type) + assert.Equal("fH_8AulVR", importTest.Spec.ID) + assert.Equal("Pokeshop - Import", importTest.Spec.Name) + assert.Equal("Import a Pokemon", importTest.Spec.Description) + assert.Equal("http", importTest.Spec.Trigger.Type) + assert.Equal("http://demo-api:8081/pokemon/import", importTest.Spec.Trigger.HTTPRequest.URL) + assert.Equal("POST", importTest.Spec.Trigger.HTTPRequest.Method) + assert.Equal(`'{"id":52}'`, importTest.Spec.Trigger.HTTPRequest.Body) + require.Len(importTest.Spec.Trigger.HTTPRequest.Headers, 1) + assert.Equal("Content-Type", importTest.Spec.Trigger.HTTPRequest.Headers[0].Key) + assert.Equal("application/json", importTest.Spec.Trigger.HTTPRequest.Headers[0].Value) + + listTest := testVarsList[1] + assert.Equal("Test", listTest.Type) + assert.Equal("fH_8AulVR", listTest.Spec.ID) + assert.Equal("Pokeshop - List", listTest.Spec.Name) + assert.Equal("List Pokemon", listTest.Spec.Description) + assert.Equal("http", listTest.Spec.Trigger.Type) + assert.Equal("http://demo-api:8081/pokemon?take=20&skip=0", listTest.Spec.Trigger.HTTPRequest.URL) + assert.Equal("GET", listTest.Spec.Trigger.HTTPRequest.Method) + assert.Equal("", listTest.Spec.Trigger.HTTPRequest.Body) + require.Len(listTest.Spec.Trigger.HTTPRequest.Headers, 1) + assert.Equal("Content-Type", listTest.Spec.Trigger.HTTPRequest.Headers[0].Key) + assert.Equal("application/json", listTest.Spec.Trigger.HTTPRequest.Headers[0].Value) + }) + + // t.Run("list with JSON format", func(t *testing.T) { + // // Given I am a Tracetest CLI user + // // And I have my server recently created + + // // When I try to list these tests by a valid field and in JSON format + // // Then I should receive three tests + // result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection asc --output json", tracetestcli.WithCLIConfig(cliConfig)) + // helpers.RequireExitCodeEqual(t, result, 0) + + // testVarsList := helpers.UnmarshalJSON[[]types.TestResource](t, result.StdOut) + // require.Len(testVarsList, 3) + + // // due our database sorting algorithm, "another-env" comes in the front of ".env" + // // ref https://wiki.postgresql.org/wiki/FAQ#Why_do_my_strings_sort_incorrectly.3F + // anotherTestVars := testVarsList[0] + // require.Equal("Test", anotherTestVars.Type) + // require.Equal("another-env", anotherTestVars.Spec.ID) + // require.Equal("another-env", anotherTestVars.Spec.Name) + // require.Len(anotherTestVars.Spec.Values, 2) + // require.Equal("Here", anotherTestVars.Spec.Values[0].Key) + // require.Equal("We", anotherTestVars.Spec.Values[0].Value) + // require.Equal("Come", anotherTestVars.Spec.Values[1].Key) + // require.Equal("Again", anotherTestVars.Spec.Values[1].Value) + + // testVars := testVarsList[1] + // require.Equal("Test", testVars.Type) + // require.Equal(".env", testVars.Spec.ID) + // require.Equal(".env", testVars.Spec.Name) + // require.Len(testVars.Spec.Values, 2) + // require.Equal("FIRST_VAR", testVars.Spec.Values[0].Key) + // require.Equal("some-value", testVars.Spec.Values[0].Value) + // require.Equal("SECOND_VAR", testVars.Spec.Values[1].Key) + // require.Equal("another_value", testVars.Spec.Values[1].Value) + + // oneMoreTestVars := testVarsList[2] + // require.Equal("Test", oneMoreTestVars.Type) + // require.Equal("one-more-env", oneMoreTestVars.Spec.ID) + // require.Equal("one-more-env", oneMoreTestVars.Spec.Name) + // require.Len(oneMoreTestVars.Spec.Values, 2) + // require.Equal("This", oneMoreTestVars.Spec.Values[0].Key) + // require.Equal("Is", oneMoreTestVars.Spec.Values[0].Value) + // require.Equal("The", oneMoreTestVars.Spec.Values[1].Key) + // require.Equal("Third", oneMoreTestVars.Spec.Values[1].Value) + // }) + + // t.Run("list with pretty format", func(t *testing.T) { + // // Given I am a Tracetest CLI user + // // And I have my server recently created + + // // When I try to list these tests by a valid field and in pretty format + // // Then it should print a table with 6 lines printed: header, separator, three envs and empty line + // result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection asc --output pretty", tracetestcli.WithCLIConfig(cliConfig)) + // helpers.RequireExitCodeEqual(t, result, 0) + + // lines := strings.Split(result.StdOut, "\n") + // require.Len(lines, 6) + + // // due our database sorting algorithm, "another-env" comes in the front of ".env" + // // ref https://wiki.postgresql.org/wiki/FAQ#Why_do_my_strings_sort_incorrectly.3F + // require.Contains(lines[2], "another-env") + // require.Contains(lines[3], ".env") + // require.Contains(lines[4], "one-more-env") + // }) + + // t.Run("list with YAML format skipping the first and taking two items", func(t *testing.T) { + // // Given I am a Tracetest CLI user + // // And I have my server recently created + + // // When I try to list these tests by a valid field, paging options and in YAML format + // // Then I should receive two tests + // result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection asc --skip 1 --take 2 --output yaml", tracetestcli.WithCLIConfig(cliConfig)) + // helpers.RequireExitCodeEqual(t, result, 0) + + // testVarsList := helpers.UnmarshalYAMLSequence[types.TestResource](t, result.StdOut) + // require.Len(testVarsList, 2) + + // // due our database sorting algorithm, "another-env" comes in the front of ".env" + // // ref https://wiki.postgresql.org/wiki/FAQ#Why_do_my_strings_sort_incorrectly.3F + // testVars := testVarsList[0] + // require.Equal("Test", testVars.Type) + // require.Equal(".env", testVars.Spec.ID) + // require.Equal(".env", testVars.Spec.Name) + // require.Len(testVars.Spec.Values, 2) + // require.Equal("FIRST_VAR", testVars.Spec.Values[0].Key) + // require.Equal("some-value", testVars.Spec.Values[0].Value) + // require.Equal("SECOND_VAR", testVars.Spec.Values[1].Key) + // require.Equal("another_value", testVars.Spec.Values[1].Value) + + // oneMoreTestVars := testVarsList[1] + // require.Equal("Test", oneMoreTestVars.Type) + // require.Equal("one-more-env", oneMoreTestVars.Spec.ID) + // require.Equal("one-more-env", oneMoreTestVars.Spec.Name) + // require.Len(oneMoreTestVars.Spec.Values, 2) + // require.Equal("This", oneMoreTestVars.Spec.Values[0].Key) + // require.Equal("Is", oneMoreTestVars.Spec.Values[0].Value) + // require.Equal("The", oneMoreTestVars.Spec.Values[1].Key) + // require.Equal("Third", oneMoreTestVars.Spec.Values[1].Value) + // }) +} diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/api.proto b/testing/cli-e2etest/testscenarios/test/test/resources/api.proto new file mode 100644 index 0000000000..e4e94d4bd5 --- /dev/null +++ b/testing/cli-e2etest/testscenarios/test/test/resources/api.proto @@ -0,0 +1,37 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_outer_classname = "PokeshopProto"; +option objc_class_prefix = "PKS"; + +package pokeshop; + +service Pokeshop { + rpc getPokemonList (GetPokemonRequest) returns (GetPokemonListResponse) {} + rpc createPokemon (Pokemon) returns (Pokemon) {} + rpc importPokemon (ImportPokemonRequest) returns (ImportPokemonRequest) {} +} + +message ImportPokemonRequest { + int32 id = 1; + optional bool isFixed = 2; +} + +message GetPokemonRequest { + optional int32 skip = 1; + optional int32 take = 2; + optional bool isFixed = 3; +} + +message GetPokemonListResponse { + repeated Pokemon items = 1; + int32 totalCount = 2; +} + +message Pokemon { + optional int32 id = 1; + string name = 2; + string type = 3; + bool isFeatured = 4; + optional string imageUrl = 5; +} diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/environment-file.yaml b/testing/cli-e2etest/testscenarios/test/test/resources/environment-file.yaml new file mode 100644 index 0000000000..6c5831b356 --- /dev/null +++ b/testing/cli-e2etest/testscenarios/test/test/resources/environment-file.yaml @@ -0,0 +1,11 @@ +type: Environment +spec: + id: pokeapi-env + name: pokeapi-env + description: "" + createdAt: 2023-06-21T20:37:10.10518Z + values: + - key: POKEMON_NAME + value: snorlax + - key: POKEMON_URL + value: https://assets.pokemon.com/assets/cms2/img/pokedex/full/143.png diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-embedded-protobuf.yaml b/testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-embedded-protobuf.yaml new file mode 100644 index 0000000000..84e210ffb7 --- /dev/null +++ b/testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-embedded-protobuf.yaml @@ -0,0 +1,60 @@ +type: Test +spec: + id: create-pokemon + name: "Create Pokemon" + description: Create a single pokemon on Pokeshop + trigger: + type: grpc + grpc: + protobufFile: | + syntax = "proto3"; + + option java_multiple_files = true; + option java_outer_classname = "PokeshopProto"; + option objc_class_prefix = "PKS"; + + package pokeshop; + + service Pokeshop { + rpc getPokemonList (GetPokemonRequest) returns (GetPokemonListResponse) {} + rpc createPokemon (Pokemon) returns (Pokemon) {} + rpc importPokemon (ImportPokemonRequest) returns (ImportPokemonRequest) {} + } + + message ImportPokemonRequest { + int32 id = 1; + optional bool isFixed = 2; + } + + message GetPokemonRequest { + optional int32 skip = 1; + optional int32 take = 2; + optional bool isFixed = 3; + } + + message GetPokemonListResponse { + repeated Pokemon items = 1; + int32 totalCount = 2; + } + + message Pokemon { + optional int32 id = 1; + string name = 2; + string type = 3; + bool isFeatured = 4; + optional string imageUrl = 5; + } + + address: demo-rpc:8082 + method: pokeshop.Pokeshop.createPokemon + request: |- + { + "name": "Pikachu", + "type": "eletric", + "isFeatured": true + } + specs: + - name: It calls Pokeshop correctly + selector: span[tracetest.span.type="rpc" name="pokeshop.Pokeshop/createPokemon" rpc.system="grpc" rpc.method="createPokemon" rpc.service="pokeshop.Pokeshop"] + assertions: + - attr:rpc.grpc.status_code = 0 diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-reference-protobuf.yaml b/testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-reference-protobuf.yaml new file mode 100644 index 0000000000..1149226290 --- /dev/null +++ b/testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-reference-protobuf.yaml @@ -0,0 +1,22 @@ +type: Test +spec: + id: create-pokemon + name: "Create Pokemon" + description: Create a single pokemon on Pokeshop + trigger: + type: grpc + grpc: + protobufFile: ./api.proto + address: demo-rpc:8082 + method: pokeshop.Pokeshop.createPokemon + request: |- + { + "name": "Pikachu", + "type": "eletric", + "isFeatured": true + } + specs: + - name: It calls Pokeshop correctly + selector: span[tracetest.span.type="rpc" name="pokeshop.Pokeshop/createPokemon" rpc.system="grpc" rpc.method="createPokemon" rpc.service="pokeshop.Pokeshop"] + assertions: + - attr:rpc.grpc.status_code = 0 diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/http-trigger-with-environment-file.yaml b/testing/cli-e2etest/testscenarios/test/test/resources/http-trigger-with-environment-file.yaml new file mode 100644 index 0000000000..52f6c5011e --- /dev/null +++ b/testing/cli-e2etest/testscenarios/test/test/resources/http-trigger-with-environment-file.yaml @@ -0,0 +1,26 @@ +type: Test +spec: + id: 9wtAH2_Vg + name: Pokeshop - Add + description: Add a Pokemon + trigger: + type: http + httpRequest: + url: http://demo-api:8081/pokemon + method: POST + headers: + - key: Content-Type + value: application/json + body: '{"name":"${env:POKEMON_NAME}","type":"normal","imageUrl":"${env:POKEMON_URL}","isFeatured":true}' + specs: + - name: It should add a Pokemon correctly + selector: span[tracetest.span.type="http" name="POST /pokemon" http.method="POST"] + assertions: + - attr:http.status_code = 201 + - name: It should save the correct data + selector: + span[tracetest.span.type="database" name="create postgres.pokemon" db.system="postgres" + db.name="postgres" db.user="postgres" db.operation="create" db.sql.table="pokemon"] + assertions: + - attr:db.result contains '"imageUrl":"${env:POKEMON_URL}"' + - attr:db.result contains '"name":"${env:POKEMON_NAME}"' diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/import.yaml b/testing/cli-e2etest/testscenarios/test/test/resources/import.yaml new file mode 100644 index 0000000000..0bcd61422b --- /dev/null +++ b/testing/cli-e2etest/testscenarios/test/test/resources/import.yaml @@ -0,0 +1,14 @@ +type: Test +spec: + id: RXrbV__4g + name: Pokeshop - Import + description: Import a Pokemon + trigger: + type: http + httpRequest: + url: http://demo-api:8081/pokemon/import + method: POST + headers: + - key: Content-Type + value: application/json + body: '{"id":52}' diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/list.yaml b/testing/cli-e2etest/testscenarios/test/test/resources/list.yaml new file mode 100644 index 0000000000..06fc9ff36c --- /dev/null +++ b/testing/cli-e2etest/testscenarios/test/test/resources/list.yaml @@ -0,0 +1,13 @@ +type: Test +spec: + id: fH_8AulVR + name: Pokeshop - List + description: List Pokemon + trigger: + type: http + httpRequest: + url: http://demo-api:8081/pokemon?take=20&skip=0 + method: GET + headers: + - key: Content-Type + value: application/json diff --git a/testing/cli-e2etest/testscenarios/test/test/run_test_with_grpc_trigger_test.go b/testing/cli-e2etest/testscenarios/test/test/run_test_with_grpc_trigger_test.go new file mode 100644 index 0000000000..e626b32154 --- /dev/null +++ b/testing/cli-e2etest/testscenarios/test/test/run_test_with_grpc_trigger_test.go @@ -0,0 +1,55 @@ +package test + +import ( + "fmt" + "testing" + + "github.com/kubeshop/tracetest/cli-e2etest/environment" + "github.com/kubeshop/tracetest/cli-e2etest/helpers" + "github.com/kubeshop/tracetest/cli-e2etest/tracetestcli" + "github.com/stretchr/testify/require" +) + +func TestRunTestWithGrpcTrigger(t *testing.T) { + // setup isolated e2e environment + env := environment.CreateAndStart(t, environment.WithDataStoreEnabled(), environment.WithPokeshop()) + defer env.Close(t) + + cliConfig := env.GetCLIConfigPath(t) + + t.Run("should pass when using an embedded protobuf string in the test", func(t *testing.T) { + // instantiate require with testing helper + require := require.New(t) + + // Given I am a Tracetest CLI user + // And I have my server recently created + // And the datasource is already set + + // When I try to run a test with a gRPC trigger with embedded protobuf + // Then it should pass + testFile := env.GetTestResourcePath(t, "grpc-trigger-embedded-protobuf") + + command := fmt.Sprintf("test run -w -d %s", testFile) + result := tracetestcli.Exec(t, command, tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) + require.Contains(result.StdOut, "✔ It calls Pokeshop correctly") // checks if the assertion was succeeded + }) + + t.Run("should pass when referencing a protobuf file in the test", func(t *testing.T) { + // instantiate require with testing helper + require := require.New(t) + + // Given I am a Tracetest CLI user + // And I have my server recently created + // And the datasource is already set + + // When I try to run a test with a gRPC trigger with a reference to a protobuf file + // Then it should pass + testFile := env.GetTestResourcePath(t, "grpc-trigger-reference-protobuf") + + command := fmt.Sprintf("test run -w -d %s", testFile) + result := tracetestcli.Exec(t, command, tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) + require.Contains(result.StdOut, "✔ It calls Pokeshop correctly") // checks if the assertion was succeeded + }) +} diff --git a/testing/cli-e2etest/testscenarios/test/test/run_test_with_http_trigger_and_environment_file_test.go b/testing/cli-e2etest/testscenarios/test/test/run_test_with_http_trigger_and_environment_file_test.go new file mode 100644 index 0000000000..9e41dc9426 --- /dev/null +++ b/testing/cli-e2etest/testscenarios/test/test/run_test_with_http_trigger_and_environment_file_test.go @@ -0,0 +1,95 @@ +package test + +import ( + "fmt" + "testing" + + "github.com/kubeshop/tracetest/cli-e2etest/environment" + "github.com/kubeshop/tracetest/cli-e2etest/helpers" + "github.com/kubeshop/tracetest/cli-e2etest/testscenarios/types" + "github.com/kubeshop/tracetest/cli-e2etest/tracetestcli" + "github.com/stretchr/testify/require" +) + +func TestRunTestWithHttpTriggerAndEnvironmentFile(t *testing.T) { + // setup isolated e2e environment + env := environment.CreateAndStart(t, environment.WithDataStoreEnabled(), environment.WithPokeshop()) + defer env.Close(t) + + cliConfig := env.GetCLIConfigPath(t) + + // instantiate require with testing helper + require := require.New(t) + + t.Run("should pass when using environment definition file", func(t *testing.T) { + // Given I am a Tracetest CLI user + // And I have my server recently created + // And the datasource is already set + + // When I try to get an environment + // Then it should return a message saying that the environment was not found + result := tracetestcli.Exec(t, "get environment --id pokeapi-env", tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) + require.Contains(result.StdOut, "Resource environment with ID pokeapi-env not found") + + // When I try to run a test with a http trigger and a environment file + // Then it should pass + environmentFile := env.GetTestResourcePath(t, "environment-file") + testFile := env.GetTestResourcePath(t, "http-trigger-with-environment-file") + + command := fmt.Sprintf("test run -w -d %s --environment %s", testFile, environmentFile) + result = tracetestcli.Exec(t, command, tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) + require.Contains(result.StdOut, "✔ It should add a Pokemon correctly") + require.Contains(result.StdOut, "✔ It should save the correct data") + + // When I try to get the environment created on the previous step + // Then it should retrieve it correctly + result = tracetestcli.Exec(t, "get environment --id pokeapi-env --output yaml", tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) + + environmentVars := helpers.UnmarshalYAML[types.EnvironmentResource](t, result.StdOut) + require.Equal("Environment", environmentVars.Type) + require.Equal("pokeapi-env", environmentVars.Spec.ID) + require.Equal("pokeapi-env", environmentVars.Spec.Name) + require.Len(environmentVars.Spec.Values, 2) + require.Equal("POKEMON_NAME", environmentVars.Spec.Values[0].Key) + require.Equal("snorlax", environmentVars.Spec.Values[0].Value) + require.Equal("POKEMON_URL", environmentVars.Spec.Values[1].Key) + require.Equal("https://assets.pokemon.com/assets/cms2/img/pokedex/full/143.png", environmentVars.Spec.Values[1].Value) + }) + + t.Run("should pass when using environment id", func(t *testing.T) { + // Given I am a Tracetest CLI user + // And I have my server recently created + // And the datasource is already set + + // When I create an environment + // Then it should be created correctly + environmentFile := env.GetTestResourcePath(t, "environment-file") + + result := tracetestcli.Exec(t, fmt.Sprintf("apply environment --file %s", environmentFile), tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) + + environmentVars := helpers.UnmarshalYAML[types.EnvironmentResource](t, result.StdOut) + require.Equal("Environment", environmentVars.Type) + require.Equal("pokeapi-env", environmentVars.Spec.ID) + require.Equal("pokeapi-env", environmentVars.Spec.Name) + require.Len(environmentVars.Spec.Values, 2) + require.Equal("POKEMON_NAME", environmentVars.Spec.Values[0].Key) + require.Equal("snorlax", environmentVars.Spec.Values[0].Value) + require.Equal("POKEMON_URL", environmentVars.Spec.Values[1].Key) + require.Equal("https://assets.pokemon.com/assets/cms2/img/pokedex/full/143.png", environmentVars.Spec.Values[1].Value) + + // When I try to run a test with a http trigger and a environment id + // Then it should pass + + testFile := env.GetTestResourcePath(t, "http-trigger-with-environment-file") + + command := fmt.Sprintf("test run -w -d %s --environment pokeapi-env", testFile) + result = tracetestcli.Exec(t, command, tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) + require.Contains(result.StdOut, "✔ It should add a Pokemon correctly") + require.Contains(result.StdOut, "✔ It should save the correct data") + }) +} diff --git a/testing/cli-e2etest/testscenarios/types/test.go b/testing/cli-e2etest/testscenarios/types/test.go new file mode 100644 index 0000000000..127c582c45 --- /dev/null +++ b/testing/cli-e2etest/testscenarios/types/test.go @@ -0,0 +1,84 @@ +package types + +import ( + "time" + + "github.com/kubeshop/tracetest/server/pkg/maps" +) + +type TestResource struct { + Type string `json:"type"` + Spec Test `json:"spec"` +} + +type Test struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Version int `json:"version"` + Trigger Trigger `json:"trigger"` + Specs []TestSpec `json:"specs"` + Outputs maps.Ordered[string, Output] `json:"outputs"` + Summary Summary `json:"summary"` +} + +type Trigger struct { + Type string `json:"type"` + HTTPRequest HTTPRequest `json:"http"` +} + +type HTTPRequest struct { + Method string `json:"method,omitempty"` + URL string `json:"url"` + Body string `json:"body,omitempty"` + Headers []HTTPHeader `json:"headers,omitempty"` +} + +type HTTPHeader struct { + Key string `json:"Key"` + Value string `json:"Value"` +} + +type Output struct { + Selector string `json:"selector"` + Value string `json:"value"` +} + +type TestSpec struct { + Selector Selector `json:"selector"` + Name string `json:"name,omitempty"` + Assertions []string `json:"assertions"` +} + +type Selector struct { + Query string `json:"query"` + ParsedSelector SpanSelector `json:"parsedSelector"` +} + +type SpanSelector struct { + Filters []SelectorFilter `json:"filters"` + PseudoClass *SelectorPseudoClass `json:"pseudoClass,omitempty"` + ChildSelector *SpanSelector `json:"childSelector,omitempty"` +} + +type SelectorFilter struct { + Property string `json:"property"` + Operator string `json:"operator"` + Value string `json:"value"` +} + +type SelectorPseudoClass struct { + Name string `json:"name"` + Argument *int32 `json:"argument,omitempty"` +} + +type Summary struct { + Runs int `json:"runs"` + LastRun LastRun `json:"lastRun"` +} + +type LastRun struct { + Time time.Time `json:"time"` + Passes int `json:"passes"` + Fails int `json:"fails"` +} From 2c7876d8dca324a72abe7649a892e9e9a5ac9e5b Mon Sep 17 00:00:00 2001 From: Sebastian Choren Date: Tue, 4 Jul 2023 19:37:29 -0300 Subject: [PATCH 3/4] add tests --- .../testscenarios/test/list_test_test.go | 212 ++++++++++++++++++ .../testscenarios/test/resources/import.yaml | 14 ++ .../testscenarios/test/resources/list.yaml | 13 ++ 3 files changed, 239 insertions(+) create mode 100644 testing/cli-e2etest/testscenarios/test/list_test_test.go create mode 100644 testing/cli-e2etest/testscenarios/test/resources/import.yaml create mode 100644 testing/cli-e2etest/testscenarios/test/resources/list.yaml diff --git a/testing/cli-e2etest/testscenarios/test/list_test_test.go b/testing/cli-e2etest/testscenarios/test/list_test_test.go new file mode 100644 index 0000000000..947e922cd6 --- /dev/null +++ b/testing/cli-e2etest/testscenarios/test/list_test_test.go @@ -0,0 +1,212 @@ +package test + +import ( + "fmt" + "testing" + + "github.com/kubeshop/tracetest/cli-e2etest/environment" + "github.com/kubeshop/tracetest/cli-e2etest/helpers" + "github.com/kubeshop/tracetest/cli-e2etest/testscenarios/types" + "github.com/kubeshop/tracetest/cli-e2etest/tracetestcli" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func addListTestsPreReqs(t *testing.T, env environment.Manager) { + cliConfig := env.GetCLIConfigPath(t) + + // Given I am a Tracetest CLI user + // And I have my server recently created + + // When I try to set up a new test + // Then it should be applied with success + newTestPath := env.GetTestResourcePath(t, "list") + + // TODO: using test run as apply test is not yet implemented + // result := tracetestcli.Exec(t, fmt.Sprintf("apply test --file %s", newTestPath), tracetestcli.WithCLIConfig(cliConfig)) + result := tracetestcli.Exec(t, fmt.Sprintf("test run --definition %s", newTestPath), tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) + + // When I try to set up a another test + // Then it should be applied with success + anotherTestPath := env.GetTestResourcePath(t, "import") + + // TODO: using test run as apply test is not yet implemented + // result = tracetestcli.Exec(t, fmt.Sprintf("apply test --file %s", anotherTestPath), tracetestcli.WithCLIConfig(cliConfig)) + result = tracetestcli.Exec(t, fmt.Sprintf("test run --definition %s", anotherTestPath), tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) +} + +func TestListTests(t *testing.T) { + // instantiate require with testing helper + require := require.New(t) + assert := assert.New(t) + + // setup isolated e2e test + env := environment.CreateAndStart(t) + defer env.Close(t) + + cliConfig := env.GetCLIConfigPath(t) + + t.Run("list no tests", func(t *testing.T) { + // Given I am a Tracetest CLI user + // And I have my server recently created + // And there is no envs + result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection asc --output yaml", tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) + + testVarsList := helpers.UnmarshalYAMLSequence[types.TestResource](t, result.StdOut) + require.Len(testVarsList, 0) + }) + + addListTestsPreReqs(t, env) + + t.Run("list with invalid sortBy field", func(t *testing.T) { + // Given I am a Tracetest CLI user + // And I have my server recently created + + // When I try to list these tests by an invalid field + // Then I should receive an error + result := tracetestcli.Exec(t, "list test --sortBy id --output yaml", tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 1) + require.Contains(result.StdErr, "invalid sort field: id") // TODO: think on how to improve this error handling + }) + + t.Run("list with YAML format", func(t *testing.T) { + // Given I am a Tracetest CLI user + // And I have 2 existing tests + + // When I try to list these tests by a valid field and in YAML format + // Then I should receive 2 tests + result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection desc --output yaml", tracetestcli.WithCLIConfig(cliConfig)) + helpers.RequireExitCodeEqual(t, result, 0) + + testVarsList := helpers.UnmarshalYAMLSequence[types.TestResource](t, result.StdOut) + require.Len(testVarsList, 2) + importTest := testVarsList[0] + + assert.Equal("Test", importTest.Type) + assert.Equal("fH_8AulVR", importTest.Spec.ID) + assert.Equal("Pokeshop - Import", importTest.Spec.Name) + assert.Equal("Import a Pokemon", importTest.Spec.Description) + assert.Equal("http", importTest.Spec.Trigger.Type) + assert.Equal("http://demo-api:8081/pokemon/import", importTest.Spec.Trigger.HTTPRequest.URL) + assert.Equal("POST", importTest.Spec.Trigger.HTTPRequest.Method) + assert.Equal(`'{"id":52}'`, importTest.Spec.Trigger.HTTPRequest.Body) + require.Len(importTest.Spec.Trigger.HTTPRequest.Headers, 1) + assert.Equal("Content-Type", importTest.Spec.Trigger.HTTPRequest.Headers[0].Key) + assert.Equal("application/json", importTest.Spec.Trigger.HTTPRequest.Headers[0].Value) + + listTest := testVarsList[1] + assert.Equal("Test", listTest.Type) + assert.Equal("fH_8AulVR", listTest.Spec.ID) + assert.Equal("Pokeshop - List", listTest.Spec.Name) + assert.Equal("List Pokemon", listTest.Spec.Description) + assert.Equal("http", listTest.Spec.Trigger.Type) + assert.Equal("http://demo-api:8081/pokemon?take=20&skip=0", listTest.Spec.Trigger.HTTPRequest.URL) + assert.Equal("GET", listTest.Spec.Trigger.HTTPRequest.Method) + assert.Equal("", listTest.Spec.Trigger.HTTPRequest.Body) + require.Len(listTest.Spec.Trigger.HTTPRequest.Headers, 1) + assert.Equal("Content-Type", listTest.Spec.Trigger.HTTPRequest.Headers[0].Key) + assert.Equal("application/json", listTest.Spec.Trigger.HTTPRequest.Headers[0].Value) + }) + + // t.Run("list with JSON format", func(t *testing.T) { + // // Given I am a Tracetest CLI user + // // And I have my server recently created + + // // When I try to list these tests by a valid field and in JSON format + // // Then I should receive three tests + // result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection asc --output json", tracetestcli.WithCLIConfig(cliConfig)) + // helpers.RequireExitCodeEqual(t, result, 0) + + // testVarsList := helpers.UnmarshalJSON[[]types.TestResource](t, result.StdOut) + // require.Len(testVarsList, 3) + + // // due our database sorting algorithm, "another-env" comes in the front of ".env" + // // ref https://wiki.postgresql.org/wiki/FAQ#Why_do_my_strings_sort_incorrectly.3F + // anotherTestVars := testVarsList[0] + // require.Equal("Test", anotherTestVars.Type) + // require.Equal("another-env", anotherTestVars.Spec.ID) + // require.Equal("another-env", anotherTestVars.Spec.Name) + // require.Len(anotherTestVars.Spec.Values, 2) + // require.Equal("Here", anotherTestVars.Spec.Values[0].Key) + // require.Equal("We", anotherTestVars.Spec.Values[0].Value) + // require.Equal("Come", anotherTestVars.Spec.Values[1].Key) + // require.Equal("Again", anotherTestVars.Spec.Values[1].Value) + + // testVars := testVarsList[1] + // require.Equal("Test", testVars.Type) + // require.Equal(".env", testVars.Spec.ID) + // require.Equal(".env", testVars.Spec.Name) + // require.Len(testVars.Spec.Values, 2) + // require.Equal("FIRST_VAR", testVars.Spec.Values[0].Key) + // require.Equal("some-value", testVars.Spec.Values[0].Value) + // require.Equal("SECOND_VAR", testVars.Spec.Values[1].Key) + // require.Equal("another_value", testVars.Spec.Values[1].Value) + + // oneMoreTestVars := testVarsList[2] + // require.Equal("Test", oneMoreTestVars.Type) + // require.Equal("one-more-env", oneMoreTestVars.Spec.ID) + // require.Equal("one-more-env", oneMoreTestVars.Spec.Name) + // require.Len(oneMoreTestVars.Spec.Values, 2) + // require.Equal("This", oneMoreTestVars.Spec.Values[0].Key) + // require.Equal("Is", oneMoreTestVars.Spec.Values[0].Value) + // require.Equal("The", oneMoreTestVars.Spec.Values[1].Key) + // require.Equal("Third", oneMoreTestVars.Spec.Values[1].Value) + // }) + + // t.Run("list with pretty format", func(t *testing.T) { + // // Given I am a Tracetest CLI user + // // And I have my server recently created + + // // When I try to list these tests by a valid field and in pretty format + // // Then it should print a table with 6 lines printed: header, separator, three envs and empty line + // result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection asc --output pretty", tracetestcli.WithCLIConfig(cliConfig)) + // helpers.RequireExitCodeEqual(t, result, 0) + + // lines := strings.Split(result.StdOut, "\n") + // require.Len(lines, 6) + + // // due our database sorting algorithm, "another-env" comes in the front of ".env" + // // ref https://wiki.postgresql.org/wiki/FAQ#Why_do_my_strings_sort_incorrectly.3F + // require.Contains(lines[2], "another-env") + // require.Contains(lines[3], ".env") + // require.Contains(lines[4], "one-more-env") + // }) + + // t.Run("list with YAML format skipping the first and taking two items", func(t *testing.T) { + // // Given I am a Tracetest CLI user + // // And I have my server recently created + + // // When I try to list these tests by a valid field, paging options and in YAML format + // // Then I should receive two tests + // result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection asc --skip 1 --take 2 --output yaml", tracetestcli.WithCLIConfig(cliConfig)) + // helpers.RequireExitCodeEqual(t, result, 0) + + // testVarsList := helpers.UnmarshalYAMLSequence[types.TestResource](t, result.StdOut) + // require.Len(testVarsList, 2) + + // // due our database sorting algorithm, "another-env" comes in the front of ".env" + // // ref https://wiki.postgresql.org/wiki/FAQ#Why_do_my_strings_sort_incorrectly.3F + // testVars := testVarsList[0] + // require.Equal("Test", testVars.Type) + // require.Equal(".env", testVars.Spec.ID) + // require.Equal(".env", testVars.Spec.Name) + // require.Len(testVars.Spec.Values, 2) + // require.Equal("FIRST_VAR", testVars.Spec.Values[0].Key) + // require.Equal("some-value", testVars.Spec.Values[0].Value) + // require.Equal("SECOND_VAR", testVars.Spec.Values[1].Key) + // require.Equal("another_value", testVars.Spec.Values[1].Value) + + // oneMoreTestVars := testVarsList[1] + // require.Equal("Test", oneMoreTestVars.Type) + // require.Equal("one-more-env", oneMoreTestVars.Spec.ID) + // require.Equal("one-more-env", oneMoreTestVars.Spec.Name) + // require.Len(oneMoreTestVars.Spec.Values, 2) + // require.Equal("This", oneMoreTestVars.Spec.Values[0].Key) + // require.Equal("Is", oneMoreTestVars.Spec.Values[0].Value) + // require.Equal("The", oneMoreTestVars.Spec.Values[1].Key) + // require.Equal("Third", oneMoreTestVars.Spec.Values[1].Value) + // }) +} diff --git a/testing/cli-e2etest/testscenarios/test/resources/import.yaml b/testing/cli-e2etest/testscenarios/test/resources/import.yaml new file mode 100644 index 0000000000..0bcd61422b --- /dev/null +++ b/testing/cli-e2etest/testscenarios/test/resources/import.yaml @@ -0,0 +1,14 @@ +type: Test +spec: + id: RXrbV__4g + name: Pokeshop - Import + description: Import a Pokemon + trigger: + type: http + httpRequest: + url: http://demo-api:8081/pokemon/import + method: POST + headers: + - key: Content-Type + value: application/json + body: '{"id":52}' diff --git a/testing/cli-e2etest/testscenarios/test/resources/list.yaml b/testing/cli-e2etest/testscenarios/test/resources/list.yaml new file mode 100644 index 0000000000..06fc9ff36c --- /dev/null +++ b/testing/cli-e2etest/testscenarios/test/resources/list.yaml @@ -0,0 +1,13 @@ +type: Test +spec: + id: fH_8AulVR + name: Pokeshop - List + description: List Pokemon + trigger: + type: http + httpRequest: + url: http://demo-api:8081/pokemon?take=20&skip=0 + method: GET + headers: + - key: Content-Type + value: application/json From 53a78eeaaad8cabb629b91e5305777eaaa5232f6 Mon Sep 17 00:00:00 2001 From: Sebastian Choren Date: Tue, 4 Jul 2023 21:33:52 -0300 Subject: [PATCH 4/4] Cli test run (#2853) --- .github/workflows/pull-request.yaml | 4 +- api/triggers.yaml | 3 + cli/actions/export_test_action.go | 13 +- cli/actions/run_test_action.go | 969 +++++++++++------- cli/actions/tests.go | 118 --- cli/cmd/apply_cmd.go | 9 +- cli/cmd/config.go | 14 - cli/cmd/test_run_cmd.go | 15 +- cli/formatters/formatter.go | 76 -- cli/formatters/json.go | 54 - cli/formatters/table.go | 54 - cli/formatters/yaml.go | 60 -- cli/go.mod | 4 +- cli/go.sum | 7 +- cli/openapi/api_api.go | 232 +++-- cli/openapi/api_resource_api.go | 265 ++--- cli/openapi/model_trigger.go | 36 + cli/pkg/fileutil/file.go | 38 +- cli/pkg/fileutil/{is_file_path.go => path.go} | 25 + cli/pkg/resourcemanager/apply.go | 7 +- cli/variable/injector.go | 4 +- server/app/app.go | 1 + server/http/controller.go | 3 +- server/openapi/model_trigger.go | 5 + server/test/test_repository.go | 6 +- .../testscenarios/test/list_test_test.go | 37 +- .../testscenarios/test/test/list_test_test.go | 213 ---- .../test/test/resources/api.proto | 37 - .../test/test/resources/environment-file.yaml | 11 - .../grpc-trigger-embedded-protobuf.yaml | 60 -- .../grpc-trigger-reference-protobuf.yaml | 22 - .../http-trigger-with-environment-file.yaml | 26 - .../test/test/resources/import.yaml | 14 - .../test/test/resources/list.yaml | 13 - .../test/run_test_with_grpc_trigger_test.go | 55 - ..._http_trigger_and_environment_file_test.go | 95 -- .../cli-e2etest/testscenarios/types/test.go | 6 +- web/src/types/Generated.types.ts | 1 + 38 files changed, 1025 insertions(+), 1587 deletions(-) delete mode 100644 cli/actions/tests.go delete mode 100644 cli/formatters/formatter.go delete mode 100644 cli/formatters/json.go delete mode 100644 cli/formatters/table.go delete mode 100644 cli/formatters/yaml.go rename cli/pkg/fileutil/{is_file_path.go => path.go} (52%) delete mode 100644 testing/cli-e2etest/testscenarios/test/test/list_test_test.go delete mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/api.proto delete mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/environment-file.yaml delete mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-embedded-protobuf.yaml delete mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-reference-protobuf.yaml delete mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/http-trigger-with-environment-file.yaml delete mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/import.yaml delete mode 100644 testing/cli-e2etest/testscenarios/test/test/resources/list.yaml delete mode 100644 testing/cli-e2etest/testscenarios/test/test/run_test_with_grpc_trigger_test.go delete mode 100644 testing/cli-e2etest/testscenarios/test/test/run_test_with_http_trigger_and_environment_file_test.go diff --git a/.github/workflows/pull-request.yaml b/.github/workflows/pull-request.yaml index c5f19ee82b..cc5e920fea 100644 --- a/.github/workflows/pull-request.yaml +++ b/.github/workflows/pull-request.yaml @@ -303,7 +303,7 @@ jobs: - name: Start services run: | ./run.sh down up - ./run.sh logstt > /tmp/docker-log & + ./run.sh tracetest-logs > /tmp/docker-log & - name: Run tests run: | chmod +x ./dist/tracetest ./dist/tracetest-server @@ -399,7 +399,7 @@ jobs: - name: Run integration tests run: | ./run.sh down up - ./run.sh logstt > /tmp/docker-log & + ./run.sh tracetest-logs > /tmp/docker-log & ./scripts/wait-for-port.sh 11633 if [ "${{env.CYPRESS_RECORD_KEY}}" = "" ]; then diff --git a/api/triggers.yaml b/api/triggers.yaml index 2b204780e8..d7fb2d44d2 100644 --- a/api/triggers.yaml +++ b/api/triggers.yaml @@ -11,8 +11,11 @@ components: triggerType: type: string enum: ["http", "grpc", "traceid"] + # TODO: remove after test migration http: $ref: "./http.yaml#/components/schemas/HTTPRequest" + httpRequest: + $ref: "./http.yaml#/components/schemas/HTTPRequest" grpc: $ref: "./grpc.yaml#/components/schemas/GRPCRequest" traceid: diff --git a/cli/actions/export_test_action.go b/cli/actions/export_test_action.go index b0913c19dc..bf36b2a8bd 100644 --- a/cli/actions/export_test_action.go +++ b/cli/actions/export_test_action.go @@ -69,13 +69,14 @@ func (a exportTestAction) getDefinitionFromServer(ctx context.Context, args Expo expectedVersion = *test.Version } - request := a.client.ApiApi.GetTestVersionDefinitionFile(ctx, args.TestId, expectedVersion) - definitionString, _, err := a.client.ApiApi.GetTestVersionDefinitionFileExecute(request) - if err != nil { - return "", fmt.Errorf("could not get test definition: %w", err) - } + // request := a.client.ApiApi.GetTestVersionDefinitionFile(ctx, args.TestId, expectedVersion) + // definitionString, _, err := a.client.ApiApi.GetTestVersionDefinitionFileExecute(request) + // if err != nil { + // return "", fmt.Errorf("could not get test definition: %w", err) + // } - return definitionString, nil + // return definitionString, nil + return "", fmt.Errorf("deprecated") } func (a exportTestAction) getTestFromServer(ctx context.Context, testID string) (openapi.Test, error) { diff --git a/cli/actions/run_test_action.go b/cli/actions/run_test_action.go index fe6eb4e994..1ae90eb24c 100644 --- a/cli/actions/run_test_action.go +++ b/cli/actions/run_test_action.go @@ -4,25 +4,23 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "os" - "path/filepath" "strconv" "sync" "time" - "github.com/Jeffail/gabs/v2" cienvironment "github.com/cucumber/ci-environment/go" + "github.com/goccy/go-yaml" "github.com/kubeshop/tracetest/cli/config" - "github.com/kubeshop/tracetest/cli/file" "github.com/kubeshop/tracetest/cli/formatters" "github.com/kubeshop/tracetest/cli/openapi" "github.com/kubeshop/tracetest/cli/pkg/fileutil" "github.com/kubeshop/tracetest/cli/pkg/resourcemanager" "github.com/kubeshop/tracetest/cli/ui" "github.com/kubeshop/tracetest/cli/utils" - "github.com/kubeshop/tracetest/server/model/yaml" + "github.com/kubeshop/tracetest/cli/variable" "go.uber.org/zap" ) @@ -33,49 +31,66 @@ type RunResourceArgs struct { JUnit string } -type runTestAction struct { - config config.Config - logger *zap.Logger - client *openapi.APIClient - testActions resourcemanager.Client - environmentActions resourcemanager.Client - cliExit func(int) +func (args RunResourceArgs) Validate() error { + if args.DefinitionFile == "" { + return fmt.Errorf("you must specify a definition file to run a test") + } + + if args.JUnit != "" && !args.WaitForResult { + return fmt.Errorf("--junit option requires --wait-for-result") + } + + return nil } -type runDefParams struct { - DefinitionFile string - EnvID string - WaitForResult bool - JunitFile string - Metadata map[string]string - EnvironmentVariables map[string]string +type runTestAction struct { + config config.Config + logger *zap.Logger + openapiClient *openapi.APIClient + environments resourcemanager.Client + tests resourcemanager.Client + transactions resourcemanager.Client + yamlFormat resourcemanager.Format + jsonFormat resourcemanager.Format + cliExit func(int) } func NewRunTestAction( config config.Config, logger *zap.Logger, - client *openapi.APIClient, - testActions resourcemanager.Client, - environmentActions resourcemanager.Client, + openapiClient *openapi.APIClient, + tests resourcemanager.Client, + transactions resourcemanager.Client, + environments resourcemanager.Client, cliExit func(int), ) runTestAction { + + yamlFormat, err := resourcemanager.Formats.Get(resourcemanager.FormatYAML) + if err != nil { + panic(fmt.Errorf("could not get yaml format: %w", err)) + } + + jsonFormat, err := resourcemanager.Formats.Get(resourcemanager.FormatJSON) + if err != nil { + panic(fmt.Errorf("could not get json format: %w", err)) + } + return runTestAction{ config, logger, - client, - testActions, - environmentActions, + openapiClient, + environments, + tests, + transactions, + yamlFormat, + jsonFormat, cliExit, } } func (a runTestAction) Run(ctx context.Context, args RunResourceArgs) error { - if args.DefinitionFile == "" { - return fmt.Errorf("you must specify a definition file to run a test") - } - - if args.JUnit != "" && !args.WaitForResult { - return fmt.Errorf("--junit option requires --wait-for-result") + if err := args.Validate(); err != nil { + return err } a.logger.Debug( @@ -86,434 +101,635 @@ func (a runTestAction) Run(ctx context.Context, args RunResourceArgs) error { zap.String("junit", args.JUnit), ) - envID := args.EnvID + f, err := fileutil.Read(args.DefinitionFile) + if err != nil { + return fmt.Errorf("cannot read definition file %s: %w", args.DefinitionFile, err) + } + df := defFile{f} + a.logger.Debug("Definition file read", zap.String("absolutePath", df.AbsPath())) - if fileutil.IsFilePath(args.EnvID) { - a.logger.Debug("resolve envID from file reference", zap.String("path", envID)) - jsonFormat, err := resourcemanager.Formats.Get(resourcemanager.FormatJSON) - if err != nil { - return fmt.Errorf("could not get json format: %w", err) - } + envID, err := a.resolveEnvID(ctx, args.EnvID) + if err != nil { + return fmt.Errorf("cannot resolve environment id: %w", err) + } + a.logger.Debug("env resolved", zap.String("ID", envID)) - envJson, err := a.environmentActions.Apply(ctx, args.EnvID, jsonFormat) - if err != nil { - return fmt.Errorf("could not read environment file: %w", err) - } + df, err = a.apply(ctx, df) + if err != nil { + return fmt.Errorf("cannot apply definition file: %w", err) + } - parsed, err := gabs.ParseJSON([]byte(envJson)) - if err != nil { - return fmt.Errorf("could not parse environment json: %w", err) - } + a.logger.Debug("Definition file applied", zap.String("updated", string(df.Contents()))) + + var run runResult + var envVars []envVar - ok := true - envID, ok = parsed.Path("spec.id").Data().(string) + // iterate until we have all env vars, + // or the server returns an actual error + for { + run, err = a.run(ctx, df, envID, envVars) + if err == nil { + break + } + missingEnvVarsErr, ok := err.(missingEnvVarsError) if !ok { - return fmt.Errorf("could not parse environment id from json") + // actual error, return + return fmt.Errorf("cannot run test: %w", err) } - } - a.logger.Debug("resolved env", zap.String("envID", envID)) + // missing vars error + envVars = a.askForMissingVars([]envVar(missingEnvVarsErr)) + } - params := runDefParams{ - DefinitionFile: args.DefinitionFile, - EnvID: envID, - WaitForResult: args.WaitForResult, - JunitFile: args.JUnit, - Metadata: a.getMetadata(), + if !args.WaitForResult { + fmt.Println(a.formatResult(run, false)) + a.cliExit(0) } - err := a.runDefinition(ctx, params) + result, err := a.waitForResult(ctx, run) if err != nil { - return fmt.Errorf("could not run definition: %w", err) + return fmt.Errorf("cannot wait for test result: %w", err) + } + + fmt.Println(a.formatResult(result, true)) + a.cliExit(a.exitCode(result)) + + if args.JUnit != "" { + err := a.writeJUnitReport(ctx, result, args.JUnit) + if err != nil { + return fmt.Errorf("cannot write junit report: %w", err) + } } return nil } -func (a runTestAction) testFileToID(ctx context.Context, originalPath, filePath string) (string, error) { - path := filepath.Join(originalPath, filePath) - f, err := file.Read(path) - if err != nil { - return "", err +func (a runTestAction) exitCode(res runResult) int { + switch res.ResourceType { + case "Test": + if !res.Run.(openapi.TestRun).Result.GetAllPassed() { + return 1 + } + case "Transaction": + for _, step := range res.Run.(openapi.TransactionRun).Steps { + if !step.Result.GetAllPassed() { + return 1 + } + } } + return 0 +} - if t, err := f.Definition().Test(); err == nil && t.Trigger.Type == "grpc" { - newFile, err := getUpdatedTestWithGrpcTrigger(f, t) - if err != nil { - return "", err - } +func (a runTestAction) resolveEnvID(ctx context.Context, envID string) (string, error) { + if !fileutil.IsFilePath(envID) { + a.logger.Debug("envID is not a file path", zap.String("envID", envID)) + return envID, nil + } - if newFile != nil { // has new file, update it - f = newFile - } + f, err := fileutil.Read(envID) + if err != nil { + return "", fmt.Errorf("cannot read environment file %s: %w", envID, err) } - newFile, err := a.testActions.Apply(ctx, *f) + a.logger.Debug("envID is a file path", zap.String("filePath", envID), zap.Any("file", f)) + updatedEnv, err := a.environments.Apply(ctx, f, a.yamlFormat) if err != nil { - return "", fmt.Errorf("could not apply test: %w", err) + return "", fmt.Errorf("could not read environment file: %w", err) } - if t, err := newFile.Definition().Test(); err == nil { - return t.ID, nil + var env openapi.EnvironmentResource + err = yaml.Unmarshal([]byte(updatedEnv), &env) + if err != nil { + a.logger.Error("error parsing json", zap.String("content", updatedEnv), zap.Error(err)) + return "", fmt.Errorf("could not unmarshal environment json: %w", err) } - return "", fmt.Errorf("obtained definition is not a test") + return env.Spec.GetId(), nil } -func (a runTestAction) runDefinition(ctx context.Context, params runDefParams) error { - f, err := file.Read(params.DefinitionFile) +func (a runTestAction) injectLocalEnvVars(ctx context.Context, df defFile) (defFile, error) { + variableInjector := variable.NewInjector(variable.WithVariableProvider( + variable.EnvironmentVariableProvider{}, + )) + + injected, err := variableInjector.ReplaceInString(string(df.Contents())) if err != nil { - return err + return df, fmt.Errorf("cannot inject local environment variables: %w", err) } - newFile, err := a.testActions.Apply(ctx, *f) + df = defFile{fileutil.New(df.AbsPath(), []byte(injected))} + + return df, nil +} + +func (a runTestAction) apply(ctx context.Context, df defFile) (defFile, error) { + defType, err := getTypeFromFile(df) if err != nil { - return fmt.Errorf("could not apply test: %w", err) + return df, fmt.Errorf("cannot get type from definition file: %w", err) } + a.logger.Debug("definition file type", zap.String("type", defType)) - return a.runDefinitionFile(ctx, newFile, params) + switch defType { + case "Test": + return a.applyTest(ctx, df) + case "Transaction": + return a.applyTransaction(ctx, df) + default: + return df, fmt.Errorf("unknown type %s", defType) + } } -func (a runTestAction) runDefinitionFile(ctx context.Context, f *file.File, params runDefParams) error { - f, err := f.ResolveVariables() +func (a runTestAction) applyTest(ctx context.Context, df defFile) (defFile, error) { + df, err := a.injectLocalEnvVars(ctx, df) if err != nil { - return err + return df, fmt.Errorf("cannot inject local env vars: %w", err) } - if t, err := f.Definition().Transaction(); err == nil { - for i, step := range t.Steps { - // since step could be a relative path in relation of the definition file, - // to check it properly we need to convert it to an absolute path - stepPath := filepath.Join(f.AbsDir(), step) + var test openapi.TestResource + err = yaml.Unmarshal(df.Contents(), &test) + if err != nil { + a.logger.Error("error parsing test", zap.String("content", string(df.Contents())), zap.Error(err)) + return df, fmt.Errorf("could not unmarshal test yaml: %w", err) + } - if !fileutil.IsFilePath(stepPath) { - // not referencing a file, keep the value - continue - } + test, err = a.consolidateGRPCFile(df, test) + if err != nil { + return df, fmt.Errorf("could not consolidate grpc file: %w", err) + } - // references a file, resolve to its ID - id, err := a.testFileToID(ctx, f.AbsDir(), step) - if err != nil { - return fmt.Errorf(`cannot translate path "%s" to an ID: %w`, step, err) - } + marshalled, err := yaml.Marshal(test) + if err != nil { + return df, fmt.Errorf("could not marshal test yaml: %w", err) + } + df = defFile{fileutil.New(df.AbsPath(), marshalled)} - t.Steps[i] = id - } + a.logger.Debug("applying test", + zap.String("absolutePath", df.AbsPath()), + zap.String("id", test.Spec.GetId()), + zap.String("marshalled", string(marshalled)), + ) - def := yaml.File{ - Type: yaml.FileTypeTransaction, - Spec: t, - } + updated, err := a.tests.Apply(ctx, df.File, a.yamlFormat) + if err != nil { + return df, fmt.Errorf("could not read test file: %w", err) + } - updated, err := def.Encode() - if err != nil { - return fmt.Errorf(`cannot encode updated transaction: %w`, err) - } + df = defFile{fileutil.New(df.AbsPath(), []byte(updated))} - f, err = file.New(f.Path(), updated) - if err != nil { - return fmt.Errorf(`cannot recreate updated file: %w`, err) - } + err = yaml.Unmarshal(df.Contents(), &test) + if err != nil { + a.logger.Error("error parsing updated test", zap.String("content", string(df.Contents())), zap.Error(err)) + return df, fmt.Errorf("could not unmarshal test yaml: %w", err) } - if t, err := f.Definition().Test(); err == nil && t.Trigger.Type == "grpc" { - newFile, err := getUpdatedTestWithGrpcTrigger(f, t) - if err != nil { - return err - } + a.logger.Debug("test applied", + zap.String("absolutePath", df.AbsPath()), + zap.String("id", test.Spec.GetId()), + ) - if newFile != nil { // has new file, update it - f = newFile - } + return df, nil +} + +func (a runTestAction) consolidateGRPCFile(df defFile, test openapi.TestResource) (openapi.TestResource, error) { + if test.Spec.Trigger.GetType() != "grpc" { + a.logger.Debug("test does not use grpc", zap.String("triggerType", test.Spec.Trigger.GetType())) + return test, nil } - variables := make([]openapi.EnvironmentValue, 0) - for name, value := range params.EnvironmentVariables { - variables = append(variables, openapi.EnvironmentValue{Key: openapi.PtrString(name), Value: openapi.PtrString(value)}) + definedPBFile := test.Spec.Trigger.Grpc.GetProtobufFile() + if !fileutil.LooksLikeFilePath(definedPBFile) { + a.logger.Debug("protobuf file is not a file path", zap.String("protobufFile", definedPBFile)) + return test, nil } - body, resp, err := a.client.ApiApi. - ExecuteDefinition(ctx). - TextDefinition(openapi.TextDefinition{ - Content: openapi.PtrString(f.Contents()), - RunInformation: &openapi.RunInformation{ - Metadata: params.Metadata, - EnvironmentId: ¶ms.EnvID, - Variables: variables, - }, - }). - Execute() + pbFilePath := df.RelativeFile(definedPBFile) + a.logger.Debug("protobuf file", zap.String("path", pbFilePath)) - if resp != nil && resp.StatusCode == http.StatusUnprocessableEntity { - filledVariables, err := a.askForMissingVariables(resp) - if err != nil { - return err - } + pbFile, err := fileutil.Read(pbFilePath) + if err != nil { + return test, fmt.Errorf(`cannot read protobuf file: %w`, err) + } + a.logger.Debug("protobuf file contents", zap.String("contents", string(pbFile.Contents()))) + + test.Spec.Trigger.Grpc.SetProtobufFile(string(pbFile.Contents())) - params.EnvironmentVariables = filledVariables + return test, nil +} - return a.runDefinitionFile(ctx, f, params) +func (a runTestAction) applyTransaction(ctx context.Context, df defFile) (defFile, error) { + df, err := a.injectLocalEnvVars(ctx, df) + if err != nil { + return df, fmt.Errorf("cannot inject local env vars: %w", err) } + var tran openapi.TransactionResource + err = yaml.Unmarshal(df.Contents(), &tran) if err != nil { - return fmt.Errorf("could not execute definition: %w", err) + a.logger.Error("error parsing transaction", zap.String("content", string(df.Contents())), zap.Error(err)) + return df, fmt.Errorf("could not unmarshal transaction yaml: %w", err) } - if resp.StatusCode == http.StatusCreated && !f.HasID() { - f, err = f.SetID(body.GetId()) - if err != nil { - return fmt.Errorf("could not update definition file: %w", err) - } + tran, err = a.mapTransactionSteps(ctx, df, tran) + if err != nil { + return df, fmt.Errorf("could not map transaction steps: %w", err) + } - _, err = f.Write() - if err != nil { - return fmt.Errorf("could not update definition file: %w", err) - } + marshalled, err := yaml.Marshal(tran) + if err != nil { + return df, fmt.Errorf("could not marshal test yaml: %w", err) } + df = defFile{fileutil.New(df.AbsPath(), marshalled)} - runID := getTestRunIDFromString(body.GetRunId()) - a.logger.Debug( - "executed", - zap.Int32("runID", runID), - zap.String("runType", body.GetType()), + a.logger.Debug("applying transaction", + zap.String("absolutePath", df.AbsPath()), + zap.String("id", tran.Spec.GetId()), + zap.String("marshalled", string(marshalled)), ) - switch body.GetType() { - case "Test": - test, err := a.getTest(ctx, body.GetId()) + updated, err := a.transactions.Apply(ctx, df.File, a.yamlFormat) + if err != nil { + return df, fmt.Errorf("could not read transaction file: %w", err) + } + + df = defFile{fileutil.New(df.AbsPath(), []byte(updated))} + + err = yaml.Unmarshal(df.Contents(), &tran) + if err != nil { + a.logger.Error("error parsing updated transaction", zap.String("content", updated), zap.Error(err)) + return df, fmt.Errorf("could not unmarshal transaction yaml: %w", err) + } + + a.logger.Debug("transaction applied", + zap.String("absolutePath", df.AbsPath()), + zap.String("updated id", tran.Spec.GetId()), + ) + + return df, nil +} + +func (a runTestAction) mapTransactionSteps(ctx context.Context, df defFile, tran openapi.TransactionResource) (openapi.TransactionResource, error) { + for i, step := range tran.Spec.GetSteps() { + a.logger.Debug("mapping transaction step", + zap.Int("index", i), + zap.String("step", step), + ) + if !fileutil.LooksLikeFilePath(step) { + a.logger.Debug("does not look like a file path", + zap.Int("index", i), + zap.String("step", step), + ) + continue + } + + f, err := fileutil.Read(df.RelativeFile(step)) if err != nil { - return fmt.Errorf("could not get test info: %w", err) + return openapi.TransactionResource{}, fmt.Errorf("cannot read test file: %w", err) } - return a.testRun(ctx, test, runID, params) - case "Transaction": - test, err := a.getTransaction(ctx, body.GetId()) + + testDF, err := a.applyTest(ctx, defFile{f}) if err != nil { - return fmt.Errorf("could not get test info: %w", err) + return openapi.TransactionResource{}, fmt.Errorf("cannot apply test '%s': %w", step, err) } - return a.transactionRun(ctx, test, runID, params) + + var test openapi.TestResource + err = yaml.Unmarshal(testDF.Contents(), &test) + if err != nil { + return openapi.TransactionResource{}, fmt.Errorf("cannot unmarshal updated test '%s': %w", step, err) + } + + a.logger.Debug("mapped transaction step", + zap.Int("index", i), + zap.String("step", step), + zap.String("mapped step", test.Spec.GetId()), + ) + + tran.Spec.Steps[i] = test.Spec.GetId() } - return fmt.Errorf(`unsuported run type "%s"`, body.GetType()) + return tran, nil } -func (a runTestAction) askForMissingVariables(resp *http.Response) (map[string]string, error) { - body, err := ioutil.ReadAll(resp.Body) +func getTypeFromFile(df defFile) (string, error) { + var raw map[string]any + err := yaml.Unmarshal(df.Contents(), &raw) if err != nil { - return map[string]string{}, fmt.Errorf("could not read response body: %w", err) + return "", fmt.Errorf("cannot unmarshal definition file: %w", err) } - var missingVariablesError openapi.MissingVariablesError - err = json.Unmarshal(body, &missingVariablesError) - if err != nil { - return map[string]string{}, fmt.Errorf("could not unmarshal response: %w", err) + if raw["type"] == nil { + return "", fmt.Errorf("missing type in definition file") } - uniqueMissingVariables := map[string]string{} - for _, missingVariables := range missingVariablesError.MissingVariables { - for _, variable := range missingVariables.Variables { - defaultValue := "" - if variable.DefaultValue != nil { - defaultValue = *variable.DefaultValue - } - uniqueMissingVariables[*variable.Key] = defaultValue - } + defType, ok := raw["type"].(string) + if !ok { + return "", fmt.Errorf("type is not a string") } - if len(uniqueMissingVariables) > 0 { - ui.DefaultUI.Warning("Some variables are required by one or more tests") - ui.DefaultUI.Info("Fill the values for each variable:") - } + return defType, nil - filledVariables := map[string]string{} +} - for variableName, variableDefaultValue := range uniqueMissingVariables { - value := ui.DefaultUI.TextInput(variableName, variableDefaultValue) - filledVariables[variableName] = value +type envVar struct { + Name string + DefaultValue string + UserValue string +} + +func (ev envVar) value() string { + if ev.UserValue != "" { + return ev.UserValue } - return filledVariables, nil + return ev.DefaultValue } -func (a runTestAction) getTransaction(ctx context.Context, id string) (openapi.Transaction, error) { - a.client.GetConfig().AddDefaultHeader("X-Tracetest-Augmented", "true") - transaction, _, err := a.client.ResourceApiApi. - GetTransaction(ctx, id). - Execute() +type envVars []envVar + +func (evs envVars) toOpenapi() []openapi.EnvironmentValue { + vars := make([]openapi.EnvironmentValue, len(evs)) + for i, ev := range evs { + vars[i] = openapi.EnvironmentValue{ + Key: openapi.PtrString(ev.Name), + Value: openapi.PtrString(ev.value()), + } + } - // reset augmented header - delete(a.client.GetConfig().DefaultHeader, "X-Tracetest-Augmented") + return vars +} - if err != nil { - return openapi.Transaction{}, fmt.Errorf("could not execute request: %w", err) +func (evs envVars) unique() envVars { + seen := make(map[string]bool) + vars := make(envVars, 0, len(evs)) + for _, ev := range evs { + if seen[ev.Name] { + continue + } + + seen[ev.Name] = true + vars = append(vars, ev) } - return transaction.GetSpec(), nil + return vars } -func (a runTestAction) getTest(ctx context.Context, id string) (openapi.Test, error) { - // test, _, err := a.client.ApiApi. - // GetTest(ctx, id). - // Execute() - // if err != nil { - // return openapi.Test{}, fmt.Errorf("could not execute request: %w", err) - // } +type missingEnvVarsError envVars + +func (e missingEnvVarsError) Error() string { + return fmt.Sprintf("missing env vars: %v", []envVar(e)) +} - // return *test, nil - return openapi.Test{}, nil +type runResult struct { + ResourceType string + Resource any + Run any } -func (a runTestAction) testRun(ctx context.Context, test openapi.Test, runID int32, params runDefParams) error { - a.logger.Debug("run test", zap.Bool("wait-for-results", params.WaitForResult)) - testID := test.GetId() - testRun, err := a.getTestRun(ctx, testID, runID) +func (a runTestAction) run(ctx context.Context, df defFile, envID string, ev envVars) (runResult, error) { + res := runResult{} + + defType, err := getTypeFromFile(df) if err != nil { - return fmt.Errorf("could not run test: %w", err) + return res, fmt.Errorf("cannot get type from file: %w", err) } + res.ResourceType = defType - if params.WaitForResult { - updatedTestRun, err := a.waitForTestResult(ctx, testID, getTestRunID(testRun)) + a.logger.Debug("running definition", + zap.String("type", defType), + zap.String("envID", envID), + zap.Any("envVars", ev), + ) + + runInfo := openapi.RunInformation{ + EnvironmentId: openapi.PtrString(envID), + Variables: ev.toOpenapi(), + Metadata: getMetadata(), + } + + switch defType { + case "Test": + var test openapi.TestResource + err = yaml.Unmarshal(df.Contents(), &test) if err != nil { - return fmt.Errorf("could not wait for result: %w", err) + a.logger.Error("error parsing test", zap.String("content", string(df.Contents())), zap.Error(err)) + return res, fmt.Errorf("could not unmarshal test yaml: %w", err) } - testRun = updatedTestRun + req := a.openapiClient.ApiApi. + RunTest(ctx, test.Spec.GetId()). + RunInformation(runInfo) - if err := a.saveJUnitFile(ctx, testID, getTestRunID(testRun), params.JunitFile); err != nil { - return fmt.Errorf("could not save junit file: %w", err) + a.logger.Debug("running test", zap.String("id", test.Spec.GetId())) + + run, resp, err := a.openapiClient.ApiApi.RunTestExecute(req) + err = a.handleRunError(resp, err) + if err != nil { + return res, err } - } - tro := formatters.TestRunOutput{ - HasResults: params.WaitForResult, - Test: test, - Run: testRun, - } + full, err := a.tests.Get(ctx, test.Spec.GetId(), a.jsonFormat) + if err != nil { + return res, fmt.Errorf("cannot get full test '%s': %w", test.Spec.GetId(), err) + } + err = json.Unmarshal([]byte(full), &test) + if err != nil { + return res, fmt.Errorf("cannot get full test '%s': %w", test.Spec.GetId(), err) + } - formatter := formatters.TestRun(a.config, true) - formattedOutput := formatter.Format(tro) - fmt.Print(formattedOutput) + res.Resource = test + res.Run = *run - allPassed := tro.Run.Result.GetAllPassed() - if params.WaitForResult && !allPassed { - // It failed, so we have to return an error status - a.cliExit(1) - } + case "Transaction": + var tran openapi.TransactionResource + err = yaml.Unmarshal(df.Contents(), &tran) + if err != nil { + a.logger.Error("error parsing transaction", zap.String("content", string(df.Contents())), zap.Error(err)) + return res, fmt.Errorf("could not unmarshal transaction yaml: %w", err) + } - return nil -} + req := a.openapiClient.ApiApi. + RunTransaction(ctx, tran.Spec.GetId()). + RunInformation(runInfo) -func (a runTestAction) transactionRun(ctx context.Context, transaction openapi.Transaction, rid int32, params runDefParams) error { - a.logger.Debug("run transaction", zap.Bool("wait-for-results", params.WaitForResult)) - transactionID := transaction.GetId() - transactionRun, err := a.getTransactionRun(ctx, transactionID, int32(rid)) - if err != nil { - return fmt.Errorf("could not run transaction: %w", err) - } + a.logger.Debug("running transaction", zap.String("id", tran.Spec.GetId())) - if params.WaitForResult { - updatedTestRun, err := a.waitForTransactionResult(ctx, transactionID, transactionRun.GetId()) + run, resp, err := a.openapiClient.ApiApi.RunTransactionExecute(req) + err = a.handleRunError(resp, err) if err != nil { - return fmt.Errorf("could not wait for result: %w", err) + return res, err } - transactionRun = updatedTestRun + full, err := a.transactions.Get(ctx, tran.Spec.GetId(), a.jsonFormat) + if err != nil { + return res, fmt.Errorf("cannot get full transaction '%s': %w", tran.Spec.GetId(), err) + } + err = json.Unmarshal([]byte(full), &tran) + if err != nil { + return res, fmt.Errorf("cannot get full transaction '%s': %w", tran.Spec.GetId(), err) + } + + res.Resource = tran + res.Run = *run + default: + return res, fmt.Errorf("unknown type: %s", defType) } - tro := formatters.TransactionRunOutput{ - HasResults: params.WaitForResult, - Transaction: transaction, - Run: transactionRun, + a.logger.Debug("definition run", + zap.String("type", defType), + zap.String("envID", envID), + zap.Any("envVars", ev), + zap.Any("response", res), + ) + + return res, nil +} + +func (a runTestAction) handleRunError(resp *http.Response, reqErr error) error { + body, err := io.ReadAll(resp.Body) + if err != nil { + return fmt.Errorf("could not read response body: %w", err) } + resp.Body.Close() - formatter := formatters.TransactionRun(a.config, true) - formattedOutput := formatter.Format(tro) - fmt.Print(formattedOutput) + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("resource not found in server") + } - if params.WaitForResult { - if utils.RunStateIsFailed(tro.Run.GetState()) { - // It failed, so we have to return an error status - a.cliExit(1) - } + if resp.StatusCode == http.StatusUnprocessableEntity { + return buildMissingEnvVarsError(body) + } - for _, step := range tro.Run.Steps { - if !step.Result.GetAllPassed() { - // if any test doesn't pass, fail the transaction execution - a.cliExit(1) - } - } + if reqErr != nil { + a.logger.Error("error running transaction", zap.Error(err), zap.String("body", string(body))) + return fmt.Errorf("could not run transaction: %w", err) } return nil } -func (a runTestAction) saveJUnitFile(ctx context.Context, testId string, testRunId int32, outputFile string) error { - if outputFile == "" { - return nil +func buildMissingEnvVarsError(body []byte) error { + var missingVarsErrResp openapi.MissingVariablesError + err := json.Unmarshal(body, &missingVarsErrResp) + if err != nil { + return fmt.Errorf("could not unmarshal response body: %w", err) } - req := a.client.ApiApi.GetRunResultJUnit(ctx, testId, testRunId) - junit, _, err := a.client.ApiApi.GetRunResultJUnitExecute(req) - if err != nil { - return fmt.Errorf("could not execute request: %w", err) + missingVars := envVars{} + + for _, missingVarErr := range missingVarsErrResp.MissingVariables { + for _, missingVar := range missingVarErr.Variables { + missingVars = append(missingVars, envVar{ + Name: missingVar.GetKey(), + DefaultValue: missingVar.GetDefaultValue(), + }) + } } - f, err := os.Create(outputFile) - if err != nil { - return fmt.Errorf("could not create junit output file: %w", err) + return missingEnvVarsError(missingVars.unique()) +} + +func (a runTestAction) askForMissingVars(missingVars []envVar) []envVar { + ui.DefaultUI.Warning("Some variables are required by one or more tests") + ui.DefaultUI.Info("Fill the values for each variable:") + + filledVariables := make([]envVar, 0, len(missingVars)) + + for _, missingVar := range missingVars { + answer := missingVar + answer.UserValue = ui.DefaultUI.TextInput(missingVar.Name, missingVar.DefaultValue) + filledVariables = append(filledVariables, answer) } - _, err = f.WriteString(junit) + a.logger.Debug("filled variables", zap.Any("variables", filledVariables)) - return err + return filledVariables +} +func (a runTestAction) formatResult(result runResult, hasResults bool) string { + switch result.ResourceType { + case "Test": + return a.formatTestResult(result, hasResults) + case "Transaction": + return a.formatTransactionResult(result, hasResults) + } + return "" } -func (a runTestAction) getTestRun(ctx context.Context, testID string, runID int32) (openapi.TestRun, error) { - run, _, err := a.client.ApiApi. - GetTestRun(ctx, testID, runID). - Execute() - if err != nil { - return openapi.TestRun{}, fmt.Errorf("could not execute request: %w", err) +func (a runTestAction) formatTestResult(result runResult, hasResults bool) string { + test := result.Resource.(openapi.TestResource) + run := result.Run.(openapi.TestRun) + + tro := formatters.TestRunOutput{ + HasResults: hasResults, + Test: test.GetSpec(), + Run: run, } - return *run, nil + formatter := formatters.TestRun(a.config, true) + return formatter.Format(tro) } +func (a runTestAction) formatTransactionResult(result runResult, hasResults bool) string { + tran := result.Resource.(openapi.TransactionResource) + run := result.Run.(openapi.TransactionRun) -func (a runTestAction) getTransactionRun(ctx context.Context, transactionID string, runID int32) (openapi.TransactionRun, error) { - run, _, err := a.client.ApiApi. - GetTransactionRun(ctx, transactionID, runID). - Execute() - if err != nil { - return openapi.TransactionRun{}, fmt.Errorf("could not execute request: %w", err) + tro := formatters.TransactionRunOutput{ + HasResults: hasResults, + Transaction: tran.GetSpec(), + Run: run, } - return *run, nil + return formatters. + TransactionRun(a.config, true). + Format(tro) } -func (a runTestAction) waitForTestResult(ctx context.Context, testID string, testRunID int32) (openapi.TestRun, error) { +func (a runTestAction) waitForResult(ctx context.Context, run runResult) (runResult, error) { + switch run.ResourceType { + case "Test": + tr, err := a.waitForTestResult(ctx, run) + if err != nil { + return run, err + } + + run.Run = tr + return run, nil + + case "Transaction": + tr, err := a.waitForTransactionResult(ctx, run) + if err != nil { + return run, err + } + + run.Run = tr + return run, nil + } + return run, fmt.Errorf("unknown resource type: %s", run.ResourceType) +} + +func (a runTestAction) waitForTestResult(ctx context.Context, result runResult) (openapi.TestRun, error) { var ( testRun openapi.TestRun lastError error wg sync.WaitGroup ) + + test := result.Resource.(openapi.TestResource) + run := result.Run.(openapi.TestRun) + wg.Add(1) ticker := time.NewTicker(1 * time.Second) // TODO: change to websockets go func() { - for { - select { - case <-ticker.C: - readyTestRun, err := a.isTestReady(ctx, testID, testRunID) - if err != nil { - lastError = err - wg.Done() - return - } - - if readyTestRun != nil { - testRun = *readyTestRun - wg.Done() - return - } + for range ticker.C { + readyTestRun, err := a.isTestReady(ctx, test.Spec.GetId(), run.GetId()) + if err != nil { + lastError = err + wg.Done() + return + } + + if readyTestRun != nil { + testRun = *readyTestRun + wg.Done() + return } } }() @@ -526,30 +742,50 @@ func (a runTestAction) waitForTestResult(ctx context.Context, testID string, tes return testRun, nil } -func (a runTestAction) waitForTransactionResult(ctx context.Context, transactionID, transactionRunID string) (openapi.TransactionRun, error) { +func (a runTestAction) isTestReady(ctx context.Context, testID string, testRunID string) (*openapi.TestRun, error) { + runID, err := strconv.Atoi(testRunID) + if err != nil { + return nil, fmt.Errorf("invalid transaction run id format: %w", err) + } + + req := a.openapiClient.ApiApi.GetTestRun(ctx, testID, int32(runID)) + run, _, err := a.openapiClient.ApiApi.GetTestRunExecute(req) + if err != nil { + return &openapi.TestRun{}, fmt.Errorf("could not execute GetTestRun request: %w", err) + } + + if utils.RunStateIsFinished(run.GetState()) { + return run, nil + } + + return nil, nil +} + +func (a runTestAction) waitForTransactionResult(ctx context.Context, result runResult) (openapi.TransactionRun, error) { var ( transactionRun openapi.TransactionRun lastError error wg sync.WaitGroup ) + + tran := result.Resource.(openapi.TransactionResource) + run := result.Run.(openapi.TransactionRun) + wg.Add(1) ticker := time.NewTicker(1 * time.Second) // TODO: change to websockets go func() { - for { - select { - case <-ticker.C: - readyTransactionRun, err := a.isTransactionReady(ctx, transactionID, transactionRunID) - if err != nil { - lastError = err - wg.Done() - return - } - - if readyTransactionRun != nil { - transactionRun = *readyTransactionRun - wg.Done() - return - } + for range ticker.C { + readyTransactionRun, err := a.isTransactionReady(ctx, tran.Spec.GetId(), run.GetId()) + if err != nil { + lastError = err + wg.Done() + return + } + + if readyTransactionRun != nil { + transactionRun = *readyTransactionRun + wg.Done() + return } } }() @@ -562,11 +798,16 @@ func (a runTestAction) waitForTransactionResult(ctx context.Context, transaction return transactionRun, nil } -func (a runTestAction) isTestReady(ctx context.Context, testID string, testRunId int32) (*openapi.TestRun, error) { - req := a.client.ApiApi.GetTestRun(ctx, testID, testRunId) - run, _, err := a.client.ApiApi.GetTestRunExecute(req) +func (a runTestAction) isTransactionReady(ctx context.Context, transactionID, transactionRunID string) (*openapi.TransactionRun, error) { + runID, err := strconv.Atoi(transactionRunID) if err != nil { - return &openapi.TestRun{}, fmt.Errorf("could not execute GetTestRun request: %w", err) + return nil, fmt.Errorf("invalid transaction run id format: %w", err) + } + + req := a.openapiClient.ApiApi.GetTransactionRun(ctx, transactionID, int32(runID)) + run, _, err := a.openapiClient.ApiApi.GetTransactionRunExecute(req) + if err != nil { + return nil, fmt.Errorf("could not execute GetTestRun request: %w", err) } if utils.RunStateIsFinished(run.GetState()) { @@ -576,26 +817,32 @@ func (a runTestAction) isTestReady(ctx context.Context, testID string, testRunId return nil, nil } -func (a runTestAction) isTransactionReady(ctx context.Context, transactionID, transactionRunId string) (*openapi.TransactionRun, error) { - runId, err := strconv.Atoi(transactionRunId) +func (a runTestAction) writeJUnitReport(ctx context.Context, result runResult, outputFile string) error { + test := result.Resource.(openapi.TestResource) + run := result.Run.(openapi.TestRun) + runID, err := strconv.Atoi(run.GetId()) if err != nil { - return nil, fmt.Errorf("invalid transaction run id format: %w", err) + return fmt.Errorf("invalid run id format: %w", err) } - req := a.client.ApiApi.GetTransactionRun(ctx, transactionID, int32(runId)) - run, _, err := a.client.ApiApi.GetTransactionRunExecute(req) + req := a.openapiClient.ApiApi.GetRunResultJUnit(ctx, test.Spec.GetId(), int32(runID)) + junit, _, err := a.openapiClient.ApiApi.GetRunResultJUnitExecute(req) if err != nil { - return nil, fmt.Errorf("could not execute GetTestRun request: %w", err) + return fmt.Errorf("could not execute request: %w", err) } - if utils.RunStateIsFinished(run.GetState()) { - return run, nil + f, err := os.Create(junit) + if err != nil { + return fmt.Errorf("could not create junit output file: %w", err) } - return nil, nil + _, err = f.WriteString(outputFile) + + return err + } -func (a runTestAction) getMetadata() map[string]string { +func getMetadata() map[string]string { ci := cienvironment.DetectCIEnvironment() if ci == nil { return map[string]string{} @@ -616,44 +863,6 @@ func (a runTestAction) getMetadata() map[string]string { return metadata } -func getTestRunIDFromString(testRunIDAsString string) int32 { - testRunID, _ := strconv.Atoi(testRunIDAsString) - return int32(testRunID) -} - -func getTestRunID(testRun openapi.TestRun) int32 { - return getTestRunIDFromString(testRun.GetId()) -} - -func getUpdatedTestWithGrpcTrigger(f *file.File, t yaml.Test) (*file.File, error) { - protobufFile := filepath.Join(f.AbsDir(), t.Trigger.GRPC.ProtobufFile) - - if !fileutil.IsFilePath(protobufFile) { - return nil, nil - } - - // referencing a file, keep the value - fileContent, err := os.ReadFile(protobufFile) - if err != nil { - return nil, fmt.Errorf(`cannot read protobuf file: %w`, err) - } - - t.Trigger.GRPC.ProtobufFile = string(fileContent) - - def := yaml.File{ - Type: yaml.FileTypeTest, - Spec: t, - } - - updated, err := def.Encode() - if err != nil { - return nil, fmt.Errorf(`cannot encode updated test: %w`, err) - } - - f, err = file.New(f.Path(), updated) - if err != nil { - return nil, fmt.Errorf(`cannot recreate updated file: %w`, err) - } - - return f, nil +type defFile struct { + fileutil.File } diff --git a/cli/actions/tests.go b/cli/actions/tests.go deleted file mode 100644 index 1e86cca23a..0000000000 --- a/cli/actions/tests.go +++ /dev/null @@ -1,118 +0,0 @@ -package actions - -import ( - "context" - "fmt" - - "github.com/kubeshop/tracetest/cli/file" - "github.com/kubeshop/tracetest/cli/openapi" - "github.com/kubeshop/tracetest/cli/utils" - "github.com/kubeshop/tracetest/server/model/yaml" - "github.com/mitchellh/mapstructure" -) - -type testActions struct { - resourceArgs -} - -var _ ResourceActions = &testActions{} - -func NewTestActions(options ...ResourceArgsOption) testActions { - args := NewResourceArgs(options...) - - return testActions{ - resourceArgs: args, - } -} - -func (testActions) FileType() yaml.FileType { - return yaml.FileTypeEnvironment -} - -func (testActions) Name() string { - return "test" -} - -func (action testActions) GetID(file *file.File) (string, error) { - resource, err := action.formatter.ToStruct(file) - if err != nil { - return "", err - } - - return resource.(openapi.TestResource).Spec.GetId(), nil -} - -func (test testActions) Apply(ctx context.Context, fileContent file.File) (result *file.File, err error) { - envResource := openapi.TestResource{ - Spec: &openapi.Test{}, - } - - mapstructure.Decode(fileContent.Definition().Spec, &envResource.Spec) - - return test.resourceClient.Upsert(ctx, fileContent) -} - -func (test testActions) List(ctx context.Context, listArgs utils.ListArgs) (*file.File, error) { - return test.resourceClient.List(ctx, listArgs) -} - -func (test testActions) Delete(ctx context.Context, ID string) (string, error) { - return "Test successfully deleted", test.resourceClient.Delete(ctx, ID) -} - -func (test testActions) Get(ctx context.Context, ID string) (*file.File, error) { - return test.resourceClient.Get(ctx, ID) -} - -func (test testActions) ApplyResource(ctx context.Context, resource openapi.TestResource) (*file.File, error) { - content, err := resource.MarshalJSON() - if err != nil { - return nil, fmt.Errorf("could not marshal test: %w", err) - } - - file, err := file.NewFromRaw("test.yaml", content) - if err != nil { - return nil, fmt.Errorf("could not create test file: %w", err) - } - - return test.Apply(ctx, file) -} - -// func (action testActions) FromFile(ctx context.Context, filePath string) (openapi.TestResource, error) { -// if !utils.StringReferencesFile(filePath) { -// return openapi.TestResource{}, fmt.Errorf(`env file "%s" does not exist`, filePath) -// } - -// fileContent, err := ioutil.ReadFile(filePath) -// if err != nil { -// return openapi.TestResource{}, fmt.Errorf(`cannot read env file "%s": %w`, filePath, err) -// } - -// model, err := yaml.Decode(fileContent) -// if err != nil { -// return openapi.TestResource{}, fmt.Errorf(`cannot parse env file "%s": %w`, filePath, err) -// } - -// envModel := model.Spec.(test.) - -// values := make([]openapi.EnvironmentValue, 0, len(envModel.Values)) -// for _, value := range envModel.Values { -// v := value -// values = append(values, openapi.EnvironmentValue{ -// Key: &v.Key, -// Value: &v.Value, -// }) -// } - -// TestResource := openapi.TestResource{ -// Type: (*string)(&model.Type), -// Spec: &openapi.Environment{ -// Id: openapi.PtrString(envModel.ID.String()), -// Name: &envModel.Name, -// Description: &envModel.Description, -// Values: values, -// }, -// } - -// return TestResource, nil -// } diff --git a/cli/cmd/apply_cmd.go b/cli/cmd/apply_cmd.go index cee504e989..06ffc62551 100644 --- a/cli/cmd/apply_cmd.go +++ b/cli/cmd/apply_cmd.go @@ -2,7 +2,9 @@ package cmd import ( "context" + "fmt" + "github.com/kubeshop/tracetest/cli/pkg/fileutil" "github.com/kubeshop/tracetest/cli/pkg/resourcemanager" "github.com/spf13/cobra" ) @@ -33,7 +35,12 @@ func init() { return "", err } - result, err := resourceClient.Apply(ctx, applyParams.DefinitionFile, resultFormat) + inputFile, err := fileutil.Read(applyParams.DefinitionFile) + if err != nil { + return "", fmt.Errorf("cannot read file %s: %w", applyParams.DefinitionFile, err) + } + + result, err := resourceClient.Apply(ctx, inputFile, resultFormat) if err != nil { return "", err } diff --git a/cli/cmd/config.go b/cli/cmd/config.go index 1f8946054b..2922a4ae9e 100644 --- a/cli/cmd/config.go +++ b/cli/cmd/config.go @@ -200,20 +200,6 @@ var resources = resourcemanager.NewRegistry(). }, }), ), - ). - Register( - resourcemanager.NewClient( - httpClient, - "test", "tests", - resourcemanager.WithTableConfig(resourcemanager.TableConfig{ - Cells: []resourcemanager.TableCellConfig{ - {Header: "ID", Path: "spec.id"}, - {Header: "NAME", Path: "spec.name"}, - {Header: "VERSION", Path: "spec.version"}, - // TODO: add the rest of the fields here - }, - }), - ), ) func resourceList() string { diff --git a/cli/cmd/test_run_cmd.go b/cli/cmd/test_run_cmd.go index 3f54329f75..8b34971cbc 100644 --- a/cli/cmd/test_run_cmd.go +++ b/cli/cmd/test_run_cmd.go @@ -35,7 +35,20 @@ var testRunCmd = &cobra.Command{ return "", fmt.Errorf("failed to get test client: %w", err) } - runTestAction := actions.NewRunTestAction(cliConfig, cliLogger, client, testClient, envClient, ExitCLI) + transactionsClient, err := resources.Get("transaction") + if err != nil { + return "", fmt.Errorf("failed to get transaction client: %w", err) + } + + runTestAction := actions.NewRunTestAction( + cliConfig, + cliLogger, + client, + testClient, + transactionsClient, + envClient, + ExitCLI, + ) actionArgs := actions.RunResourceArgs{ DefinitionFile: runTestFileDefinition, EnvID: runTestEnvID, diff --git a/cli/formatters/formatter.go b/cli/formatters/formatter.go deleted file mode 100644 index 79006188e0..0000000000 --- a/cli/formatters/formatter.go +++ /dev/null @@ -1,76 +0,0 @@ -package formatters - -import ( - "fmt" - - "github.com/alexeyco/simpletable" - "github.com/kubeshop/tracetest/cli/file" -) - -type ToStruct func(*file.File) (interface{}, error) -type ToListStruct func(*file.File) ([]interface{}, error) - -type ToTable func(*file.File) (*simpletable.Header, *simpletable.Body, error) -type ToListTable ToTable - -type ResourceFormatter interface { - ToTable(*file.File) (*simpletable.Header, *simpletable.Body, error) - ToListTable(*file.File) (*simpletable.Header, *simpletable.Body, error) - ToStruct(*file.File) (interface{}, error) - ToListStruct(*file.File) ([]interface{}, error) -} - -type FormatterInterface interface { - Format(*file.File) (string, error) - FormatList(*file.File) (string, error) - Type() string -} - -type Formatter struct { - formatType string - registry map[string]FormatterInterface -} - -func NewFormatter(formatType string, formatters ...FormatterInterface) Formatter { - registry := make(map[string]FormatterInterface, len(formatters)) - - for _, option := range formatters { - registry[option.Type()] = option - } - - return Formatter{formatType, registry} -} - -func (f Formatter) Format(file *file.File) (string, error) { - formatter, ok := f.registry[f.formatType] - if !ok { - return "", fmt.Errorf("formatter %s not found", f.formatType) - } - - return formatter.Format(file) -} - -func (f Formatter) FormatList(file *file.File) (string, error) { - formatter, ok := f.registry[f.formatType] - if !ok { - return "", fmt.Errorf("formatter %s not found", f.formatType) - } - - return formatter.FormatList(file) -} - -func BuildFormatter(formatType string, defaultType Output, resourceFormatter ResourceFormatter) Formatter { - jsonFormatter := NewJson(resourceFormatter) - yamlFormatter := NewYaml(resourceFormatter) - tableFormatter := NewTable(resourceFormatter) - - if defaultType == "" { - defaultType = YAML - } - - if formatType == "" { - formatType = string(defaultType) - } - - return NewFormatter(formatType, jsonFormatter, yamlFormatter, tableFormatter) -} diff --git a/cli/formatters/json.go b/cli/formatters/json.go deleted file mode 100644 index f04debb8fa..0000000000 --- a/cli/formatters/json.go +++ /dev/null @@ -1,54 +0,0 @@ -package formatters - -import ( - "encoding/json" - "fmt" - - "github.com/kubeshop/tracetest/cli/file" -) - -type Json struct { - toStructFn ToStruct - toListStructFn ToListStruct -} - -var _ FormatterInterface = Json{} - -func NewJson(resourceFormatter ResourceFormatter) Json { - return Json{ - toStructFn: resourceFormatter.ToStruct, - toListStructFn: resourceFormatter.ToListStruct, - } -} - -func (j Json) Type() string { - return "json" -} - -func (j Json) Format(file *file.File) (string, error) { - data, err := j.toStructFn(file) - if err != nil { - return "", fmt.Errorf("could not convert file to struct: %w", err) - } - - bytes, err := json.MarshalIndent(data, "", " ") - if err != nil { - return "", fmt.Errorf("could not marshal output json: %w", err) - } - - return string(bytes), nil -} - -func (j Json) FormatList(file *file.File) (string, error) { - data, err := j.toListStructFn(file) - if err != nil { - return "", fmt.Errorf("could not convert file to struct: %w", err) - } - - bytes, err := json.MarshalIndent(data, "", " ") - if err != nil { - return "", fmt.Errorf("could not marshal output json: %w", err) - } - - return string(bytes), nil -} diff --git a/cli/formatters/table.go b/cli/formatters/table.go deleted file mode 100644 index 896341d70d..0000000000 --- a/cli/formatters/table.go +++ /dev/null @@ -1,54 +0,0 @@ -package formatters - -import ( - "github.com/alexeyco/simpletable" - "github.com/kubeshop/tracetest/cli/file" -) - -type Table struct { - toTableFn ToTable - toListTableFn ToListTable -} - -var _ FormatterInterface = Table{} - -func NewTable(resourceFormatter ResourceFormatter) Table { - return Table{ - toTableFn: resourceFormatter.ToTable, - toListTableFn: resourceFormatter.ToListTable, - } -} - -func (t Table) Type() string { - return "pretty" -} - -func (t Table) Format(file *file.File) (string, error) { - table := simpletable.New() - - header, body, err := t.toTableFn(file) - if err != nil { - return "", err - } - - table.Header = header - table.Body = body - - table.SetStyle(simpletable.StyleCompactLite) - return table.String(), nil -} - -func (t Table) FormatList(file *file.File) (string, error) { - table := simpletable.New() - - header, body, err := t.toListTableFn(file) - if err != nil { - return "", err - } - - table.Header = header - table.Body = body - - table.SetStyle(simpletable.StyleCompactLite) - return table.String(), nil -} diff --git a/cli/formatters/yaml.go b/cli/formatters/yaml.go deleted file mode 100644 index 8fa778563a..0000000000 --- a/cli/formatters/yaml.go +++ /dev/null @@ -1,60 +0,0 @@ -package formatters - -import ( - "fmt" - - "github.com/goccy/go-yaml" - - "github.com/kubeshop/tracetest/cli/file" -) - -type Yaml struct { - toStructFn ToStruct - toListStructFn ToListStruct -} - -var _ FormatterInterface = Yaml{} - -func NewYaml(resourceFormatter ResourceFormatter) Yaml { - return Yaml{ - toStructFn: resourceFormatter.ToStruct, - toListStructFn: resourceFormatter.ToListStruct, - } -} - -func (Yaml) Type() string { - return "yaml" -} - -func (y Yaml) FormatList(file *file.File) (string, error) { - data, err := y.toListStructFn(file) - if err != nil { - return "", fmt.Errorf("could not convert file to struct: %w", err) - } - - result := "" - for _, value := range data { - bytes, err := yaml.Marshal(value) - if err != nil { - return "", fmt.Errorf("could not marshal output json: %w", err) - } - - result += "---\n" + string(bytes) + "\n" - } - - return result, nil -} - -func (y Yaml) Format(file *file.File) (string, error) { - data, err := y.toStructFn(file) - if err != nil { - return "", fmt.Errorf("could not convert file to struct: %w", err) - } - - bytes, err := yaml.Marshal(data) - if err != nil { - return "", fmt.Errorf("could not marshal output json: %w", err) - } - - return "---\n" + string(bytes), nil -} diff --git a/cli/go.mod b/cli/go.mod index 01415de841..6193ab6f80 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -6,7 +6,7 @@ require ( github.com/Jeffail/gabs/v2 v2.7.0 github.com/alexeyco/simpletable v1.0.0 github.com/compose-spec/compose-go v1.5.1 - github.com/cucumber/ci-environment/go v0.0.0-20220915001957-711b1c82415f + github.com/cucumber/ci-environment/go v0.0.0-20230703185945-ddbd134c44fd github.com/denisbrodbeck/machineid v1.0.1 github.com/goccy/go-yaml v1.11.0 github.com/kubeshop/tracetest/server v0.0.0-20230512142545-cb5e526e06f9 @@ -14,7 +14,7 @@ require ( github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.15.0 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.8.4 go.uber.org/zap v1.23.0 golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15 gopkg.in/yaml.v3 v3.0.1 diff --git a/cli/go.sum b/cli/go.sum index 6f66f25ac4..bce49c5f95 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -80,8 +80,8 @@ github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkX github.com/containerd/containerd v1.6.18 h1:qZbsLvmyu+Vlty0/Ex5xc0z2YtKpIsb5n45mAMI+2Ns= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cucumber/ci-environment/go v0.0.0-20220915001957-711b1c82415f h1:JoQPsirXW3nGs5shRwidDODWeicHf4CDFaaMzSl9aeE= -github.com/cucumber/ci-environment/go v0.0.0-20220915001957-711b1c82415f/go.mod h1:ND1mBObqeFyxrBaIuDkdtM+2gqNsCrPCMyZ9sfJ97ls= +github.com/cucumber/ci-environment/go v0.0.0-20230703185945-ddbd134c44fd h1:YnPJcbnNHcsFFyckLIynp4B6nvT75GEpH+yOc8aYhhE= +github.com/cucumber/ci-environment/go v0.0.0-20230703185945-ddbd134c44fd/go.mod h1:W5gTLX4+0/cT8vgja6OSH3OsnuNK8HfTOK3PrXyGQ/Q= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -323,8 +323,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 h1:xzABM9let0HLLqFypcxvLmlvEciCHL7+Lv+4vwZqecI= diff --git a/cli/openapi/api_api.go b/cli/openapi/api_api.go index af354c53bd..9e609ec422 100644 --- a/cli/openapi/api_api.go +++ b/cli/openapi/api_api.go @@ -38,10 +38,10 @@ DeleteTestRun delete a test run delete a test run - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @param runId id of the run - @return ApiDeleteTestRunRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @param runId id of the run + @return ApiDeleteTestRunRequest */ func (a *ApiApiService) DeleteTestRun(ctx context.Context, testId string, runId int32) ApiDeleteTestRunRequest { return ApiDeleteTestRunRequest{ @@ -134,10 +134,10 @@ DeleteTransactionRun Delete a specific run from a particular transaction Delete a specific run from a particular transaction - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param transactionId id of the transaction - @param runId id of the run - @return ApiDeleteTransactionRunRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param transactionId id of the transaction + @param runId id of the run + @return ApiDeleteTransactionRunRequest */ func (a *ApiApiService) DeleteTransactionRun(ctx context.Context, transactionId string, runId int32) ApiDeleteTransactionRunRequest { return ApiDeleteTransactionRunRequest{ @@ -236,10 +236,10 @@ DryRunAssertion run given assertions against the traces from the given run witho use this method to test a definition against an actual trace without creating a new version or persisting anything - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @param runId id of the run - @return ApiDryRunAssertionRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @param runId id of the run + @return ApiDryRunAssertionRequest */ func (a *ApiApiService) DryRunAssertion(ctx context.Context, testId string, runId int32) ApiDryRunAssertionRequest { return ApiDryRunAssertionRequest{ @@ -251,7 +251,8 @@ func (a *ApiApiService) DryRunAssertion(ctx context.Context, testId string, runI } // Execute executes the request -// @return AssertionResults +// +// @return AssertionResults func (a *ApiApiService) DryRunAssertionExecute(r ApiDryRunAssertionRequest) (*AssertionResults, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPut @@ -349,8 +350,8 @@ ExecuteDefinition Execute a definition Execute a definition - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiExecuteDefinitionRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiExecuteDefinitionRequest */ func (a *ApiApiService) ExecuteDefinition(ctx context.Context) ApiExecuteDefinitionRequest { return ApiExecuteDefinitionRequest{ @@ -360,7 +361,8 @@ func (a *ApiApiService) ExecuteDefinition(ctx context.Context) ApiExecuteDefinit } // Execute executes the request -// @return ExecuteDefinitionResponse +// +// @return ExecuteDefinitionResponse func (a *ApiApiService) ExecuteDefinitionExecute(r ApiExecuteDefinitionRequest) (*ExecuteDefinitionResponse, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPost @@ -452,10 +454,10 @@ ExportTestRun export test and test run information export test and test run information for debugging - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @param runId id of the run - @return ApiExportTestRunRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @param runId id of the run + @return ApiExportTestRunRequest */ func (a *ApiApiService) ExportTestRun(ctx context.Context, testId string, runId int32) ApiExportTestRunRequest { return ApiExportTestRunRequest{ @@ -467,7 +469,8 @@ func (a *ApiApiService) ExportTestRun(ctx context.Context, testId string, runId } // Execute executes the request -// @return ExportedTestInformation +// +// @return ExportedTestInformation func (a *ApiApiService) ExportTestRunExecute(r ApiExportTestRunRequest) (*ExportedTestInformation, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -563,8 +566,8 @@ ExpressionResolve resolves an expression and returns the result string resolves an expression and returns the result string - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiExpressionResolveRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiExpressionResolveRequest */ func (a *ApiApiService) ExpressionResolve(ctx context.Context) ApiExpressionResolveRequest { return ApiExpressionResolveRequest{ @@ -574,7 +577,8 @@ func (a *ApiApiService) ExpressionResolve(ctx context.Context) ApiExpressionReso } // Execute executes the request -// @return ResolveResponseInfo +// +// @return ResolveResponseInfo func (a *ApiApiService) ExpressionResolveExecute(r ApiExpressionResolveRequest) (*ResolveResponseInfo, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPost @@ -699,8 +703,8 @@ GetResources Get resources get resources - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiGetResourcesRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetResourcesRequest */ func (a *ApiApiService) GetResources(ctx context.Context) ApiGetResourcesRequest { return ApiGetResourcesRequest{ @@ -710,7 +714,8 @@ func (a *ApiApiService) GetResources(ctx context.Context) ApiGetResourcesRequest } // Execute executes the request -// @return []Resource +// +// @return []Resource func (a *ApiApiService) GetResourcesExecute(r ApiGetResourcesRequest) ([]Resource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -815,10 +820,10 @@ GetRunResultJUnit get test run results in JUnit xml format get test run results in JUnit xml format - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @param runId id of the run - @return ApiGetRunResultJUnitRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @param runId id of the run + @return ApiGetRunResultJUnitRequest */ func (a *ApiApiService) GetRunResultJUnit(ctx context.Context, testId string, runId int32) ApiGetRunResultJUnitRequest { return ApiGetRunResultJUnitRequest{ @@ -830,7 +835,8 @@ func (a *ApiApiService) GetRunResultJUnit(ctx context.Context, testId string, ru } // Execute executes the request -// @return string +// +// @return string func (a *ApiApiService) GetRunResultJUnitExecute(r ApiGetRunResultJUnitRequest) (string, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -929,10 +935,10 @@ GetTestResultSelectedSpans retrieve spans that will be selected by selector get the spans ids that would be selected by a specific selector query - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @param runId id of the run - @return ApiGetTestResultSelectedSpansRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @param runId id of the run + @return ApiGetTestResultSelectedSpansRequest */ func (a *ApiApiService) GetTestResultSelectedSpans(ctx context.Context, testId string, runId int32) ApiGetTestResultSelectedSpansRequest { return ApiGetTestResultSelectedSpansRequest{ @@ -944,7 +950,8 @@ func (a *ApiApiService) GetTestResultSelectedSpans(ctx context.Context, testId s } // Execute executes the request -// @return SelectedSpansResult +// +// @return SelectedSpansResult func (a *ApiApiService) GetTestResultSelectedSpansExecute(r ApiGetTestResultSelectedSpansRequest) (*SelectedSpansResult, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1039,10 +1046,10 @@ GetTestRun get test Run get a particular test Run - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @param runId id of the run - @return ApiGetTestRunRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @param runId id of the run + @return ApiGetTestRunRequest */ func (a *ApiApiService) GetTestRun(ctx context.Context, testId string, runId int32) ApiGetTestRunRequest { return ApiGetTestRunRequest{ @@ -1054,7 +1061,8 @@ func (a *ApiApiService) GetTestRun(ctx context.Context, testId string, runId int } // Execute executes the request -// @return TestRun +// +// @return TestRun func (a *ApiApiService) GetTestRunExecute(r ApiGetTestRunRequest) (*TestRun, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1146,10 +1154,10 @@ GetTestRunEvents get events from a test run get events from a test run - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @param runId id of the run - @return ApiGetTestRunEventsRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @param runId id of the run + @return ApiGetTestRunEventsRequest */ func (a *ApiApiService) GetTestRunEvents(ctx context.Context, testId string, runId int32) ApiGetTestRunEventsRequest { return ApiGetTestRunEventsRequest{ @@ -1161,7 +1169,8 @@ func (a *ApiApiService) GetTestRunEvents(ctx context.Context, testId string, run } // Execute executes the request -// @return []TestRunEvent +// +// @return []TestRunEvent func (a *ApiApiService) GetTestRunEventsExecute(r ApiGetTestRunEventsRequest) ([]TestRunEvent, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1266,9 +1275,9 @@ GetTestRuns get the runs for a test get the runs from a particular test - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @return ApiGetTestRunsRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @return ApiGetTestRunsRequest */ func (a *ApiApiService) GetTestRuns(ctx context.Context, testId string) ApiGetTestRunsRequest { return ApiGetTestRunsRequest{ @@ -1279,7 +1288,8 @@ func (a *ApiApiService) GetTestRuns(ctx context.Context, testId string) ApiGetTe } // Execute executes the request -// @return []TestRun +// +// @return []TestRun func (a *ApiApiService) GetTestRunsExecute(r ApiGetTestRunsRequest) ([]TestRun, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1375,9 +1385,9 @@ GetTestSpecs Get definition for a test Gets definition for a test - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @return ApiGetTestSpecsRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @return ApiGetTestSpecsRequest */ func (a *ApiApiService) GetTestSpecs(ctx context.Context, testId string) ApiGetTestSpecsRequest { return ApiGetTestSpecsRequest{ @@ -1388,7 +1398,8 @@ func (a *ApiApiService) GetTestSpecs(ctx context.Context, testId string) ApiGetT } // Execute executes the request -// @return []TestSpecs +// +// @return []TestSpecs func (a *ApiApiService) GetTestSpecsExecute(r ApiGetTestSpecsRequest) ([]TestSpecs, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1479,10 +1490,10 @@ GetTestVersion get a test specific version get a test specific version - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @param version version of the test - @return ApiGetTestVersionRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @param version version of the test + @return ApiGetTestVersionRequest */ func (a *ApiApiService) GetTestVersion(ctx context.Context, testId string, version int32) ApiGetTestVersionRequest { return ApiGetTestVersionRequest{ @@ -1494,7 +1505,8 @@ func (a *ApiApiService) GetTestVersion(ctx context.Context, testId string, versi } // Execute executes the request -// @return Test +// +// @return Test func (a *ApiApiService) GetTestVersionExecute(r ApiGetTestVersionRequest) (*Test, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1586,10 +1598,10 @@ GetTransactionRun Get a specific run from a particular transaction Get a specific run from a particular transaction - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param transactionId id of the transaction - @param runId id of the run - @return ApiGetTransactionRunRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param transactionId id of the transaction + @param runId id of the run + @return ApiGetTransactionRunRequest */ func (a *ApiApiService) GetTransactionRun(ctx context.Context, transactionId string, runId int32) ApiGetTransactionRunRequest { return ApiGetTransactionRunRequest{ @@ -1601,7 +1613,8 @@ func (a *ApiApiService) GetTransactionRun(ctx context.Context, transactionId str } // Execute executes the request -// @return TransactionRun +// +// @return TransactionRun func (a *ApiApiService) GetTransactionRunExecute(r ApiGetTransactionRunRequest) (*TransactionRun, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1706,9 +1719,9 @@ GetTransactionRuns Get all runs from a particular transaction Get all runs from a particular transaction - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param transactionId id of the transaction - @return ApiGetTransactionRunsRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param transactionId id of the transaction + @return ApiGetTransactionRunsRequest */ func (a *ApiApiService) GetTransactionRuns(ctx context.Context, transactionId string) ApiGetTransactionRunsRequest { return ApiGetTransactionRunsRequest{ @@ -1719,7 +1732,8 @@ func (a *ApiApiService) GetTransactionRuns(ctx context.Context, transactionId st } // Execute executes the request -// @return []TransactionRun +// +// @return []TransactionRun func (a *ApiApiService) GetTransactionRunsExecute(r ApiGetTransactionRunsRequest) ([]TransactionRun, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1816,10 +1830,10 @@ GetTransactionVersion get a transaction specific version get a transaction specific version - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param transactionId id of the transaction - @param version version of the test - @return ApiGetTransactionVersionRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param transactionId id of the transaction + @param version version of the test + @return ApiGetTransactionVersionRequest */ func (a *ApiApiService) GetTransactionVersion(ctx context.Context, transactionId string, version int32) ApiGetTransactionVersionRequest { return ApiGetTransactionVersionRequest{ @@ -1831,7 +1845,8 @@ func (a *ApiApiService) GetTransactionVersion(ctx context.Context, transactionId } // Execute executes the request -// @return Transaction +// +// @return Transaction func (a *ApiApiService) GetTransactionVersionExecute(r ApiGetTransactionVersionRequest) (*Transaction, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1923,10 +1938,10 @@ GetTransactionVersionDefinitionFile Get the transaction definition as an YAML fi Get the transaction as an YAML file - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param transactionId id of the transaction - @param version version of the test - @return ApiGetTransactionVersionDefinitionFileRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param transactionId id of the transaction + @param version version of the test + @return ApiGetTransactionVersionDefinitionFileRequest */ func (a *ApiApiService) GetTransactionVersionDefinitionFile(ctx context.Context, transactionId string, version int32) ApiGetTransactionVersionDefinitionFileRequest { return ApiGetTransactionVersionDefinitionFileRequest{ @@ -1938,7 +1953,8 @@ func (a *ApiApiService) GetTransactionVersionDefinitionFile(ctx context.Context, } // Execute executes the request -// @return string +// +// @return string func (a *ApiApiService) GetTransactionVersionDefinitionFileExecute(r ApiGetTransactionVersionDefinitionFileRequest) (string, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -2028,8 +2044,8 @@ GetVersion Get the version of the API Get the version of the API - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiGetVersionRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetVersionRequest */ func (a *ApiApiService) GetVersion(ctx context.Context) ApiGetVersionRequest { return ApiGetVersionRequest{ @@ -2039,7 +2055,8 @@ func (a *ApiApiService) GetVersion(ctx context.Context) ApiGetVersionRequest { } // Execute executes the request -// @return Version +// +// @return Version func (a *ApiApiService) GetVersionExecute(r ApiGetVersionRequest) (*Version, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -2133,8 +2150,8 @@ ImportTestRun import test and test run information import test and test run information for debugging - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiImportTestRunRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiImportTestRunRequest */ func (a *ApiApiService) ImportTestRun(ctx context.Context) ApiImportTestRunRequest { return ApiImportTestRunRequest{ @@ -2144,7 +2161,8 @@ func (a *ApiApiService) ImportTestRun(ctx context.Context) ApiImportTestRunReque } // Execute executes the request -// @return ExportedTestInformation +// +// @return ExportedTestInformation func (a *ApiApiService) ImportTestRunExecute(r ApiImportTestRunRequest) (*ExportedTestInformation, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPost @@ -2236,10 +2254,10 @@ RerunTestRun rerun a test run rerun a test run - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @param runId id of the run - @return ApiRerunTestRunRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @param runId id of the run + @return ApiRerunTestRunRequest */ func (a *ApiApiService) RerunTestRun(ctx context.Context, testId string, runId int32) ApiRerunTestRunRequest { return ApiRerunTestRunRequest{ @@ -2251,7 +2269,8 @@ func (a *ApiApiService) RerunTestRun(ctx context.Context, testId string, runId i } // Execute executes the request -// @return TestRun +// +// @return TestRun func (a *ApiApiService) RerunTestRunExecute(r ApiRerunTestRunRequest) (*TestRun, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPost @@ -2348,9 +2367,9 @@ RunTest run test run a particular test - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @return ApiRunTestRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @return ApiRunTestRequest */ func (a *ApiApiService) RunTest(ctx context.Context, testId string) ApiRunTestRequest { return ApiRunTestRequest{ @@ -2361,7 +2380,8 @@ func (a *ApiApiService) RunTest(ctx context.Context, testId string) ApiRunTestRe } // Execute executes the request -// @return TestRun +// +// @return TestRun func (a *ApiApiService) RunTestExecute(r ApiRunTestRequest) (*TestRun, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPost @@ -2469,9 +2489,9 @@ RunTransaction run transaction run a particular transaction - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param transactionId id of the transaction - @return ApiRunTransactionRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param transactionId id of the transaction + @return ApiRunTransactionRequest */ func (a *ApiApiService) RunTransaction(ctx context.Context, transactionId string) ApiRunTransactionRequest { return ApiRunTransactionRequest{ @@ -2482,7 +2502,8 @@ func (a *ApiApiService) RunTransaction(ctx context.Context, transactionId string } // Execute executes the request -// @return TransactionRun +// +// @return TransactionRun func (a *ApiApiService) RunTransactionExecute(r ApiRunTransactionRequest) (*TransactionRun, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPost @@ -2575,10 +2596,10 @@ StopTestRun stops the execution of a test run stops the execution of a test run - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @param runId id of the run - @return ApiStopTestRunRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @param runId id of the run + @return ApiStopTestRunRequest */ func (a *ApiApiService) StopTestRun(ctx context.Context, testId string, runId int32) ApiStopTestRunRequest { return ApiStopTestRunRequest{ @@ -2675,8 +2696,8 @@ TestConnection Tests the config data store/exporter connection Tests the config data store/exporter connection - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiTestConnectionRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiTestConnectionRequest */ func (a *ApiApiService) TestConnection(ctx context.Context) ApiTestConnectionRequest { return ApiTestConnectionRequest{ @@ -2686,7 +2707,8 @@ func (a *ApiApiService) TestConnection(ctx context.Context) ApiTestConnectionReq } // Execute executes the request -// @return TestConnectionResponse +// +// @return TestConnectionResponse func (a *ApiApiService) TestConnectionExecute(r ApiTestConnectionRequest) (*TestConnectionResponse, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPost diff --git a/cli/openapi/api_resource_api.go b/cli/openapi/api_resource_api.go index e60509d3e1..41c0fce596 100644 --- a/cli/openapi/api_resource_api.go +++ b/cli/openapi/api_resource_api.go @@ -42,8 +42,8 @@ CreateDemo Create a Demonstration setting Create a demonstration used on Tracetest as quick start examples. - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiCreateDemoRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateDemoRequest */ func (a *ResourceApiApiService) CreateDemo(ctx context.Context) ApiCreateDemoRequest { return ApiCreateDemoRequest{ @@ -53,7 +53,8 @@ func (a *ResourceApiApiService) CreateDemo(ctx context.Context) ApiCreateDemoReq } // Execute executes the request -// @return Demo +// +// @return Demo func (a *ResourceApiApiService) CreateDemoExecute(r ApiCreateDemoRequest) (*Demo, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPost @@ -149,8 +150,8 @@ CreateEnvironment Create an environment Create an environment that can be used by tests and transactions - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiCreateEnvironmentRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateEnvironmentRequest */ func (a *ResourceApiApiService) CreateEnvironment(ctx context.Context) ApiCreateEnvironmentRequest { return ApiCreateEnvironmentRequest{ @@ -160,7 +161,8 @@ func (a *ResourceApiApiService) CreateEnvironment(ctx context.Context) ApiCreate } // Execute executes the request -// @return EnvironmentResource +// +// @return EnvironmentResource func (a *ResourceApiApiService) CreateEnvironmentExecute(r ApiCreateEnvironmentRequest) (*EnvironmentResource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPost @@ -256,8 +258,8 @@ CreateLinter Create an Linter Create an Linter that can be used by tests and Linters - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiCreateLinterRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateLinterRequest */ func (a *ResourceApiApiService) CreateLinter(ctx context.Context) ApiCreateLinterRequest { return ApiCreateLinterRequest{ @@ -267,7 +269,8 @@ func (a *ResourceApiApiService) CreateLinter(ctx context.Context) ApiCreateLinte } // Execute executes the request -// @return LinterResource +// +// @return LinterResource func (a *ResourceApiApiService) CreateLinterExecute(r ApiCreateLinterRequest) (*LinterResource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPost @@ -363,8 +366,8 @@ CreateTest Create new test Create new test action - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiCreateTestRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateTestRequest */ func (a *ResourceApiApiService) CreateTest(ctx context.Context) ApiCreateTestRequest { return ApiCreateTestRequest{ @@ -374,7 +377,8 @@ func (a *ResourceApiApiService) CreateTest(ctx context.Context) ApiCreateTestReq } // Execute executes the request -// @return Test +// +// @return Test func (a *ResourceApiApiService) CreateTestExecute(r ApiCreateTestRequest) (*Test, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPost @@ -470,8 +474,8 @@ CreateTransaction Create new transaction Create new transaction - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiCreateTransactionRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateTransactionRequest */ func (a *ResourceApiApiService) CreateTransaction(ctx context.Context) ApiCreateTransactionRequest { return ApiCreateTransactionRequest{ @@ -481,7 +485,8 @@ func (a *ResourceApiApiService) CreateTransaction(ctx context.Context) ApiCreate } // Execute executes the request -// @return TransactionResource +// +// @return TransactionResource func (a *ResourceApiApiService) CreateTransactionExecute(r ApiCreateTransactionRequest) (*TransactionResource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPost @@ -572,9 +577,9 @@ DeleteDataStore Delete a Data Store Delete a Data Store - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param dataStoreId ID of a datastore used on Tracetest to configure how to fetch traces in a test - @return ApiDeleteDataStoreRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param dataStoreId ID of a datastore used on Tracetest to configure how to fetch traces in a test + @return ApiDeleteDataStoreRequest */ func (a *ResourceApiApiService) DeleteDataStore(ctx context.Context, dataStoreId string) ApiDeleteDataStoreRequest { return ApiDeleteDataStoreRequest{ @@ -664,9 +669,9 @@ DeleteDemo Delete a Demonstration setting Delete a demonstration used on Tracetest as quick start examples. - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param demoId ID of a demonstration used on Tracetest as quick start examples - @return ApiDeleteDemoRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param demoId ID of a demonstration used on Tracetest as quick start examples + @return ApiDeleteDemoRequest */ func (a *ResourceApiApiService) DeleteDemo(ctx context.Context, demoId string) ApiDeleteDemoRequest { return ApiDeleteDemoRequest{ @@ -756,9 +761,9 @@ DeleteEnvironment Delete an environment Delete an environment from Tracetest - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param environmentId ID of an environment used on Tracetest to inject values into tests and transactions - @return ApiDeleteEnvironmentRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param environmentId ID of an environment used on Tracetest to inject values into tests and transactions + @return ApiDeleteEnvironmentRequest */ func (a *ResourceApiApiService) DeleteEnvironment(ctx context.Context, environmentId string) ApiDeleteEnvironmentRequest { return ApiDeleteEnvironmentRequest{ @@ -848,9 +853,9 @@ DeleteLinter Delete an Linter Delete an Linter from Tracetest - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param linterId ID of an Linter - @return ApiDeleteLinterRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param linterId ID of an Linter + @return ApiDeleteLinterRequest */ func (a *ResourceApiApiService) DeleteLinter(ctx context.Context, linterId string) ApiDeleteLinterRequest { return ApiDeleteLinterRequest{ @@ -940,9 +945,9 @@ DeleteTest delete a test delete a test - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @return ApiDeleteTestRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @return ApiDeleteTestRequest */ func (a *ResourceApiApiService) DeleteTest(ctx context.Context, testId string) ApiDeleteTestRequest { return ApiDeleteTestRequest{ @@ -1032,9 +1037,9 @@ DeleteTransaction delete a transaction delete a transaction - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param transactionId id of the transaction - @return ApiDeleteTransactionRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param transactionId id of the transaction + @return ApiDeleteTransactionRequest */ func (a *ResourceApiApiService) DeleteTransaction(ctx context.Context, transactionId string) ApiDeleteTransactionRequest { return ApiDeleteTransactionRequest{ @@ -1124,9 +1129,9 @@ GetConfiguration Get Tracetest configuration Get Tracetest configuration - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param configId ID of the configuration resource used on Tracetest. It should be set as 'current' - @return ApiGetConfigurationRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param configId ID of the configuration resource used on Tracetest. It should be set as 'current' + @return ApiGetConfigurationRequest */ func (a *ResourceApiApiService) GetConfiguration(ctx context.Context, configId string) ApiGetConfigurationRequest { return ApiGetConfigurationRequest{ @@ -1137,7 +1142,8 @@ func (a *ResourceApiApiService) GetConfiguration(ctx context.Context, configId s } // Execute executes the request -// @return ConfigurationResource +// +// @return ConfigurationResource func (a *ResourceApiApiService) GetConfigurationExecute(r ApiGetConfigurationRequest) (*ConfigurationResource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1227,9 +1233,9 @@ GetDataStore Get a Data Store Get a Data Store - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param dataStoreId ID of a datastore used on Tracetest to configure how to fetch traces in a test - @return ApiGetDataStoreRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param dataStoreId ID of a datastore used on Tracetest to configure how to fetch traces in a test + @return ApiGetDataStoreRequest */ func (a *ResourceApiApiService) GetDataStore(ctx context.Context, dataStoreId string) ApiGetDataStoreRequest { return ApiGetDataStoreRequest{ @@ -1240,7 +1246,8 @@ func (a *ResourceApiApiService) GetDataStore(ctx context.Context, dataStoreId st } // Execute executes the request -// @return DataStoreResource +// +// @return DataStoreResource func (a *ResourceApiApiService) GetDataStoreExecute(r ApiGetDataStoreRequest) (*DataStoreResource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1330,9 +1337,9 @@ GetDemo Get Demonstration setting Get a demonstration used on Tracetest as quick start examples. - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param demoId ID of a demonstration used on Tracetest as quick start examples - @return ApiGetDemoRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param demoId ID of a demonstration used on Tracetest as quick start examples + @return ApiGetDemoRequest */ func (a *ResourceApiApiService) GetDemo(ctx context.Context, demoId string) ApiGetDemoRequest { return ApiGetDemoRequest{ @@ -1343,7 +1350,8 @@ func (a *ResourceApiApiService) GetDemo(ctx context.Context, demoId string) ApiG } // Execute executes the request -// @return Demo +// +// @return Demo func (a *ResourceApiApiService) GetDemoExecute(r ApiGetDemoRequest) (*Demo, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1433,9 +1441,9 @@ GetEnvironment Get a specific environment Get one environment by its id - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param environmentId ID of an environment used on Tracetest to inject values into tests and transactions - @return ApiGetEnvironmentRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param environmentId ID of an environment used on Tracetest to inject values into tests and transactions + @return ApiGetEnvironmentRequest */ func (a *ResourceApiApiService) GetEnvironment(ctx context.Context, environmentId string) ApiGetEnvironmentRequest { return ApiGetEnvironmentRequest{ @@ -1446,7 +1454,8 @@ func (a *ResourceApiApiService) GetEnvironment(ctx context.Context, environmentI } // Execute executes the request -// @return EnvironmentResource +// +// @return EnvironmentResource func (a *ResourceApiApiService) GetEnvironmentExecute(r ApiGetEnvironmentRequest) (*EnvironmentResource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1536,9 +1545,9 @@ GetLinter Get a specific Linter Get one Linter by its id - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param linterId ID of an Linter - @return ApiGetLinterRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param linterId ID of an Linter + @return ApiGetLinterRequest */ func (a *ResourceApiApiService) GetLinter(ctx context.Context, linterId string) ApiGetLinterRequest { return ApiGetLinterRequest{ @@ -1549,7 +1558,8 @@ func (a *ResourceApiApiService) GetLinter(ctx context.Context, linterId string) } // Execute executes the request -// @return LinterResource +// +// @return LinterResource func (a *ResourceApiApiService) GetLinterExecute(r ApiGetLinterRequest) (*LinterResource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1639,9 +1649,9 @@ GetPollingProfile Get Polling Profile Get a polling profile used on Tracetest to configure how to fetch traces in a test. - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param pollingProfileId ID of a polling profile used on Tracetest to configure how to fetch traces in a test. It should be set as 'current' - @return ApiGetPollingProfileRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param pollingProfileId ID of a polling profile used on Tracetest to configure how to fetch traces in a test. It should be set as 'current' + @return ApiGetPollingProfileRequest */ func (a *ResourceApiApiService) GetPollingProfile(ctx context.Context, pollingProfileId string) ApiGetPollingProfileRequest { return ApiGetPollingProfileRequest{ @@ -1652,7 +1662,8 @@ func (a *ResourceApiApiService) GetPollingProfile(ctx context.Context, pollingPr } // Execute executes the request -// @return PollingProfile +// +// @return PollingProfile func (a *ResourceApiApiService) GetPollingProfileExecute(r ApiGetPollingProfileRequest) (*PollingProfile, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1776,8 +1787,8 @@ GetTests Get tests get tests - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiGetTestsRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetTestsRequest */ func (a *ResourceApiApiService) GetTests(ctx context.Context) ApiGetTestsRequest { return ApiGetTestsRequest{ @@ -1787,7 +1798,8 @@ func (a *ResourceApiApiService) GetTests(ctx context.Context) ApiGetTestsRequest } // Execute executes the request -// @return TestResourceList +// +// @return TestResourceList func (a *ResourceApiApiService) GetTestsExecute(r ApiGetTestsRequest) (*TestResourceList, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -1891,9 +1903,9 @@ GetTransaction get transaction get transaction - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param transactionId id of the transaction - @return ApiGetTransactionRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param transactionId id of the transaction + @return ApiGetTransactionRequest */ func (a *ResourceApiApiService) GetTransaction(ctx context.Context, transactionId string) ApiGetTransactionRequest { return ApiGetTransactionRequest{ @@ -1904,7 +1916,8 @@ func (a *ResourceApiApiService) GetTransaction(ctx context.Context, transactionI } // Execute executes the request -// @return TransactionResource +// +// @return TransactionResource func (a *ResourceApiApiService) GetTransactionExecute(r ApiGetTransactionRequest) (*TransactionResource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -2028,8 +2041,8 @@ GetTransactions Get transactions get transactions - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiGetTransactionsRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiGetTransactionsRequest */ func (a *ResourceApiApiService) GetTransactions(ctx context.Context) ApiGetTransactionsRequest { return ApiGetTransactionsRequest{ @@ -2039,7 +2052,8 @@ func (a *ResourceApiApiService) GetTransactions(ctx context.Context) ApiGetTrans } // Execute executes the request -// @return TransactionResourceList +// +// @return TransactionResourceList func (a *ResourceApiApiService) GetTransactionsExecute(r ApiGetTransactionsRequest) (*TransactionResourceList, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -2170,8 +2184,8 @@ ListConfiguration List Tracetest configuration List Tracetest configuration - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiListConfigurationRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiListConfigurationRequest */ func (a *ResourceApiApiService) ListConfiguration(ctx context.Context) ApiListConfigurationRequest { return ApiListConfigurationRequest{ @@ -2181,7 +2195,8 @@ func (a *ResourceApiApiService) ListConfiguration(ctx context.Context) ApiListCo } // Execute executes the request -// @return ConfigurationResourceList +// +// @return ConfigurationResourceList func (a *ResourceApiApiService) ListConfigurationExecute(r ApiListConfigurationRequest) (*ConfigurationResourceList, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -2309,8 +2324,8 @@ ListDataStore List Data Store List Data Store - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiListDataStoreRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiListDataStoreRequest */ func (a *ResourceApiApiService) ListDataStore(ctx context.Context) ApiListDataStoreRequest { return ApiListDataStoreRequest{ @@ -2320,7 +2335,8 @@ func (a *ResourceApiApiService) ListDataStore(ctx context.Context) ApiListDataSt } // Execute executes the request -// @return DataStoreList +// +// @return DataStoreList func (a *ResourceApiApiService) ListDataStoreExecute(r ApiListDataStoreRequest) (*DataStoreList, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -2448,8 +2464,8 @@ ListDemos List Demonstrations List demonstrations used on Tracetest as quick start examples. - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiListDemosRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiListDemosRequest */ func (a *ResourceApiApiService) ListDemos(ctx context.Context) ApiListDemosRequest { return ApiListDemosRequest{ @@ -2459,7 +2475,8 @@ func (a *ResourceApiApiService) ListDemos(ctx context.Context) ApiListDemosReque } // Execute executes the request -// @return DemoList +// +// @return DemoList func (a *ResourceApiApiService) ListDemosExecute(r ApiListDemosRequest) (*DemoList, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -2587,8 +2604,8 @@ ListEnvironments List environments List environments available in Tracetest. - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiListEnvironmentsRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiListEnvironmentsRequest */ func (a *ResourceApiApiService) ListEnvironments(ctx context.Context) ApiListEnvironmentsRequest { return ApiListEnvironmentsRequest{ @@ -2598,7 +2615,8 @@ func (a *ResourceApiApiService) ListEnvironments(ctx context.Context) ApiListEnv } // Execute executes the request -// @return EnvironmentResourceList +// +// @return EnvironmentResourceList func (a *ResourceApiApiService) ListEnvironmentsExecute(r ApiListEnvironmentsRequest) (*EnvironmentResourceList, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -2726,8 +2744,8 @@ ListLinters List Linters List Linters available in Tracetest. - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiListLintersRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiListLintersRequest */ func (a *ResourceApiApiService) ListLinters(ctx context.Context) ApiListLintersRequest { return ApiListLintersRequest{ @@ -2737,7 +2755,8 @@ func (a *ResourceApiApiService) ListLinters(ctx context.Context) ApiListLintersR } // Execute executes the request -// @return LinterResourceList +// +// @return LinterResourceList func (a *ResourceApiApiService) ListLintersExecute(r ApiListLintersRequest) (*LinterResourceList, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -2865,8 +2884,8 @@ ListPollingProfile List Polling Profile Configuration List Polling Profile configuration - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @return ApiListPollingProfileRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiListPollingProfileRequest */ func (a *ResourceApiApiService) ListPollingProfile(ctx context.Context) ApiListPollingProfileRequest { return ApiListPollingProfileRequest{ @@ -2876,7 +2895,8 @@ func (a *ResourceApiApiService) ListPollingProfile(ctx context.Context) ApiListP } // Execute executes the request -// @return PollingProfileList +// +// @return PollingProfileList func (a *ResourceApiApiService) ListPollingProfileExecute(r ApiListPollingProfileRequest) (*PollingProfileList, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -2977,9 +2997,9 @@ TestsTestIdGet get test get test - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @return ApiTestsTestIdGetRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @return ApiTestsTestIdGetRequest */ func (a *ResourceApiApiService) TestsTestIdGet(ctx context.Context, testId string) ApiTestsTestIdGetRequest { return ApiTestsTestIdGetRequest{ @@ -2990,7 +3010,8 @@ func (a *ResourceApiApiService) TestsTestIdGet(ctx context.Context, testId strin } // Execute executes the request -// @return TestResource +// +// @return TestResource func (a *ResourceApiApiService) TestsTestIdGetExecute(r ApiTestsTestIdGetRequest) (*TestResource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodGet @@ -3086,9 +3107,9 @@ UpdateConfiguration Update Tracetest configuration Update Tracetest configuration - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param configId ID of the configuration resource used on Tracetest. It should be set as 'current' - @return ApiUpdateConfigurationRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param configId ID of the configuration resource used on Tracetest. It should be set as 'current' + @return ApiUpdateConfigurationRequest */ func (a *ResourceApiApiService) UpdateConfiguration(ctx context.Context, configId string) ApiUpdateConfigurationRequest { return ApiUpdateConfigurationRequest{ @@ -3099,7 +3120,8 @@ func (a *ResourceApiApiService) UpdateConfiguration(ctx context.Context, configI } // Execute executes the request -// @return ConfigurationResource +// +// @return ConfigurationResource func (a *ResourceApiApiService) UpdateConfigurationExecute(r ApiUpdateConfigurationRequest) (*ConfigurationResource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPut @@ -3197,9 +3219,9 @@ UpdateDataStore Update a Data Store Update a Data Store - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param dataStoreId ID of a datastore used on Tracetest to configure how to fetch traces in a test - @return ApiUpdateDataStoreRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param dataStoreId ID of a datastore used on Tracetest to configure how to fetch traces in a test + @return ApiUpdateDataStoreRequest */ func (a *ResourceApiApiService) UpdateDataStore(ctx context.Context, dataStoreId string) ApiUpdateDataStoreRequest { return ApiUpdateDataStoreRequest{ @@ -3297,9 +3319,9 @@ UpdateDemo Update a Demonstration setting Update a demonstration used on Tracetest as quick start examples. - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param demoId ID of a demonstration used on Tracetest as quick start examples - @return ApiUpdateDemoRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param demoId ID of a demonstration used on Tracetest as quick start examples + @return ApiUpdateDemoRequest */ func (a *ResourceApiApiService) UpdateDemo(ctx context.Context, demoId string) ApiUpdateDemoRequest { return ApiUpdateDemoRequest{ @@ -3310,7 +3332,8 @@ func (a *ResourceApiApiService) UpdateDemo(ctx context.Context, demoId string) A } // Execute executes the request -// @return Demo +// +// @return Demo func (a *ResourceApiApiService) UpdateDemoExecute(r ApiUpdateDemoRequest) (*Demo, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPut @@ -3408,9 +3431,9 @@ UpdateEnvironment Update an environment Update an environment used on Tracetest - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param environmentId ID of an environment used on Tracetest to inject values into tests and transactions - @return ApiUpdateEnvironmentRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param environmentId ID of an environment used on Tracetest to inject values into tests and transactions + @return ApiUpdateEnvironmentRequest */ func (a *ResourceApiApiService) UpdateEnvironment(ctx context.Context, environmentId string) ApiUpdateEnvironmentRequest { return ApiUpdateEnvironmentRequest{ @@ -3421,7 +3444,8 @@ func (a *ResourceApiApiService) UpdateEnvironment(ctx context.Context, environme } // Execute executes the request -// @return EnvironmentResource +// +// @return EnvironmentResource func (a *ResourceApiApiService) UpdateEnvironmentExecute(r ApiUpdateEnvironmentRequest) (*EnvironmentResource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPut @@ -3519,9 +3543,9 @@ UpdateLinter Update a Linter Update a Linter used on Tracetest - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param linterId ID of an Linter - @return ApiUpdateLinterRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param linterId ID of an Linter + @return ApiUpdateLinterRequest */ func (a *ResourceApiApiService) UpdateLinter(ctx context.Context, linterId string) ApiUpdateLinterRequest { return ApiUpdateLinterRequest{ @@ -3532,7 +3556,8 @@ func (a *ResourceApiApiService) UpdateLinter(ctx context.Context, linterId strin } // Execute executes the request -// @return LinterResource +// +// @return LinterResource func (a *ResourceApiApiService) UpdateLinterExecute(r ApiUpdateLinterRequest) (*LinterResource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPut @@ -3630,9 +3655,9 @@ UpdatePollingProfile Update a Polling Profile Update a polling profile used on Tracetest to configure how to fetch traces in a test. - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param pollingProfileId ID of a polling profile used on Tracetest to configure how to fetch traces in a test. It should be set as 'current' - @return ApiUpdatePollingProfileRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param pollingProfileId ID of a polling profile used on Tracetest to configure how to fetch traces in a test. It should be set as 'current' + @return ApiUpdatePollingProfileRequest */ func (a *ResourceApiApiService) UpdatePollingProfile(ctx context.Context, pollingProfileId string) ApiUpdatePollingProfileRequest { return ApiUpdatePollingProfileRequest{ @@ -3643,7 +3668,8 @@ func (a *ResourceApiApiService) UpdatePollingProfile(ctx context.Context, pollin } // Execute executes the request -// @return PollingProfile +// +// @return PollingProfile func (a *ResourceApiApiService) UpdatePollingProfileExecute(r ApiUpdatePollingProfileRequest) (*PollingProfile, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPut @@ -3741,9 +3767,9 @@ UpdateTest update test update test action - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param testId id of the test - @return ApiUpdateTestRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param testId id of the test + @return ApiUpdateTestRequest */ func (a *ResourceApiApiService) UpdateTest(ctx context.Context, testId string) ApiUpdateTestRequest { return ApiUpdateTestRequest{ @@ -3841,9 +3867,9 @@ UpdateTransaction update transaction update transaction action - @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). - @param transactionId id of the transaction - @return ApiUpdateTransactionRequest + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param transactionId id of the transaction + @return ApiUpdateTransactionRequest */ func (a *ResourceApiApiService) UpdateTransaction(ctx context.Context, transactionId string) ApiUpdateTransactionRequest { return ApiUpdateTransactionRequest{ @@ -3854,7 +3880,8 @@ func (a *ResourceApiApiService) UpdateTransaction(ctx context.Context, transacti } // Execute executes the request -// @return TransactionResource +// +// @return TransactionResource func (a *ResourceApiApiService) UpdateTransactionExecute(r ApiUpdateTransactionRequest) (*TransactionResource, *http.Response, error) { var ( localVarHTTPMethod = http.MethodPut diff --git a/cli/openapi/model_trigger.go b/cli/openapi/model_trigger.go index 2e34532b3f..fd11c4c1af 100644 --- a/cli/openapi/model_trigger.go +++ b/cli/openapi/model_trigger.go @@ -22,6 +22,7 @@ type Trigger struct { Type *string `json:"type,omitempty"` TriggerType *string `json:"triggerType,omitempty"` Http *HTTPRequest `json:"http,omitempty"` + HttpRequest *HTTPRequest `json:"httpRequest,omitempty"` Grpc *GRPCRequest `json:"grpc,omitempty"` Traceid *TRACEIDRequest `json:"traceid,omitempty"` } @@ -139,6 +140,38 @@ func (o *Trigger) SetHttp(v HTTPRequest) { o.Http = &v } +// GetHttpRequest returns the HttpRequest field value if set, zero value otherwise. +func (o *Trigger) GetHttpRequest() HTTPRequest { + if o == nil || isNil(o.HttpRequest) { + var ret HTTPRequest + return ret + } + return *o.HttpRequest +} + +// GetHttpRequestOk returns a tuple with the HttpRequest field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Trigger) GetHttpRequestOk() (*HTTPRequest, bool) { + if o == nil || isNil(o.HttpRequest) { + return nil, false + } + return o.HttpRequest, true +} + +// HasHttpRequest returns a boolean if a field has been set. +func (o *Trigger) HasHttpRequest() bool { + if o != nil && !isNil(o.HttpRequest) { + return true + } + + return false +} + +// SetHttpRequest gets a reference to the given HTTPRequest and assigns it to the HttpRequest field. +func (o *Trigger) SetHttpRequest(v HTTPRequest) { + o.HttpRequest = &v +} + // GetGrpc returns the Grpc field value if set, zero value otherwise. func (o *Trigger) GetGrpc() GRPCRequest { if o == nil || isNil(o.Grpc) { @@ -222,6 +255,9 @@ func (o Trigger) ToMap() (map[string]interface{}, error) { if !isNil(o.Http) { toSerialize["http"] = o.Http } + if !isNil(o.HttpRequest) { + toSerialize["httpRequest"] = o.HttpRequest + } if !isNil(o.Grpc) { toSerialize["grpc"] = o.Grpc } diff --git a/cli/pkg/fileutil/file.go b/cli/pkg/fileutil/file.go index 2dbd625000..8c28a1a715 100644 --- a/cli/pkg/fileutil/file.go +++ b/cli/pkg/fileutil/file.go @@ -11,22 +11,22 @@ import ( "strings" ) -type file struct { +type File struct { path string contents []byte } -func Read(filePath string) (file, error) { +func Read(filePath string) (File, error) { b, err := os.ReadFile(filePath) if err != nil { - return file{}, fmt.Errorf("could not read definition file %s: %w", filePath, err) + return File{}, fmt.Errorf("could not read definition file %s: %w", filePath, err) } return New(filePath, b), nil } -func New(path string, b []byte) file { - file := file{ +func New(path string, b []byte) File { + file := File{ contents: b, path: path, } @@ -34,7 +34,7 @@ func New(path string, b []byte) file { return file } -func (f file) Reader() io.Reader { +func (f File) Reader() io.Reader { return bytes.NewReader(f.contents) } @@ -45,12 +45,12 @@ var ( var ErrFileHasID = errors.New("file already has ID") -func (f file) HasID() bool { +func (f File) HasID() bool { fileID := hasIDRegex.Find(f.contents) return fileID != nil } -func (f file) SetID(id string) (file, error) { +func (f File) SetID(id string) (File, error) { if f.HasID() { return f, ErrFileHasID } @@ -76,16 +76,28 @@ func (f file) SetID(id string) (file, error) { return New(f.path, newContents), nil } -func (f file) AbsDir() string { +func (f File) AbsPath() string { abs, err := filepath.Abs(f.path) if err != nil { panic(fmt.Errorf(`cannot get absolute path from "%s": %w`, f.path, err)) } - return filepath.Dir(abs) + return abs } -func (f file) Write() (file, error) { +func (f File) AbsDir() string { + return filepath.Dir(f.AbsPath()) +} + +func (f File) RelativeFile(path string) string { + if filepath.IsAbs(path) { + return path + } + + return filepath.Join(f.AbsDir(), path) +} + +func (f File) Write() (File, error) { err := os.WriteFile(f.path, f.contents, 0644) if err != nil { return f, fmt.Errorf("could not write file %s: %w", f.path, err) @@ -94,6 +106,6 @@ func (f file) Write() (file, error) { return Read(f.path) } -func (f file) ReadAll() (string, error) { - return string(f.contents), nil +func (f File) Contents() []byte { + return f.contents } diff --git a/cli/pkg/fileutil/is_file_path.go b/cli/pkg/fileutil/path.go similarity index 52% rename from cli/pkg/fileutil/is_file_path.go rename to cli/pkg/fileutil/path.go index 60edee45ac..2af87cbf7f 100644 --- a/cli/pkg/fileutil/is_file_path.go +++ b/cli/pkg/fileutil/path.go @@ -3,8 +3,33 @@ package fileutil import ( "os" "path/filepath" + "strings" ) +func ToAbsDir(filePath string) (string, error) { + absPath, err := filepath.Abs(filePath) + if err != nil { + return "", err + } + + return filepath.Dir(absPath), nil +} + +func RelativeTo(path, relativeTo string) string { + if filepath.IsAbs(path) { + return path + } + + return filepath.Join(relativeTo, path) +} + +func LooksLikeFilePath(path string) bool { + return strings.HasPrefix(path, "./") || + strings.HasPrefix(path, "../") || + strings.HasPrefix(path, "/") + +} + func IsFilePath(path string) bool { // for the current working dir, check if the file exists // by finding its absolute path and executing a stat command diff --git a/cli/pkg/resourcemanager/apply.go b/cli/pkg/resourcemanager/apply.go index 2e5f37c03f..e81147580e 100644 --- a/cli/pkg/resourcemanager/apply.go +++ b/cli/pkg/resourcemanager/apply.go @@ -12,12 +12,7 @@ import ( const VerbApply Verb = "apply" -func (c Client) Apply(ctx context.Context, filePath string, requestedFormat Format) (string, error) { - inputFile, err := fileutil.Read(filePath) - if err != nil { - return "", fmt.Errorf("cannot read file %s: %w", filePath, err) - } - +func (c Client) Apply(ctx context.Context, inputFile fileutil.File, requestedFormat Format) (string, error) { url := c.client.url(c.resourceNamePlural) req, err := http.NewRequestWithContext(ctx, http.MethodPut, url.String(), inputFile.Reader()) if err != nil { diff --git a/cli/variable/injector.go b/cli/variable/injector.go index 05f045a4e8..7ab6b7acbd 100644 --- a/cli/variable/injector.go +++ b/cli/variable/injector.go @@ -110,7 +110,7 @@ func (i Injector) injectValueIntoField(field reflect.Value) error { // We only support variables replacements in strings right now strValue := field.String() - newValue, err := i.replaceVariable(strValue) + newValue, err := i.ReplaceInString(strValue) if err != nil { return err } @@ -119,7 +119,7 @@ func (i Injector) injectValueIntoField(field reflect.Value) error { return nil } -func (i Injector) replaceVariable(value string) (string, error) { +func (i Injector) ReplaceInString(value string) (string, error) { envVarRegex, err := regexp.Compile(`\$\{\w+\}`) if err != nil { return "", fmt.Errorf("could not compile env variable regex: %w", err) diff --git a/server/app/app.go b/server/app/app.go index b20e9b658b..a680650914 100644 --- a/server/app/app.go +++ b/server/app/app.go @@ -454,6 +454,7 @@ func registerTestResource(repository test.Repository, router *mux.Router, provis test.ResourceNamePlural, repository, resourcemanager.WithTracer(tracer), + resourcemanager.CanBeAugmented(), ) manager.RegisterRoutes(router) provisioner.AddResourceProvisioner(manager) diff --git a/server/http/controller.go b/server/http/controller.go index 3c4b452560..b8ac659e74 100644 --- a/server/http/controller.go +++ b/server/http/controller.go @@ -2,6 +2,7 @@ package http import ( "context" + "database/sql" "encoding/hex" "errors" "fmt" @@ -107,7 +108,7 @@ func NewController( func handleDBError(err error) openapi.ImplResponse { switch { - case errors.Is(testdb.ErrNotFound, err): + case errors.Is(testdb.ErrNotFound, err) || errors.Is(sql.ErrNoRows, err): return openapi.Response(http.StatusNotFound, err.Error()) default: return openapi.Response(http.StatusInternalServerError, err.Error()) diff --git a/server/openapi/model_trigger.go b/server/openapi/model_trigger.go index a032a0e648..44875cf947 100644 --- a/server/openapi/model_trigger.go +++ b/server/openapi/model_trigger.go @@ -16,6 +16,8 @@ type Trigger struct { Http HttpRequest `json:"http,omitempty"` + HttpRequest HttpRequest `json:"httpRequest,omitempty"` + Grpc GrpcRequest `json:"grpc,omitempty"` Traceid TraceidRequest `json:"traceid,omitempty"` @@ -26,6 +28,9 @@ func AssertTriggerRequired(obj Trigger) error { if err := AssertHttpRequestRequired(obj.Http); err != nil { return err } + if err := AssertHttpRequestRequired(obj.HttpRequest); err != nil { + return err + } if err := AssertGrpcRequestRequired(obj.Grpc); err != nil { return err } diff --git a/server/test/test_repository.go b/server/test/test_repository.go index ae4d154367..01f23eef31 100644 --- a/server/test/test_repository.go +++ b/server/test/test_repository.go @@ -409,7 +409,7 @@ func (r *repository) Update(ctx context.Context, test Test) (Test, error) { return Test{}, fmt.Errorf("could not bump test version: %w", err) } - if *oldTest.Version == *testToUpdate.Version { + if oldTest.SafeVersion() == testToUpdate.SafeVersion() { // No change in the version. Nothing changed so no need to persist it r.removeNonAugmentedFields(&testToUpdate) return testToUpdate, nil @@ -431,9 +431,11 @@ func bumpTestVersionIfNeeded(in, updated Test) (Test, error) { return Test{}, err } + version := in.SafeVersion() if testHasChanged { - updated.Version = intPtr(*in.Version + 1) + version = version + 1 } + updated.Version = &version return updated, nil } diff --git a/testing/cli-e2etest/testscenarios/test/list_test_test.go b/testing/cli-e2etest/testscenarios/test/list_test_test.go index 947e922cd6..019839502d 100644 --- a/testing/cli-e2etest/testscenarios/test/list_test_test.go +++ b/testing/cli-e2etest/testscenarios/test/list_test_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + "github.com/davecgh/go-spew/spew" "github.com/kubeshop/tracetest/cli-e2etest/environment" "github.com/kubeshop/tracetest/cli-e2etest/helpers" "github.com/kubeshop/tracetest/cli-e2etest/testscenarios/types" @@ -22,18 +23,14 @@ func addListTestsPreReqs(t *testing.T, env environment.Manager) { // Then it should be applied with success newTestPath := env.GetTestResourcePath(t, "list") - // TODO: using test run as apply test is not yet implemented - // result := tracetestcli.Exec(t, fmt.Sprintf("apply test --file %s", newTestPath), tracetestcli.WithCLIConfig(cliConfig)) - result := tracetestcli.Exec(t, fmt.Sprintf("test run --definition %s", newTestPath), tracetestcli.WithCLIConfig(cliConfig)) + result := tracetestcli.Exec(t, fmt.Sprintf("apply test --file %s", newTestPath), tracetestcli.WithCLIConfig(cliConfig)) helpers.RequireExitCodeEqual(t, result, 0) // When I try to set up a another test // Then it should be applied with success anotherTestPath := env.GetTestResourcePath(t, "import") - // TODO: using test run as apply test is not yet implemented - // result = tracetestcli.Exec(t, fmt.Sprintf("apply test --file %s", anotherTestPath), tracetestcli.WithCLIConfig(cliConfig)) - result = tracetestcli.Exec(t, fmt.Sprintf("test run --definition %s", anotherTestPath), tracetestcli.WithCLIConfig(cliConfig)) + result = tracetestcli.Exec(t, fmt.Sprintf("apply test --file %s", anotherTestPath), tracetestcli.WithCLIConfig(cliConfig)) helpers.RequireExitCodeEqual(t, result, 0) } @@ -83,21 +80,10 @@ func TestListTests(t *testing.T) { testVarsList := helpers.UnmarshalYAMLSequence[types.TestResource](t, result.StdOut) require.Len(testVarsList, 2) - importTest := testVarsList[0] - assert.Equal("Test", importTest.Type) - assert.Equal("fH_8AulVR", importTest.Spec.ID) - assert.Equal("Pokeshop - Import", importTest.Spec.Name) - assert.Equal("Import a Pokemon", importTest.Spec.Description) - assert.Equal("http", importTest.Spec.Trigger.Type) - assert.Equal("http://demo-api:8081/pokemon/import", importTest.Spec.Trigger.HTTPRequest.URL) - assert.Equal("POST", importTest.Spec.Trigger.HTTPRequest.Method) - assert.Equal(`'{"id":52}'`, importTest.Spec.Trigger.HTTPRequest.Body) - require.Len(importTest.Spec.Trigger.HTTPRequest.Headers, 1) - assert.Equal("Content-Type", importTest.Spec.Trigger.HTTPRequest.Headers[0].Key) - assert.Equal("application/json", importTest.Spec.Trigger.HTTPRequest.Headers[0].Value) + spew.Dump(testVarsList) - listTest := testVarsList[1] + listTest := testVarsList[0] assert.Equal("Test", listTest.Type) assert.Equal("fH_8AulVR", listTest.Spec.ID) assert.Equal("Pokeshop - List", listTest.Spec.Name) @@ -109,6 +95,19 @@ func TestListTests(t *testing.T) { require.Len(listTest.Spec.Trigger.HTTPRequest.Headers, 1) assert.Equal("Content-Type", listTest.Spec.Trigger.HTTPRequest.Headers[0].Key) assert.Equal("application/json", listTest.Spec.Trigger.HTTPRequest.Headers[0].Value) + + importTest := testVarsList[1] + assert.Equal("Test", importTest.Type) + assert.Equal("RXrbV__4g", importTest.Spec.ID) + assert.Equal("Pokeshop - Import", importTest.Spec.Name) + assert.Equal("Import a Pokemon", importTest.Spec.Description) + assert.Equal("http", importTest.Spec.Trigger.Type) + assert.Equal("http://demo-api:8081/pokemon/import", importTest.Spec.Trigger.HTTPRequest.URL) + assert.Equal("POST", importTest.Spec.Trigger.HTTPRequest.Method) + assert.Equal(`{"id":52}`, importTest.Spec.Trigger.HTTPRequest.Body) + require.Len(importTest.Spec.Trigger.HTTPRequest.Headers, 1) + assert.Equal("Content-Type", importTest.Spec.Trigger.HTTPRequest.Headers[0].Key) + assert.Equal("application/json", importTest.Spec.Trigger.HTTPRequest.Headers[0].Value) }) // t.Run("list with JSON format", func(t *testing.T) { diff --git a/testing/cli-e2etest/testscenarios/test/test/list_test_test.go b/testing/cli-e2etest/testscenarios/test/test/list_test_test.go deleted file mode 100644 index f5896a3840..0000000000 --- a/testing/cli-e2etest/testscenarios/test/test/list_test_test.go +++ /dev/null @@ -1,213 +0,0 @@ -package test - -import ( - "fmt" - "testing" - - "github.com/davecgh/go-spew/spew" - "github.com/kubeshop/tracetest/cli-e2etest/environment" - "github.com/kubeshop/tracetest/cli-e2etest/helpers" - "github.com/kubeshop/tracetest/cli-e2etest/testscenarios/types" - "github.com/kubeshop/tracetest/cli-e2etest/tracetestcli" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func addListTestsPreReqs(t *testing.T, env environment.Manager) { - cliConfig := env.GetCLIConfigPath(t) - - // Given I am a Tracetest CLI user - // And I have my server recently created - - // When I try to set up a new test - // Then it should be applied with success - newTestPath := env.GetTestResourcePath(t, "list") - - // TODO: using test run as apply test is not yet implemented - // result := tracetestcli.Exec(t, fmt.Sprintf("apply test --file %s", newTestPath), tracetestcli.WithCLIConfig(cliConfig)) - result := tracetestcli.Exec(t, fmt.Sprintf("test run --definition %s", newTestPath), tracetestcli.WithCLIConfig(cliConfig)) - helpers.RequireExitCodeEqual(t, result, 0) - - // When I try to set up a another test - // Then it should be applied with success - anotherTestPath := env.GetTestResourcePath(t, "import") - - // TODO: using test run as apply test is not yet implemented - // result = tracetestcli.Exec(t, fmt.Sprintf("apply test --file %s", anotherTestPath), tracetestcli.WithCLIConfig(cliConfig)) - result = tracetestcli.Exec(t, fmt.Sprintf("test run --definition %s", anotherTestPath), tracetestcli.WithCLIConfig(cliConfig)) - helpers.RequireExitCodeEqual(t, result, 0) -} - -func TestListTests(t *testing.T) { - // instantiate require with testing helper - require := require.New(t) - assert := assert.New(t) - - // setup isolated e2e test - env := environment.CreateAndStart(t) - defer env.Close(t) - - cliConfig := env.GetCLIConfigPath(t) - - t.Run("list no tests", func(t *testing.T) { - // Given I am a Tracetest CLI user - // And I have my server recently created - // And there is no envs - result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection asc --output yaml", tracetestcli.WithCLIConfig(cliConfig)) - helpers.RequireExitCodeEqual(t, result, 0) - - testVarsList := helpers.UnmarshalYAMLSequence[types.TestResource](t, result.StdOut) - require.Len(testVarsList, 0) - }) - - addListTestsPreReqs(t, env) - - t.Run("list with invalid sortBy field", func(t *testing.T) { - // Given I am a Tracetest CLI user - // And I have my server recently created - - // When I try to list these tests by an invalid field - // Then I should receive an error - result := tracetestcli.Exec(t, "list test --sortBy id --output yaml", tracetestcli.WithCLIConfig(cliConfig)) - helpers.RequireExitCodeEqual(t, result, 1) - require.Contains(result.StdErr, "invalid sort field: id") // TODO: think on how to improve this error handling - }) - - t.Run("list with YAML format", func(t *testing.T) { - // Given I am a Tracetest CLI user - // And I have 2 existing tests - - // When I try to list these tests by a valid field and in YAML format - // Then I should receive 2 tests - result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection desc --output yaml", tracetestcli.WithCLIConfig(cliConfig)) - helpers.RequireExitCodeEqual(t, result, 0) - - testVarsList := helpers.UnmarshalYAMLSequence[types.TestResource](t, result.StdOut) - require.Len(testVarsList, 2) - importTest := testVarsList[0] - spew.Dump(importTest) - assert.Equal("Test", importTest.Type) - assert.Equal("fH_8AulVR", importTest.Spec.ID) - assert.Equal("Pokeshop - Import", importTest.Spec.Name) - assert.Equal("Import a Pokemon", importTest.Spec.Description) - assert.Equal("http", importTest.Spec.Trigger.Type) - assert.Equal("http://demo-api:8081/pokemon/import", importTest.Spec.Trigger.HTTPRequest.URL) - assert.Equal("POST", importTest.Spec.Trigger.HTTPRequest.Method) - assert.Equal(`'{"id":52}'`, importTest.Spec.Trigger.HTTPRequest.Body) - require.Len(importTest.Spec.Trigger.HTTPRequest.Headers, 1) - assert.Equal("Content-Type", importTest.Spec.Trigger.HTTPRequest.Headers[0].Key) - assert.Equal("application/json", importTest.Spec.Trigger.HTTPRequest.Headers[0].Value) - - listTest := testVarsList[1] - assert.Equal("Test", listTest.Type) - assert.Equal("fH_8AulVR", listTest.Spec.ID) - assert.Equal("Pokeshop - List", listTest.Spec.Name) - assert.Equal("List Pokemon", listTest.Spec.Description) - assert.Equal("http", listTest.Spec.Trigger.Type) - assert.Equal("http://demo-api:8081/pokemon?take=20&skip=0", listTest.Spec.Trigger.HTTPRequest.URL) - assert.Equal("GET", listTest.Spec.Trigger.HTTPRequest.Method) - assert.Equal("", listTest.Spec.Trigger.HTTPRequest.Body) - require.Len(listTest.Spec.Trigger.HTTPRequest.Headers, 1) - assert.Equal("Content-Type", listTest.Spec.Trigger.HTTPRequest.Headers[0].Key) - assert.Equal("application/json", listTest.Spec.Trigger.HTTPRequest.Headers[0].Value) - }) - - // t.Run("list with JSON format", func(t *testing.T) { - // // Given I am a Tracetest CLI user - // // And I have my server recently created - - // // When I try to list these tests by a valid field and in JSON format - // // Then I should receive three tests - // result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection asc --output json", tracetestcli.WithCLIConfig(cliConfig)) - // helpers.RequireExitCodeEqual(t, result, 0) - - // testVarsList := helpers.UnmarshalJSON[[]types.TestResource](t, result.StdOut) - // require.Len(testVarsList, 3) - - // // due our database sorting algorithm, "another-env" comes in the front of ".env" - // // ref https://wiki.postgresql.org/wiki/FAQ#Why_do_my_strings_sort_incorrectly.3F - // anotherTestVars := testVarsList[0] - // require.Equal("Test", anotherTestVars.Type) - // require.Equal("another-env", anotherTestVars.Spec.ID) - // require.Equal("another-env", anotherTestVars.Spec.Name) - // require.Len(anotherTestVars.Spec.Values, 2) - // require.Equal("Here", anotherTestVars.Spec.Values[0].Key) - // require.Equal("We", anotherTestVars.Spec.Values[0].Value) - // require.Equal("Come", anotherTestVars.Spec.Values[1].Key) - // require.Equal("Again", anotherTestVars.Spec.Values[1].Value) - - // testVars := testVarsList[1] - // require.Equal("Test", testVars.Type) - // require.Equal(".env", testVars.Spec.ID) - // require.Equal(".env", testVars.Spec.Name) - // require.Len(testVars.Spec.Values, 2) - // require.Equal("FIRST_VAR", testVars.Spec.Values[0].Key) - // require.Equal("some-value", testVars.Spec.Values[0].Value) - // require.Equal("SECOND_VAR", testVars.Spec.Values[1].Key) - // require.Equal("another_value", testVars.Spec.Values[1].Value) - - // oneMoreTestVars := testVarsList[2] - // require.Equal("Test", oneMoreTestVars.Type) - // require.Equal("one-more-env", oneMoreTestVars.Spec.ID) - // require.Equal("one-more-env", oneMoreTestVars.Spec.Name) - // require.Len(oneMoreTestVars.Spec.Values, 2) - // require.Equal("This", oneMoreTestVars.Spec.Values[0].Key) - // require.Equal("Is", oneMoreTestVars.Spec.Values[0].Value) - // require.Equal("The", oneMoreTestVars.Spec.Values[1].Key) - // require.Equal("Third", oneMoreTestVars.Spec.Values[1].Value) - // }) - - // t.Run("list with pretty format", func(t *testing.T) { - // // Given I am a Tracetest CLI user - // // And I have my server recently created - - // // When I try to list these tests by a valid field and in pretty format - // // Then it should print a table with 6 lines printed: header, separator, three envs and empty line - // result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection asc --output pretty", tracetestcli.WithCLIConfig(cliConfig)) - // helpers.RequireExitCodeEqual(t, result, 0) - - // lines := strings.Split(result.StdOut, "\n") - // require.Len(lines, 6) - - // // due our database sorting algorithm, "another-env" comes in the front of ".env" - // // ref https://wiki.postgresql.org/wiki/FAQ#Why_do_my_strings_sort_incorrectly.3F - // require.Contains(lines[2], "another-env") - // require.Contains(lines[3], ".env") - // require.Contains(lines[4], "one-more-env") - // }) - - // t.Run("list with YAML format skipping the first and taking two items", func(t *testing.T) { - // // Given I am a Tracetest CLI user - // // And I have my server recently created - - // // When I try to list these tests by a valid field, paging options and in YAML format - // // Then I should receive two tests - // result := tracetestcli.Exec(t, "list test --sortBy name --sortDirection asc --skip 1 --take 2 --output yaml", tracetestcli.WithCLIConfig(cliConfig)) - // helpers.RequireExitCodeEqual(t, result, 0) - - // testVarsList := helpers.UnmarshalYAMLSequence[types.TestResource](t, result.StdOut) - // require.Len(testVarsList, 2) - - // // due our database sorting algorithm, "another-env" comes in the front of ".env" - // // ref https://wiki.postgresql.org/wiki/FAQ#Why_do_my_strings_sort_incorrectly.3F - // testVars := testVarsList[0] - // require.Equal("Test", testVars.Type) - // require.Equal(".env", testVars.Spec.ID) - // require.Equal(".env", testVars.Spec.Name) - // require.Len(testVars.Spec.Values, 2) - // require.Equal("FIRST_VAR", testVars.Spec.Values[0].Key) - // require.Equal("some-value", testVars.Spec.Values[0].Value) - // require.Equal("SECOND_VAR", testVars.Spec.Values[1].Key) - // require.Equal("another_value", testVars.Spec.Values[1].Value) - - // oneMoreTestVars := testVarsList[1] - // require.Equal("Test", oneMoreTestVars.Type) - // require.Equal("one-more-env", oneMoreTestVars.Spec.ID) - // require.Equal("one-more-env", oneMoreTestVars.Spec.Name) - // require.Len(oneMoreTestVars.Spec.Values, 2) - // require.Equal("This", oneMoreTestVars.Spec.Values[0].Key) - // require.Equal("Is", oneMoreTestVars.Spec.Values[0].Value) - // require.Equal("The", oneMoreTestVars.Spec.Values[1].Key) - // require.Equal("Third", oneMoreTestVars.Spec.Values[1].Value) - // }) -} diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/api.proto b/testing/cli-e2etest/testscenarios/test/test/resources/api.proto deleted file mode 100644 index e4e94d4bd5..0000000000 --- a/testing/cli-e2etest/testscenarios/test/test/resources/api.proto +++ /dev/null @@ -1,37 +0,0 @@ -syntax = "proto3"; - -option java_multiple_files = true; -option java_outer_classname = "PokeshopProto"; -option objc_class_prefix = "PKS"; - -package pokeshop; - -service Pokeshop { - rpc getPokemonList (GetPokemonRequest) returns (GetPokemonListResponse) {} - rpc createPokemon (Pokemon) returns (Pokemon) {} - rpc importPokemon (ImportPokemonRequest) returns (ImportPokemonRequest) {} -} - -message ImportPokemonRequest { - int32 id = 1; - optional bool isFixed = 2; -} - -message GetPokemonRequest { - optional int32 skip = 1; - optional int32 take = 2; - optional bool isFixed = 3; -} - -message GetPokemonListResponse { - repeated Pokemon items = 1; - int32 totalCount = 2; -} - -message Pokemon { - optional int32 id = 1; - string name = 2; - string type = 3; - bool isFeatured = 4; - optional string imageUrl = 5; -} diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/environment-file.yaml b/testing/cli-e2etest/testscenarios/test/test/resources/environment-file.yaml deleted file mode 100644 index 6c5831b356..0000000000 --- a/testing/cli-e2etest/testscenarios/test/test/resources/environment-file.yaml +++ /dev/null @@ -1,11 +0,0 @@ -type: Environment -spec: - id: pokeapi-env - name: pokeapi-env - description: "" - createdAt: 2023-06-21T20:37:10.10518Z - values: - - key: POKEMON_NAME - value: snorlax - - key: POKEMON_URL - value: https://assets.pokemon.com/assets/cms2/img/pokedex/full/143.png diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-embedded-protobuf.yaml b/testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-embedded-protobuf.yaml deleted file mode 100644 index 84e210ffb7..0000000000 --- a/testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-embedded-protobuf.yaml +++ /dev/null @@ -1,60 +0,0 @@ -type: Test -spec: - id: create-pokemon - name: "Create Pokemon" - description: Create a single pokemon on Pokeshop - trigger: - type: grpc - grpc: - protobufFile: | - syntax = "proto3"; - - option java_multiple_files = true; - option java_outer_classname = "PokeshopProto"; - option objc_class_prefix = "PKS"; - - package pokeshop; - - service Pokeshop { - rpc getPokemonList (GetPokemonRequest) returns (GetPokemonListResponse) {} - rpc createPokemon (Pokemon) returns (Pokemon) {} - rpc importPokemon (ImportPokemonRequest) returns (ImportPokemonRequest) {} - } - - message ImportPokemonRequest { - int32 id = 1; - optional bool isFixed = 2; - } - - message GetPokemonRequest { - optional int32 skip = 1; - optional int32 take = 2; - optional bool isFixed = 3; - } - - message GetPokemonListResponse { - repeated Pokemon items = 1; - int32 totalCount = 2; - } - - message Pokemon { - optional int32 id = 1; - string name = 2; - string type = 3; - bool isFeatured = 4; - optional string imageUrl = 5; - } - - address: demo-rpc:8082 - method: pokeshop.Pokeshop.createPokemon - request: |- - { - "name": "Pikachu", - "type": "eletric", - "isFeatured": true - } - specs: - - name: It calls Pokeshop correctly - selector: span[tracetest.span.type="rpc" name="pokeshop.Pokeshop/createPokemon" rpc.system="grpc" rpc.method="createPokemon" rpc.service="pokeshop.Pokeshop"] - assertions: - - attr:rpc.grpc.status_code = 0 diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-reference-protobuf.yaml b/testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-reference-protobuf.yaml deleted file mode 100644 index 1149226290..0000000000 --- a/testing/cli-e2etest/testscenarios/test/test/resources/grpc-trigger-reference-protobuf.yaml +++ /dev/null @@ -1,22 +0,0 @@ -type: Test -spec: - id: create-pokemon - name: "Create Pokemon" - description: Create a single pokemon on Pokeshop - trigger: - type: grpc - grpc: - protobufFile: ./api.proto - address: demo-rpc:8082 - method: pokeshop.Pokeshop.createPokemon - request: |- - { - "name": "Pikachu", - "type": "eletric", - "isFeatured": true - } - specs: - - name: It calls Pokeshop correctly - selector: span[tracetest.span.type="rpc" name="pokeshop.Pokeshop/createPokemon" rpc.system="grpc" rpc.method="createPokemon" rpc.service="pokeshop.Pokeshop"] - assertions: - - attr:rpc.grpc.status_code = 0 diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/http-trigger-with-environment-file.yaml b/testing/cli-e2etest/testscenarios/test/test/resources/http-trigger-with-environment-file.yaml deleted file mode 100644 index 52f6c5011e..0000000000 --- a/testing/cli-e2etest/testscenarios/test/test/resources/http-trigger-with-environment-file.yaml +++ /dev/null @@ -1,26 +0,0 @@ -type: Test -spec: - id: 9wtAH2_Vg - name: Pokeshop - Add - description: Add a Pokemon - trigger: - type: http - httpRequest: - url: http://demo-api:8081/pokemon - method: POST - headers: - - key: Content-Type - value: application/json - body: '{"name":"${env:POKEMON_NAME}","type":"normal","imageUrl":"${env:POKEMON_URL}","isFeatured":true}' - specs: - - name: It should add a Pokemon correctly - selector: span[tracetest.span.type="http" name="POST /pokemon" http.method="POST"] - assertions: - - attr:http.status_code = 201 - - name: It should save the correct data - selector: - span[tracetest.span.type="database" name="create postgres.pokemon" db.system="postgres" - db.name="postgres" db.user="postgres" db.operation="create" db.sql.table="pokemon"] - assertions: - - attr:db.result contains '"imageUrl":"${env:POKEMON_URL}"' - - attr:db.result contains '"name":"${env:POKEMON_NAME}"' diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/import.yaml b/testing/cli-e2etest/testscenarios/test/test/resources/import.yaml deleted file mode 100644 index 0bcd61422b..0000000000 --- a/testing/cli-e2etest/testscenarios/test/test/resources/import.yaml +++ /dev/null @@ -1,14 +0,0 @@ -type: Test -spec: - id: RXrbV__4g - name: Pokeshop - Import - description: Import a Pokemon - trigger: - type: http - httpRequest: - url: http://demo-api:8081/pokemon/import - method: POST - headers: - - key: Content-Type - value: application/json - body: '{"id":52}' diff --git a/testing/cli-e2etest/testscenarios/test/test/resources/list.yaml b/testing/cli-e2etest/testscenarios/test/test/resources/list.yaml deleted file mode 100644 index 06fc9ff36c..0000000000 --- a/testing/cli-e2etest/testscenarios/test/test/resources/list.yaml +++ /dev/null @@ -1,13 +0,0 @@ -type: Test -spec: - id: fH_8AulVR - name: Pokeshop - List - description: List Pokemon - trigger: - type: http - httpRequest: - url: http://demo-api:8081/pokemon?take=20&skip=0 - method: GET - headers: - - key: Content-Type - value: application/json diff --git a/testing/cli-e2etest/testscenarios/test/test/run_test_with_grpc_trigger_test.go b/testing/cli-e2etest/testscenarios/test/test/run_test_with_grpc_trigger_test.go deleted file mode 100644 index e626b32154..0000000000 --- a/testing/cli-e2etest/testscenarios/test/test/run_test_with_grpc_trigger_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package test - -import ( - "fmt" - "testing" - - "github.com/kubeshop/tracetest/cli-e2etest/environment" - "github.com/kubeshop/tracetest/cli-e2etest/helpers" - "github.com/kubeshop/tracetest/cli-e2etest/tracetestcli" - "github.com/stretchr/testify/require" -) - -func TestRunTestWithGrpcTrigger(t *testing.T) { - // setup isolated e2e environment - env := environment.CreateAndStart(t, environment.WithDataStoreEnabled(), environment.WithPokeshop()) - defer env.Close(t) - - cliConfig := env.GetCLIConfigPath(t) - - t.Run("should pass when using an embedded protobuf string in the test", func(t *testing.T) { - // instantiate require with testing helper - require := require.New(t) - - // Given I am a Tracetest CLI user - // And I have my server recently created - // And the datasource is already set - - // When I try to run a test with a gRPC trigger with embedded protobuf - // Then it should pass - testFile := env.GetTestResourcePath(t, "grpc-trigger-embedded-protobuf") - - command := fmt.Sprintf("test run -w -d %s", testFile) - result := tracetestcli.Exec(t, command, tracetestcli.WithCLIConfig(cliConfig)) - helpers.RequireExitCodeEqual(t, result, 0) - require.Contains(result.StdOut, "✔ It calls Pokeshop correctly") // checks if the assertion was succeeded - }) - - t.Run("should pass when referencing a protobuf file in the test", func(t *testing.T) { - // instantiate require with testing helper - require := require.New(t) - - // Given I am a Tracetest CLI user - // And I have my server recently created - // And the datasource is already set - - // When I try to run a test with a gRPC trigger with a reference to a protobuf file - // Then it should pass - testFile := env.GetTestResourcePath(t, "grpc-trigger-reference-protobuf") - - command := fmt.Sprintf("test run -w -d %s", testFile) - result := tracetestcli.Exec(t, command, tracetestcli.WithCLIConfig(cliConfig)) - helpers.RequireExitCodeEqual(t, result, 0) - require.Contains(result.StdOut, "✔ It calls Pokeshop correctly") // checks if the assertion was succeeded - }) -} diff --git a/testing/cli-e2etest/testscenarios/test/test/run_test_with_http_trigger_and_environment_file_test.go b/testing/cli-e2etest/testscenarios/test/test/run_test_with_http_trigger_and_environment_file_test.go deleted file mode 100644 index 9e41dc9426..0000000000 --- a/testing/cli-e2etest/testscenarios/test/test/run_test_with_http_trigger_and_environment_file_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package test - -import ( - "fmt" - "testing" - - "github.com/kubeshop/tracetest/cli-e2etest/environment" - "github.com/kubeshop/tracetest/cli-e2etest/helpers" - "github.com/kubeshop/tracetest/cli-e2etest/testscenarios/types" - "github.com/kubeshop/tracetest/cli-e2etest/tracetestcli" - "github.com/stretchr/testify/require" -) - -func TestRunTestWithHttpTriggerAndEnvironmentFile(t *testing.T) { - // setup isolated e2e environment - env := environment.CreateAndStart(t, environment.WithDataStoreEnabled(), environment.WithPokeshop()) - defer env.Close(t) - - cliConfig := env.GetCLIConfigPath(t) - - // instantiate require with testing helper - require := require.New(t) - - t.Run("should pass when using environment definition file", func(t *testing.T) { - // Given I am a Tracetest CLI user - // And I have my server recently created - // And the datasource is already set - - // When I try to get an environment - // Then it should return a message saying that the environment was not found - result := tracetestcli.Exec(t, "get environment --id pokeapi-env", tracetestcli.WithCLIConfig(cliConfig)) - helpers.RequireExitCodeEqual(t, result, 0) - require.Contains(result.StdOut, "Resource environment with ID pokeapi-env not found") - - // When I try to run a test with a http trigger and a environment file - // Then it should pass - environmentFile := env.GetTestResourcePath(t, "environment-file") - testFile := env.GetTestResourcePath(t, "http-trigger-with-environment-file") - - command := fmt.Sprintf("test run -w -d %s --environment %s", testFile, environmentFile) - result = tracetestcli.Exec(t, command, tracetestcli.WithCLIConfig(cliConfig)) - helpers.RequireExitCodeEqual(t, result, 0) - require.Contains(result.StdOut, "✔ It should add a Pokemon correctly") - require.Contains(result.StdOut, "✔ It should save the correct data") - - // When I try to get the environment created on the previous step - // Then it should retrieve it correctly - result = tracetestcli.Exec(t, "get environment --id pokeapi-env --output yaml", tracetestcli.WithCLIConfig(cliConfig)) - helpers.RequireExitCodeEqual(t, result, 0) - - environmentVars := helpers.UnmarshalYAML[types.EnvironmentResource](t, result.StdOut) - require.Equal("Environment", environmentVars.Type) - require.Equal("pokeapi-env", environmentVars.Spec.ID) - require.Equal("pokeapi-env", environmentVars.Spec.Name) - require.Len(environmentVars.Spec.Values, 2) - require.Equal("POKEMON_NAME", environmentVars.Spec.Values[0].Key) - require.Equal("snorlax", environmentVars.Spec.Values[0].Value) - require.Equal("POKEMON_URL", environmentVars.Spec.Values[1].Key) - require.Equal("https://assets.pokemon.com/assets/cms2/img/pokedex/full/143.png", environmentVars.Spec.Values[1].Value) - }) - - t.Run("should pass when using environment id", func(t *testing.T) { - // Given I am a Tracetest CLI user - // And I have my server recently created - // And the datasource is already set - - // When I create an environment - // Then it should be created correctly - environmentFile := env.GetTestResourcePath(t, "environment-file") - - result := tracetestcli.Exec(t, fmt.Sprintf("apply environment --file %s", environmentFile), tracetestcli.WithCLIConfig(cliConfig)) - helpers.RequireExitCodeEqual(t, result, 0) - - environmentVars := helpers.UnmarshalYAML[types.EnvironmentResource](t, result.StdOut) - require.Equal("Environment", environmentVars.Type) - require.Equal("pokeapi-env", environmentVars.Spec.ID) - require.Equal("pokeapi-env", environmentVars.Spec.Name) - require.Len(environmentVars.Spec.Values, 2) - require.Equal("POKEMON_NAME", environmentVars.Spec.Values[0].Key) - require.Equal("snorlax", environmentVars.Spec.Values[0].Value) - require.Equal("POKEMON_URL", environmentVars.Spec.Values[1].Key) - require.Equal("https://assets.pokemon.com/assets/cms2/img/pokedex/full/143.png", environmentVars.Spec.Values[1].Value) - - // When I try to run a test with a http trigger and a environment id - // Then it should pass - - testFile := env.GetTestResourcePath(t, "http-trigger-with-environment-file") - - command := fmt.Sprintf("test run -w -d %s --environment pokeapi-env", testFile) - result = tracetestcli.Exec(t, command, tracetestcli.WithCLIConfig(cliConfig)) - helpers.RequireExitCodeEqual(t, result, 0) - require.Contains(result.StdOut, "✔ It should add a Pokemon correctly") - require.Contains(result.StdOut, "✔ It should save the correct data") - }) -} diff --git a/testing/cli-e2etest/testscenarios/types/test.go b/testing/cli-e2etest/testscenarios/types/test.go index 127c582c45..d892d61b8b 100644 --- a/testing/cli-e2etest/testscenarios/types/test.go +++ b/testing/cli-e2etest/testscenarios/types/test.go @@ -24,7 +24,7 @@ type Test struct { type Trigger struct { Type string `json:"type"` - HTTPRequest HTTPRequest `json:"http"` + HTTPRequest HTTPRequest `json:"httpRequest"` } type HTTPRequest struct { @@ -35,8 +35,8 @@ type HTTPRequest struct { } type HTTPHeader struct { - Key string `json:"Key"` - Value string `json:"Value"` + Key string `json:"key"` + Value string `json:"value"` } type Output struct { diff --git a/web/src/types/Generated.types.ts b/web/src/types/Generated.types.ts index 6bf461ed95..0e4094774d 100644 --- a/web/src/types/Generated.types.ts +++ b/web/src/types/Generated.types.ts @@ -2033,6 +2033,7 @@ export interface external { /** @enum {string} */ triggerType?: "http" | "grpc" | "traceid"; http?: external["http.yaml"]["components"]["schemas"]["HTTPRequest"]; + httpRequest?: external["http.yaml"]["components"]["schemas"]["HTTPRequest"]; grpc?: external["grpc.yaml"]["components"]["schemas"]["GRPCRequest"]; traceid?: external["traceid.yaml"]["components"]["schemas"]["TRACEIDRequest"]; };