From bd39964e09973c67bf90e2b8ef1f13944c8522f2 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 25 Nov 2024 18:12:59 +0300 Subject: [PATCH 01/40] feat: api methods for service logs Signed-off-by: Vladislav Sukhin --- internal/app/api/v1/server.go | 2 + internal/app/api/v1/testworkflowexecutions.go | 133 ++++++++++++++---- 2 files changed, 107 insertions(+), 28 deletions(-) diff --git a/internal/app/api/v1/server.go b/internal/app/api/v1/server.go index 615f1e52c7..7b6890c605 100644 --- a/internal/app/api/v1/server.go +++ b/internal/app/api/v1/server.go @@ -150,7 +150,9 @@ func (s *TestkubeAPI) Init(server server.HTTPServer) { testWorkflowExecutions.Post("/", s.ExecuteTestWorkflowHandler()) testWorkflowExecutions.Get("/:executionID", s.GetTestWorkflowExecutionHandler()) testWorkflowExecutions.Get("/:executionID/notifications", s.StreamTestWorkflowExecutionNotificationsHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsHandler()) testWorkflowExecutions.Get("/:executionID/notifications/stream", s.StreamTestWorkflowExecutionNotificationsWebSocketHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/stream:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsWebSocketHandler()) testWorkflowExecutions.Post("/:executionID/abort", s.AbortTestWorkflowExecutionHandler()) testWorkflowExecutions.Post("/:executionID/pause", s.PauseTestWorkflowExecutionHandler()) testWorkflowExecutions.Post("/:executionID/resume", s.ResumeTestWorkflowExecutionHandler()) diff --git a/internal/app/api/v1/testworkflowexecutions.go b/internal/app/api/v1/testworkflowexecutions.go index 637ee3609f..99a4288e90 100644 --- a/internal/app/api/v1/testworkflowexecutions.go +++ b/internal/app/api/v1/testworkflowexecutions.go @@ -14,6 +14,7 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/websocket/v2" "github.com/pkg/errors" + "github.com/valyala/fasthttp" "github.com/kubeshop/testkube/internal/app/api/apiutils" "github.com/kubeshop/testkube/internal/common" @@ -23,6 +24,41 @@ import ( "github.com/kubeshop/testkube/pkg/testworkflows/executionworker/executionworkertypes" ) +func (s *TestkubeAPI) streamNotifications(ctx *fasthttp.RequestCtx, id string, notifications executionworkertypes.NotificationsWatcher) { + // Initiate processing event stream + ctx.SetContentType("text/event-stream") + ctx.Response.Header.Set("Cache-Control", "no-cache") + ctx.Response.Header.Set("Connection", "keep-alive") + ctx.Response.Header.Set("Transfer-Encoding", "chunked") + + // Stream the notifications + ctx.SetBodyStreamWriter(func(w *bufio.Writer) { + err := w.Flush() + if err != nil { + s.Log.Errorw("could not flush stream body", "error", err, "id", id) + } + + enc := json.NewEncoder(w) + + for n := range notifications.Channel() { + err := enc.Encode(n) + if err != nil { + s.Log.Errorw("could not encode value", "error", err, "id", id) + } + + _, err = fmt.Fprintf(w, "\n") + if err != nil { + s.Log.Errorw("could not print new line", "error", err, "id", id) + } + + err = w.Flush() + if err != nil { + s.Log.Errorw("could not flush stream body", "error", err, "id", id) + } + } + }) +} + func (s *TestkubeAPI) StreamTestWorkflowExecutionNotificationsHandler() fiber.Handler { return func(c *fiber.Ctx) error { ctx := c.Context() @@ -47,39 +83,40 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionNotificationsHandler() fiber.Ha return s.BadRequest(c, errPrefix, "fetching notifications", notifications.Err()) } - // Initiate processing event stream - ctx.SetContentType("text/event-stream") - ctx.Response.Header.Set("Cache-Control", "no-cache") - ctx.Response.Header.Set("Connection", "keep-alive") - ctx.Response.Header.Set("Transfer-Encoding", "chunked") - - // Stream the notifications - ctx.SetBodyStreamWriter(func(w *bufio.Writer) { - err := w.Flush() - if err != nil { - s.Log.Errorw("could not flush stream body", "error", err, "id", id) - } - - enc := json.NewEncoder(w) + s.streamNotifications(ctx, id, notifications) + return nil + } +} - for n := range notifications.Channel() { - err := enc.Encode(n) - if err != nil { - s.Log.Errorw("could not encode value", "error", err, "id", id) - } +func (s *TestkubeAPI) StreamTestWorkflowExecutionServiceNotificationsHandler() fiber.Handler { + return func(c *fiber.Ctx) error { + ctx := c.Context() + executionID := c.Params("executionID") + serviceName := c.Params("serviceName") + serviceIndex := c.Params("serviceIndex") + errPrefix := fmt.Sprintf("failed to stream test workflow execution service '%s' instance '%s' notifications '%s'", + serviceName, serviceIndex, executionID) - _, err = fmt.Fprintf(w, "\n") - if err != nil { - s.Log.Errorw("could not print new line", "error", err, "id", id) - } + // Fetch execution from database + execution, err := s.TestWorkflowResults.Get(ctx, executionID) + if err != nil { + return s.ClientError(c, errPrefix, err) + } - err = w.Flush() - if err != nil { - s.Log.Errorw("could not flush stream body", "error", err, "id", id) - } - } + // Check for the logs + id := fmt.Sprintf("%s-%s-%s", execution.Id, serviceName, serviceIndex) + notifications := s.ExecutionWorkerClient.Notifications(ctx, id, executionworkertypes.NotificationsOptions{ + Hints: executionworkertypes.Hints{ + Namespace: execution.Namespace, + ScheduledAt: common.Ptr(execution.ScheduledAt), + Signature: execution.Signature, + }, }) + if notifications.Err() != nil { + return s.BadRequest(c, errPrefix, "fetching notifications", notifications.Err()) + } + s.streamNotifications(ctx, id, notifications) return nil } } @@ -121,6 +158,46 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionNotificationsWebSocketHandler() }) } +func (s *TestkubeAPI) StreamTestWorkflowExecutionServiceNotificationsWebSocketHandler() fiber.Handler { + return websocket.New(func(c *websocket.Conn) { + ctx, ctxCancel := context.WithCancel(context.Background()) + executionID := c.Params("executionID") + serviceName := c.Params("serviceName") + serviceIndex := c.Params("serviceIndex") + + // Stop reading when the WebSocket connection is already closed + originalClose := c.CloseHandler() + c.SetCloseHandler(func(code int, text string) error { + ctxCancel() + return originalClose(code, text) + }) + defer c.Conn.Close() + + // Fetch execution from database + execution, err := s.TestWorkflowResults.Get(ctx, executionID) + if err != nil { + return + } + + // Check for the logs + id := fmt.Sprintf("%s-%s-%s", execution.Id, serviceName, serviceIndex) + notifications := s.ExecutionWorkerClient.Notifications(ctx, id, executionworkertypes.NotificationsOptions{ + Hints: executionworkertypes.Hints{ + Namespace: execution.Namespace, + Signature: execution.Signature, + ScheduledAt: common.Ptr(execution.ScheduledAt), + }, + }) + if notifications.Err() != nil { + return + } + + for n := range notifications.Channel() { + _ = c.WriteJSON(n) + } + }) +} + func (s *TestkubeAPI) ListTestWorkflowExecutionsHandler() fiber.Handler { return func(c *fiber.Ctx) error { errPrefix := "failed to list test workflow executions" From 2c7796249dd1cc81b76fca5a05a1e69aba282293 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 25 Nov 2024 19:11:58 +0300 Subject: [PATCH 02/40] fix: client for get service logs Signed-off-by: Vladislav Sukhin --- .../commands/testworkflows/run.go | 47 +++++++++++++++++-- .../commands/testworkflows/watch.go | 10 +++- internal/app/api/v1/server.go | 4 +- pkg/api/v1/client/interface.go | 1 + pkg/api/v1/client/testworkflow.go | 8 ++++ 5 files changed, 64 insertions(+), 6 deletions(-) diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index 5c96c690d3..573553c4a1 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -47,6 +47,8 @@ func NewRunTestWorkflowCmd() *cobra.Command { masks []string tags map[string]string selectors []string + serviceName string + serviceIndex int ) cmd := &cobra.Command{ @@ -146,7 +148,7 @@ func NewRunTestWorkflowCmd() *cobra.Command { ui.NL() if !execution.FailedToInitialize() { if watchEnabled && len(args) > 0 { - exitCode = uiWatch(execution, client) + exitCode = uiWatch(execution, serviceName, serviceIndex, client) ui.NL() if downloadArtifactsEnabled { tests.DownloadTestWorkflowArtifacts(execution.Id, downloadDir, format, masks, client, outputPretty) @@ -181,12 +183,21 @@ func NewRunTestWorkflowCmd() *cobra.Command { cmd.Flags().StringArrayVarP(&masks, "mask", "", []string{}, "regexp to filter downloaded files, single or comma separated, like report/.* or .*\\.json,.*\\.js$") cmd.Flags().StringToStringVarP(&tags, "tag", "", map[string]string{}, "execution tags in a form of name1=val1 passed to executor") cmd.Flags().StringSliceVarP(&selectors, "label", "l", nil, "label key value pair: --label key1=value1 or label expression") + cmd.Flags().StringVar(&serviceName, "service-name", "", "test workflow service name") + cmd.Flags().IntVar(&serviceIndex, "service-index", 0, "test workflow service index") return cmd } -func uiWatch(execution testkube.TestWorkflowExecution, client apiclientv1.Client) int { - result, err := watchTestWorkflowLogs(execution.Id, execution.Signature, client) +func uiWatch(execution testkube.TestWorkflowExecution, serviceName string, serviceIndex int, client apiclientv1.Client) int { + var result *testkube.TestWorkflowResult + var err error + + if serviceName == "" { + result, err = watchTestWorkflowLogs(execution.Id, execution.Signature, client) + } else { + result, err = watchTestWorkflowServiceLogs(execution.Id, serviceName, serviceIndex, execution.Signature, client) + } ui.ExitOnError("reading test workflow execution logs", err) // Apply the result in the execution @@ -313,6 +324,36 @@ func watchTestWorkflowLogs(id string, signature []testkube.TestWorkflowSignature return result, err } +func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, signature []testkube.TestWorkflowSignature, client apiclientv1.Client) (*testkube.TestWorkflowResult, error) { + ui.Info("Getting logs from test workflow service pod", fmt.Sprintf("%s-%s-%d", id, serviceName, serviceIndex)) + + notifications, err := client.GetTestWorkflowExecutionServiceNotifications(id, serviceName, serviceIndex) + ui.ExitOnError("getting logs from executor", err) + + steps := flattenSignatures(signature) + + var result *testkube.TestWorkflowResult + var isLineBeginning = true + for l := range notifications { + if l.Output != nil { + continue + } + if l.Result != nil { + if printResultDifference(result, l.Result, steps) { + isLineBeginning = true + } + result = l.Result + continue + } + + printStructuredLogLines(l.Log, &isLineBeginning) + } + + ui.NL() + + return result, err +} + func printStatusHeader(i, n int, name string) { if i == -1 { fmt.Println("\n" + ui.LightCyan(fmt.Sprintf("• %s", name))) diff --git a/cmd/kubectl-testkube/commands/testworkflows/watch.go b/cmd/kubectl-testkube/commands/testworkflows/watch.go index 2387810b6e..3992ec3337 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/watch.go +++ b/cmd/kubectl-testkube/commands/testworkflows/watch.go @@ -13,6 +13,11 @@ import ( ) func NewWatchTestWorkflowExecutionCmd() *cobra.Command { + var ( + serviceName string + serviceIndex int + ) + cmd := &cobra.Command{ Use: "testworkflowexecution ", Aliases: []string{"testworkflowexecutions", "twe", "tw"}, @@ -31,7 +36,7 @@ func NewWatchTestWorkflowExecutionCmd() *cobra.Command { ui.ExitOnError("render test workflow execution", err) ui.NL() - exitCode := uiWatch(execution, client) + exitCode := uiWatch(execution, serviceName, serviceIndex, client) ui.NL() execution, err = client.GetTestWorkflowExecution(execution.Id) @@ -43,5 +48,8 @@ func NewWatchTestWorkflowExecutionCmd() *cobra.Command { }, } + cmd.Flags().StringVar(&serviceName, "service-name", "", "test workflow service name") + cmd.Flags().IntVar(&serviceIndex, "service-index", 0, "test workflow service index") + return cmd } diff --git a/internal/app/api/v1/server.go b/internal/app/api/v1/server.go index 7b6890c605..d7aa19993b 100644 --- a/internal/app/api/v1/server.go +++ b/internal/app/api/v1/server.go @@ -150,9 +150,9 @@ func (s *TestkubeAPI) Init(server server.HTTPServer) { testWorkflowExecutions.Post("/", s.ExecuteTestWorkflowHandler()) testWorkflowExecutions.Get("/:executionID", s.GetTestWorkflowExecutionHandler()) testWorkflowExecutions.Get("/:executionID/notifications", s.StreamTestWorkflowExecutionNotificationsHandler()) - testWorkflowExecutions.Get("/:executionID/notifications/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsHandler()) testWorkflowExecutions.Get("/:executionID/notifications/stream", s.StreamTestWorkflowExecutionNotificationsWebSocketHandler()) - testWorkflowExecutions.Get("/:executionID/notifications/stream:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsWebSocketHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/stream:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsWebSocketHandler()) testWorkflowExecutions.Post("/:executionID/abort", s.AbortTestWorkflowExecutionHandler()) testWorkflowExecutions.Post("/:executionID/pause", s.PauseTestWorkflowExecutionHandler()) testWorkflowExecutions.Post("/:executionID/resume", s.ResumeTestWorkflowExecutionHandler()) diff --git a/pkg/api/v1/client/interface.go b/pkg/api/v1/client/interface.go index 82f1357377..73a3f6c48a 100644 --- a/pkg/api/v1/client/interface.go +++ b/pkg/api/v1/client/interface.go @@ -154,6 +154,7 @@ type TestWorkflowAPI interface { ExecuteTestWorkflows(selector string, request testkube.TestWorkflowExecutionRequest) ([]testkube.TestWorkflowExecution, error) GetTestWorkflowExecutionNotifications(id string) (chan testkube.TestWorkflowExecutionNotification, error) GetTestWorkflowExecutionLogs(id string) ([]byte, error) + GetTestWorkflowExecutionServiceNotifications(id, serviceName string, serviceIndex int) (chan testkube.TestWorkflowExecutionNotification, error) } // TestWorkflowExecutionAPI describes test workflow api methods diff --git a/pkg/api/v1/client/testworkflow.go b/pkg/api/v1/client/testworkflow.go index d878f93565..8bffb81d28 100644 --- a/pkg/api/v1/client/testworkflow.go +++ b/pkg/api/v1/client/testworkflow.go @@ -146,6 +146,14 @@ func (c TestWorkflowClient) GetTestWorkflowExecutionNotifications(id string) (no return notifications, err } +// GetTestWorkflowExecutionServiceNotifications returns events stream from job pods, based on job pods logs +func (c TestWorkflowClient) GetTestWorkflowExecutionServiceNotifications(id, serviceName string, serviceIndex int) (notifications chan testkube.TestWorkflowExecutionNotification, err error) { + notifications = make(chan testkube.TestWorkflowExecutionNotification) + uri := c.testWorkflowTransport.GetURI("/test-workflow-executions/%s/notifications/%s/%d", id, serviceName, serviceIndex) + err = c.testWorkflowTransport.GetTestWorkflowExecutionNotifications(uri, notifications) + return notifications, err +} + // GetTestWorkflowExecution returns single test workflow execution by id func (c TestWorkflowClient) GetTestWorkflowExecution(id string) (testkube.TestWorkflowExecution, error) { uri := c.testWorkflowExecutionTransport.GetURI("/test-workflow-executions/%s", id) From c71f5c810dc52e6246d183ad99f64b6046a4653d Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 25 Nov 2024 19:26:38 +0300 Subject: [PATCH 03/40] fix: change log Signed-off-by: Vladislav Sukhin --- cmd/kubectl-testkube/commands/testworkflows/executions.go | 2 +- cmd/kubectl-testkube/commands/testworkflows/run.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/kubectl-testkube/commands/testworkflows/executions.go b/cmd/kubectl-testkube/commands/testworkflows/executions.go index 66e297df84..bdd328da32 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/executions.go +++ b/cmd/kubectl-testkube/commands/testworkflows/executions.go @@ -75,7 +75,7 @@ func NewGetTestWorkflowExecutionsCmd() *cobra.Command { ui.Info("Getting logs for test workflow execution", executionID) logs, err := client.GetTestWorkflowExecutionLogs(executionID) - ui.ExitOnError("getting logs from executor", err) + ui.ExitOnError("getting logs from test workflow", err) sigs := flattenSignatures(execution.Signature) diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index 573553c4a1..0116fedd83 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -298,7 +298,7 @@ func watchTestWorkflowLogs(id string, signature []testkube.TestWorkflowSignature ui.Info("Getting logs from test workflow job", id) notifications, err := client.GetTestWorkflowExecutionNotifications(id) - ui.ExitOnError("getting logs from executor", err) + ui.ExitOnError("getting logs from test workflow", err) steps := flattenSignatures(signature) @@ -328,7 +328,7 @@ func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, sign ui.Info("Getting logs from test workflow service pod", fmt.Sprintf("%s-%s-%d", id, serviceName, serviceIndex)) notifications, err := client.GetTestWorkflowExecutionServiceNotifications(id, serviceName, serviceIndex) - ui.ExitOnError("getting logs from executor", err) + ui.ExitOnError("getting logs from service", err) steps := flattenSignatures(signature) From 3e70a83712b5a9bf3fab7ad34a43cf18ccde21d2 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 25 Nov 2024 23:07:35 +0300 Subject: [PATCH 04/40] fix: disable hints Signed-off-by: Vladislav Sukhin --- internal/app/api/v1/testworkflowexecutions.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/app/api/v1/testworkflowexecutions.go b/internal/app/api/v1/testworkflowexecutions.go index 99a4288e90..9e56997857 100644 --- a/internal/app/api/v1/testworkflowexecutions.go +++ b/internal/app/api/v1/testworkflowexecutions.go @@ -107,9 +107,9 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionServiceNotificationsHandler() f id := fmt.Sprintf("%s-%s-%s", execution.Id, serviceName, serviceIndex) notifications := s.ExecutionWorkerClient.Notifications(ctx, id, executionworkertypes.NotificationsOptions{ Hints: executionworkertypes.Hints{ - Namespace: execution.Namespace, - ScheduledAt: common.Ptr(execution.ScheduledAt), - Signature: execution.Signature, + Namespace: execution.Namespace, + // ScheduledAt: common.Ptr(execution.ScheduledAt), + // Signature: execution.Signature, }, }) if notifications.Err() != nil { @@ -183,9 +183,9 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionServiceNotificationsWebSocketHa id := fmt.Sprintf("%s-%s-%s", execution.Id, serviceName, serviceIndex) notifications := s.ExecutionWorkerClient.Notifications(ctx, id, executionworkertypes.NotificationsOptions{ Hints: executionworkertypes.Hints{ - Namespace: execution.Namespace, - Signature: execution.Signature, - ScheduledAt: common.Ptr(execution.ScheduledAt), + Namespace: execution.Namespace, + // Signature: execution.Signature, + // ScheduledAt: common.Ptr(execution.ScheduledAt), }, }) if notifications.Err() != nil { From aa9acb3f7918717243b098abdb9eb6b912d640fa Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Tue, 26 Nov 2024 15:26:59 +0300 Subject: [PATCH 05/40] fix: routing Signed-off-by: Vladislav Sukhin --- internal/app/api/v1/server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/app/api/v1/server.go b/internal/app/api/v1/server.go index d7aa19993b..139f8e9863 100644 --- a/internal/app/api/v1/server.go +++ b/internal/app/api/v1/server.go @@ -150,9 +150,9 @@ func (s *TestkubeAPI) Init(server server.HTTPServer) { testWorkflowExecutions.Post("/", s.ExecuteTestWorkflowHandler()) testWorkflowExecutions.Get("/:executionID", s.GetTestWorkflowExecutionHandler()) testWorkflowExecutions.Get("/:executionID/notifications", s.StreamTestWorkflowExecutionNotificationsHandler()) - testWorkflowExecutions.Get("/:executionID/notifications/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsHandler()) testWorkflowExecutions.Get("/:executionID/notifications/stream", s.StreamTestWorkflowExecutionNotificationsWebSocketHandler()) - testWorkflowExecutions.Get("/:executionID/notifications/stream:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsWebSocketHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/stream/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsWebSocketHandler()) testWorkflowExecutions.Post("/:executionID/abort", s.AbortTestWorkflowExecutionHandler()) testWorkflowExecutions.Post("/:executionID/pause", s.PauseTestWorkflowExecutionHandler()) testWorkflowExecutions.Post("/:executionID/resume", s.ResumeTestWorkflowExecutionHandler()) From 68fe09fcdbcd900ff2d58d36103afeeadad17903 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Tue, 26 Nov 2024 17:08:09 +0300 Subject: [PATCH 06/40] fix: show service logs Signed-off-by: Vladislav Sukhin --- .../commands/testworkflows/run.go | 43 +++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index 0116fedd83..b1fd46adc2 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -27,8 +27,9 @@ import ( ) const ( - LogTimestampLength = 30 // time.RFC3339Nano without 00:00 timezone - apiErrorMessage = "processing error:" + LogTimestampLength = 30 // time.RFC3339Nano without 00:00 timezone + apiErrorMessage = "processing error:" + serviceLogsCheckDelay = 100 * time.Millisecond ) var ( @@ -298,7 +299,9 @@ func watchTestWorkflowLogs(id string, signature []testkube.TestWorkflowSignature ui.Info("Getting logs from test workflow job", id) notifications, err := client.GetTestWorkflowExecutionNotifications(id) - ui.ExitOnError("getting logs from test workflow", err) + if err != nil { + return nil, err + } steps := flattenSignatures(signature) @@ -321,14 +324,38 @@ func watchTestWorkflowLogs(id string, signature []testkube.TestWorkflowSignature ui.NL() - return result, err + return result, nil } -func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, signature []testkube.TestWorkflowSignature, client apiclientv1.Client) (*testkube.TestWorkflowResult, error) { +func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, + signature []testkube.TestWorkflowSignature, client apiclientv1.Client) (*testkube.TestWorkflowResult, error) { ui.Info("Getting logs from test workflow service pod", fmt.Sprintf("%s-%s-%d", id, serviceName, serviceIndex)) - notifications, err := client.GetTestWorkflowExecutionServiceNotifications(id, serviceName, serviceIndex) - ui.ExitOnError("getting logs from service", err) + var ( + notifications chan testkube.TestWorkflowExecutionNotification + err error + ) + + for { + notifications, err = client.GetTestWorkflowExecutionServiceNotifications(id, serviceName, serviceIndex) + if err != nil { + execution, err := client.GetTestWorkflowExecution(id) + if err != nil { + return nil, err + } + + if execution.Result != nil && !execution.Result.IsFinished() { + time.Sleep(serviceLogsCheckDelay) + continue + } + } + + if err != nil { + return nil, err + } + + break + } steps := flattenSignatures(signature) @@ -351,7 +378,7 @@ func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, sign ui.NL() - return result, err + return result, nil } func printStatusHeader(i, n int, name string) { From c55187f29aa6ae351e85c9db40cacfb2e3030dca Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 27 Nov 2024 13:08:27 +0300 Subject: [PATCH 07/40] fix: check service name Signed-off-by: Vladislav Sukhin --- .../commands/testworkflows/run.go | 53 ++++++++----------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index b1fd46adc2..663924d2ac 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -197,6 +197,15 @@ func uiWatch(execution testkube.TestWorkflowExecution, serviceName string, servi if serviceName == "" { result, err = watchTestWorkflowLogs(execution.Id, execution.Signature, client) } else { + found := false + if execution.Workflow != nil && execution.Workflow.Spec != nil { + _, found = execution.Workflow.Spec.Services[serviceName] + } + + if !found { + ui.Failf("unknown service '%s' for test workflow execution %s", serviceName, execution.Id) + } + result, err = watchTestWorkflowServiceLogs(execution.Id, serviceName, serviceIndex, execution.Signature, client) } ui.ExitOnError("reading test workflow execution logs", err) @@ -295,17 +304,10 @@ func getTimestampLength(line string) int { return 0 } -func watchTestWorkflowLogs(id string, signature []testkube.TestWorkflowSignature, client apiclientv1.Client) (*testkube.TestWorkflowResult, error) { - ui.Info("Getting logs from test workflow job", id) - - notifications, err := client.GetTestWorkflowExecutionNotifications(id) - if err != nil { - return nil, err - } - +func printTestWorkflowLogs(signature []testkube.TestWorkflowSignature, + notifications chan testkube.TestWorkflowExecutionNotification) (result *testkube.TestWorkflowResult) { steps := flattenSignatures(signature) - var result *testkube.TestWorkflowResult var isLineBeginning = true for l := range notifications { if l.Output != nil { @@ -323,7 +325,18 @@ func watchTestWorkflowLogs(id string, signature []testkube.TestWorkflowSignature } ui.NL() + return result +} + +func watchTestWorkflowLogs(id string, signature []testkube.TestWorkflowSignature, client apiclientv1.Client) (*testkube.TestWorkflowResult, error) { + ui.Info("Getting logs from test workflow job", id) + + notifications, err := client.GetTestWorkflowExecutionNotifications(id) + if err != nil { + return nil, err + } + result := printTestWorkflowLogs(signature, notifications) return result, nil } @@ -357,27 +370,7 @@ func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, break } - steps := flattenSignatures(signature) - - var result *testkube.TestWorkflowResult - var isLineBeginning = true - for l := range notifications { - if l.Output != nil { - continue - } - if l.Result != nil { - if printResultDifference(result, l.Result, steps) { - isLineBeginning = true - } - result = l.Result - continue - } - - printStructuredLogLines(l.Log, &isLineBeginning) - } - - ui.NL() - + result := printTestWorkflowLogs(signature, notifications) return result, nil } From 93b7ac62ade920d8f1e45f8a78607368e46fd6dd Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 27 Nov 2024 13:11:54 +0300 Subject: [PATCH 08/40] fix: check service name Signed-off-by: Vladislav Sukhin --- cmd/kubectl-testkube/commands/testworkflows/run.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index 663924d2ac..dfd1185230 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -336,8 +336,7 @@ func watchTestWorkflowLogs(id string, signature []testkube.TestWorkflowSignature return nil, err } - result := printTestWorkflowLogs(signature, notifications) - return result, nil + return printTestWorkflowLogs(signature, notifications), nil } func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, @@ -370,8 +369,7 @@ func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, break } - result := printTestWorkflowLogs(signature, notifications) - return result, nil + return printTestWorkflowLogs(signature, notifications), nil } func printStatusHeader(i, n int, name string) { From cf2dd76d944cdb30426f13ec72c1dc96f37d34d1 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 27 Nov 2024 13:13:20 +0300 Subject: [PATCH 09/40] fix: log comment Signed-off-by: Vladislav Sukhin --- cmd/kubectl-testkube/commands/testworkflows/run.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index dfd1185230..c5e4c45f70 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -341,7 +341,7 @@ func watchTestWorkflowLogs(id string, signature []testkube.TestWorkflowSignature func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, signature []testkube.TestWorkflowSignature, client apiclientv1.Client) (*testkube.TestWorkflowResult, error) { - ui.Info("Getting logs from test workflow service pod", fmt.Sprintf("%s-%s-%d", id, serviceName, serviceIndex)) + ui.Info("Getting logs from test workflow service job", fmt.Sprintf("%s-%s-%d", id, serviceName, serviceIndex)) var ( notifications chan testkube.TestWorkflowExecutionNotification From fff63c0cf82d65be0a0bb804ada14000dc54ba22 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 27 Nov 2024 13:27:50 +0300 Subject: [PATCH 10/40] fix: check for testworkflow service Signed-off-by: Vladislav Sukhin --- internal/app/api/v1/server.go | 4 +-- internal/app/api/v1/testworkflowexecutions.go | 28 +++++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/internal/app/api/v1/server.go b/internal/app/api/v1/server.go index 139f8e9863..816783fee4 100644 --- a/internal/app/api/v1/server.go +++ b/internal/app/api/v1/server.go @@ -150,9 +150,9 @@ func (s *TestkubeAPI) Init(server server.HTTPServer) { testWorkflowExecutions.Post("/", s.ExecuteTestWorkflowHandler()) testWorkflowExecutions.Get("/:executionID", s.GetTestWorkflowExecutionHandler()) testWorkflowExecutions.Get("/:executionID/notifications", s.StreamTestWorkflowExecutionNotificationsHandler()) - testWorkflowExecutions.Get("/:executionID/notifications/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsHandler()) testWorkflowExecutions.Get("/:executionID/notifications/stream", s.StreamTestWorkflowExecutionNotificationsWebSocketHandler()) - testWorkflowExecutions.Get("/:executionID/notifications/stream/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsWebSocketHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/stream/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsWebSocketHandler()) testWorkflowExecutions.Post("/:executionID/abort", s.AbortTestWorkflowExecutionHandler()) testWorkflowExecutions.Post("/:executionID/pause", s.PauseTestWorkflowExecutionHandler()) testWorkflowExecutions.Post("/:executionID/resume", s.ResumeTestWorkflowExecutionHandler()) diff --git a/internal/app/api/v1/testworkflowexecutions.go b/internal/app/api/v1/testworkflowexecutions.go index 9e56997857..a806588161 100644 --- a/internal/app/api/v1/testworkflowexecutions.go +++ b/internal/app/api/v1/testworkflowexecutions.go @@ -103,13 +103,21 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionServiceNotificationsHandler() f return s.ClientError(c, errPrefix, err) } + found := false + if execution.Workflow != nil && execution.Workflow.Spec != nil { + _, found = execution.Workflow.Spec.Services[serviceName] + } + + if !found { + return s.ClientError(c, errPrefix, errors.New("unknown service for test workflow execution")) + } + // Check for the logs id := fmt.Sprintf("%s-%s-%s", execution.Id, serviceName, serviceIndex) notifications := s.ExecutionWorkerClient.Notifications(ctx, id, executionworkertypes.NotificationsOptions{ Hints: executionworkertypes.Hints{ - Namespace: execution.Namespace, - // ScheduledAt: common.Ptr(execution.ScheduledAt), - // Signature: execution.Signature, + Namespace: execution.Namespace, + ScheduledAt: common.Ptr(execution.ScheduledAt), }, }) if notifications.Err() != nil { @@ -179,13 +187,21 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionServiceNotificationsWebSocketHa return } + found := false + if execution.Workflow != nil && execution.Workflow.Spec != nil { + _, found = execution.Workflow.Spec.Services[serviceName] + } + + if !found { + return + } + // Check for the logs id := fmt.Sprintf("%s-%s-%s", execution.Id, serviceName, serviceIndex) notifications := s.ExecutionWorkerClient.Notifications(ctx, id, executionworkertypes.NotificationsOptions{ Hints: executionworkertypes.Hints{ - Namespace: execution.Namespace, - // Signature: execution.Signature, - // ScheduledAt: common.Ptr(execution.ScheduledAt), + Namespace: execution.Namespace, + ScheduledAt: common.Ptr(execution.ScheduledAt), }, }) if notifications.Err() != nil { From c7bed19ac731bd0f33986f7eee8e93f53f03e155 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 27 Nov 2024 14:44:59 +0300 Subject: [PATCH 11/40] fix: friendly error Signed-off-by: Vladislav Sukhin --- .../commands/testworkflows/run.go | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index c5e4c45f70..1e5b30bf00 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -345,25 +345,29 @@ func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, var ( notifications chan testkube.TestWorkflowExecutionNotification - err error + nErr error ) for { - notifications, err = client.GetTestWorkflowExecutionServiceNotifications(id, serviceName, serviceIndex) - if err != nil { - execution, err := client.GetTestWorkflowExecution(id) - if err != nil { - return nil, err + notifications, nErr = client.GetTestWorkflowExecutionServiceNotifications(id, serviceName, serviceIndex) + if nErr != nil { + execution, cErr := client.GetTestWorkflowExecution(id) + if cErr != nil { + return nil, cErr } - if execution.Result != nil && !execution.Result.IsFinished() { - time.Sleep(serviceLogsCheckDelay) - continue + if execution.Result != nil { + if execution.Result.IsFinished() { + nErr = errors.New("test workflow execution is finished") + } else { + time.Sleep(serviceLogsCheckDelay) + continue + } } } - if err != nil { - return nil, err + if nErr != nil { + return nil, nErr } break From f34e5d1f27a74e1fbc81a1ff34615570b5f05617 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 27 Nov 2024 14:52:58 +0300 Subject: [PATCH 12/40] fix: add spinner Signed-off-by: Vladislav Sukhin --- cmd/kubectl-testkube/commands/testworkflows/run.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index 1e5b30bf00..cbe7061a6b 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -348,11 +348,13 @@ func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, nErr error ) + spinner := ui.NewSpinner("Waiting for service logs") for { notifications, nErr = client.GetTestWorkflowExecutionServiceNotifications(id, serviceName, serviceIndex) if nErr != nil { execution, cErr := client.GetTestWorkflowExecution(id) if cErr != nil { + spinner.Fail() return nil, cErr } @@ -367,12 +369,14 @@ func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, } if nErr != nil { + spinner.Fail() return nil, nErr } break } + spinner.Success() return printTestWorkflowLogs(signature, notifications), nil } From 07ce30817b7cfe8eb919afde392f080e18b0b839 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 27 Nov 2024 18:01:35 +0300 Subject: [PATCH 13/40] feat: proto for service notifications Signed-off-by: Vladislav Sukhin --- pkg/cloud/service.pb.go | 463 ++++++++++++++++++++++++++--------- pkg/cloud/service_grpc.pb.go | 68 +++++ proto/service.proto | 18 ++ 3 files changed, 435 insertions(+), 114 deletions(-) diff --git a/pkg/cloud/service.pb.go b/pkg/cloud/service.pb.go index 12eabcdee4..5d4252ebfd 100644 --- a/pkg/cloud/service.pb.go +++ b/pkg/cloud/service.pb.go @@ -1076,6 +1076,172 @@ func (x *CredentialResponse) GetContent() []byte { return nil } +type TestWorkflowServiceNotificationsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + StreamId string `protobuf:"bytes,1,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + ExecutionId string `protobuf:"bytes,2,opt,name=execution_id,json=executionId,proto3" json:"execution_id,omitempty"` + ServiceName string `protobuf:"bytes,3,opt,name=service_name,json=serviceName,proto3" json:"service_name,omitempty"` + ServiceIndex int32 `protobuf:"varint,4,opt,name=service_index,json=serviceIndex,proto3" json:"service_index,omitempty"` + RequestType TestWorkflowNotificationsRequestType `protobuf:"varint,5,opt,name=request_type,json=requestType,proto3,enum=cloud.TestWorkflowNotificationsRequestType" json:"request_type,omitempty"` +} + +func (x *TestWorkflowServiceNotificationsRequest) Reset() { + *x = TestWorkflowServiceNotificationsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_service_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestWorkflowServiceNotificationsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestWorkflowServiceNotificationsRequest) ProtoMessage() {} + +func (x *TestWorkflowServiceNotificationsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_service_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestWorkflowServiceNotificationsRequest.ProtoReflect.Descriptor instead. +func (*TestWorkflowServiceNotificationsRequest) Descriptor() ([]byte, []int) { + return file_proto_service_proto_rawDescGZIP(), []int{14} +} + +func (x *TestWorkflowServiceNotificationsRequest) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *TestWorkflowServiceNotificationsRequest) GetExecutionId() string { + if x != nil { + return x.ExecutionId + } + return "" +} + +func (x *TestWorkflowServiceNotificationsRequest) GetServiceName() string { + if x != nil { + return x.ServiceName + } + return "" +} + +func (x *TestWorkflowServiceNotificationsRequest) GetServiceIndex() int32 { + if x != nil { + return x.ServiceIndex + } + return 0 +} + +func (x *TestWorkflowServiceNotificationsRequest) GetRequestType() TestWorkflowNotificationsRequestType { + if x != nil { + return x.RequestType + } + return TestWorkflowNotificationsRequestType_WORKFLOW_STREAM_LOG_MESSAGE +} + +type TestWorkflowServiceNotificationsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + StreamId string `protobuf:"bytes,1,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + SeqNo uint32 `protobuf:"varint,2,opt,name=seq_no,json=seqNo,proto3" json:"seq_no,omitempty"` + Timestamp string `protobuf:"bytes,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Ref string `protobuf:"bytes,4,opt,name=ref,proto3" json:"ref,omitempty"` + Type TestWorkflowNotificationType `protobuf:"varint,5,opt,name=type,proto3,enum=cloud.TestWorkflowNotificationType" json:"type,omitempty"` + Message string `protobuf:"bytes,6,opt,name=message,proto3" json:"message,omitempty"` // based on type: log/error = inline, others = serialized to JSON +} + +func (x *TestWorkflowServiceNotificationsResponse) Reset() { + *x = TestWorkflowServiceNotificationsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_service_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestWorkflowServiceNotificationsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestWorkflowServiceNotificationsResponse) ProtoMessage() {} + +func (x *TestWorkflowServiceNotificationsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_service_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestWorkflowServiceNotificationsResponse.ProtoReflect.Descriptor instead. +func (*TestWorkflowServiceNotificationsResponse) Descriptor() ([]byte, []int) { + return file_proto_service_proto_rawDescGZIP(), []int{15} +} + +func (x *TestWorkflowServiceNotificationsResponse) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *TestWorkflowServiceNotificationsResponse) GetSeqNo() uint32 { + if x != nil { + return x.SeqNo + } + return 0 +} + +func (x *TestWorkflowServiceNotificationsResponse) GetTimestamp() string { + if x != nil { + return x.Timestamp + } + return "" +} + +func (x *TestWorkflowServiceNotificationsResponse) GetRef() string { + if x != nil { + return x.Ref + } + return "" +} + +func (x *TestWorkflowServiceNotificationsResponse) GetType() TestWorkflowNotificationType { + if x != nil { + return x.Type + } + return TestWorkflowNotificationType_WORKFLOW_STREAM_ERROR +} + +func (x *TestWorkflowServiceNotificationsResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + var File_proto_service_proto protoreflect.FileDescriptor var file_proto_service_proto_rawDesc = []byte{ @@ -1193,71 +1359,110 @@ var file_proto_service_proto_rawDesc = []byte{ 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x2e, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2a, 0x48, 0x0a, 0x15, 0x4c, 0x6f, 0x67, 0x73, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x5f, 0x4d, - 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x52, 0x45, - 0x41, 0x4d, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, - 0x01, 0x2a, 0x69, 0x0a, 0x24, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x57, 0x4f, 0x52, - 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, - 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x57, 0x4f, - 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x48, 0x45, - 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x01, 0x2a, 0x8a, 0x01, 0x0a, - 0x1c, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, - 0x15, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, - 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x57, 0x4f, 0x52, 0x4b, - 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x10, - 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, - 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x02, 0x12, 0x1a, 0x0a, - 0x16, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, - 0x5f, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x10, 0x03, 0x2a, 0x4c, 0x0a, 0x06, 0x4f, 0x70, 0x63, - 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x45, 0x58, 0x54, 0x5f, 0x46, 0x52, 0x41, 0x4d, - 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x46, 0x52, - 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, - 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x03, 0x32, 0xd3, 0x04, 0x0a, 0x10, 0x54, 0x65, 0x73, 0x74, - 0x4b, 0x75, 0x62, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x41, 0x50, 0x49, 0x12, 0x3c, 0x0a, 0x07, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, - 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x36, 0x0a, 0x04, 0x53, 0x65, - 0x6e, 0x64, 0x12, 0x14, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, - 0x63, 0x6b, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x28, 0x01, 0x12, 0x35, 0x0a, 0x04, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x15, 0x2e, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x65, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, - 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x1a, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x0d, - 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x19, 0x2e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x7b, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x81, 0x02, 0x0a, 0x27, 0x54, 0x65, 0x73, 0x74, + 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x64, + 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4e, 0x0a, 0x0c, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x2b, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0xe1, 0x01, 0x0a, 0x28, + 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x6f, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x6f, 0x12, 0x1c, 0x0a, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, + 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x37, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x63, 0x6c, 0x6f, + 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, + 0x48, 0x0a, 0x15, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x52, 0x45, + 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x00, + 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, + 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x01, 0x2a, 0x69, 0x0a, 0x24, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x2e, 0x63, - 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x27, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, - 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, - 0x01, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x63, - 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x50, 0x72, 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x72, - 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0b, 0x5a, - 0x09, 0x70, 0x6b, 0x67, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, + 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, + 0x10, 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, + 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, + 0x43, 0x4b, 0x10, 0x01, 0x2a, 0x8a, 0x01, 0x0a, 0x1c, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, + 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, + 0x12, 0x17, 0x0a, 0x13, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, + 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x4f, 0x52, + 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x52, 0x45, 0x53, + 0x55, 0x4c, 0x54, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, + 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x10, + 0x03, 0x2a, 0x4c, 0x0a, 0x06, 0x4f, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x54, + 0x45, 0x58, 0x54, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x42, + 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, + 0x0c, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x03, 0x32, + 0xe6, 0x05, 0x0a, 0x10, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x43, 0x6c, 0x6f, 0x75, + 0x64, 0x41, 0x50, 0x49, 0x12, 0x3c, 0x0a, 0x07, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, + 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, + 0x30, 0x01, 0x12, 0x36, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x14, 0x2e, 0x63, 0x6c, 0x6f, + 0x75, 0x64, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x12, 0x35, 0x0a, 0x04, 0x43, 0x61, + 0x6c, 0x6c, 0x12, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x41, 0x73, 0x79, 0x6e, + 0x63, 0x12, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x28, 0x01, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x6f, + 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x1a, 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x7b, + 0x0a, 0x22, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, + 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x27, + 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x90, 0x01, 0x0a, 0x29, + 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x2f, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x2e, 0x2e, 0x63, 0x6c, 0x6f, + 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x42, + 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, + 0x50, 0x72, 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x61, 0x6c, 0x12, 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, 0x67, 0x2f, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1273,63 +1478,69 @@ func file_proto_service_proto_rawDescGZIP() []byte { } var file_proto_service_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_proto_service_proto_msgTypes = make([]protoimpl.MessageInfo, 16) +var file_proto_service_proto_msgTypes = make([]protoimpl.MessageInfo, 18) var file_proto_service_proto_goTypes = []interface{}{ - (LogsStreamRequestType)(0), // 0: cloud.LogsStreamRequestType - (TestWorkflowNotificationsRequestType)(0), // 1: cloud.TestWorkflowNotificationsRequestType - (TestWorkflowNotificationType)(0), // 2: cloud.TestWorkflowNotificationType - (Opcode)(0), // 3: cloud.Opcode - (*LogsStreamRequest)(nil), // 4: cloud.LogsStreamRequest - (*LogsStreamResponse)(nil), // 5: cloud.LogsStreamResponse - (*CommandRequest)(nil), // 6: cloud.CommandRequest - (*CommandResponse)(nil), // 7: cloud.CommandResponse - (*ExecuteRequest)(nil), // 8: cloud.ExecuteRequest - (*TestWorkflowNotificationsRequest)(nil), // 9: cloud.TestWorkflowNotificationsRequest - (*TestWorkflowNotificationsResponse)(nil), // 10: cloud.TestWorkflowNotificationsResponse - (*ProContextResponse)(nil), // 11: cloud.ProContextResponse - (*Capability)(nil), // 12: cloud.Capability - (*HeaderValue)(nil), // 13: cloud.HeaderValue - (*ExecuteResponse)(nil), // 14: cloud.ExecuteResponse - (*WebsocketData)(nil), // 15: cloud.WebsocketData - (*CredentialRequest)(nil), // 16: cloud.CredentialRequest - (*CredentialResponse)(nil), // 17: cloud.CredentialResponse - nil, // 18: cloud.ExecuteRequest.HeadersEntry - nil, // 19: cloud.ExecuteResponse.HeadersEntry - (*structpb.Struct)(nil), // 20: google.protobuf.Struct - (*emptypb.Empty)(nil), // 21: google.protobuf.Empty + (LogsStreamRequestType)(0), // 0: cloud.LogsStreamRequestType + (TestWorkflowNotificationsRequestType)(0), // 1: cloud.TestWorkflowNotificationsRequestType + (TestWorkflowNotificationType)(0), // 2: cloud.TestWorkflowNotificationType + (Opcode)(0), // 3: cloud.Opcode + (*LogsStreamRequest)(nil), // 4: cloud.LogsStreamRequest + (*LogsStreamResponse)(nil), // 5: cloud.LogsStreamResponse + (*CommandRequest)(nil), // 6: cloud.CommandRequest + (*CommandResponse)(nil), // 7: cloud.CommandResponse + (*ExecuteRequest)(nil), // 8: cloud.ExecuteRequest + (*TestWorkflowNotificationsRequest)(nil), // 9: cloud.TestWorkflowNotificationsRequest + (*TestWorkflowNotificationsResponse)(nil), // 10: cloud.TestWorkflowNotificationsResponse + (*ProContextResponse)(nil), // 11: cloud.ProContextResponse + (*Capability)(nil), // 12: cloud.Capability + (*HeaderValue)(nil), // 13: cloud.HeaderValue + (*ExecuteResponse)(nil), // 14: cloud.ExecuteResponse + (*WebsocketData)(nil), // 15: cloud.WebsocketData + (*CredentialRequest)(nil), // 16: cloud.CredentialRequest + (*CredentialResponse)(nil), // 17: cloud.CredentialResponse + (*TestWorkflowServiceNotificationsRequest)(nil), // 18: cloud.TestWorkflowServiceNotificationsRequest + (*TestWorkflowServiceNotificationsResponse)(nil), // 19: cloud.TestWorkflowServiceNotificationsResponse + nil, // 20: cloud.ExecuteRequest.HeadersEntry + nil, // 21: cloud.ExecuteResponse.HeadersEntry + (*structpb.Struct)(nil), // 22: google.protobuf.Struct + (*emptypb.Empty)(nil), // 23: google.protobuf.Empty } var file_proto_service_proto_depIdxs = []int32{ 0, // 0: cloud.LogsStreamRequest.request_type:type_name -> cloud.LogsStreamRequestType - 20, // 1: cloud.CommandRequest.payload:type_name -> google.protobuf.Struct - 18, // 2: cloud.ExecuteRequest.headers:type_name -> cloud.ExecuteRequest.HeadersEntry + 22, // 1: cloud.CommandRequest.payload:type_name -> google.protobuf.Struct + 20, // 2: cloud.ExecuteRequest.headers:type_name -> cloud.ExecuteRequest.HeadersEntry 1, // 3: cloud.TestWorkflowNotificationsRequest.request_type:type_name -> cloud.TestWorkflowNotificationsRequestType 2, // 4: cloud.TestWorkflowNotificationsResponse.type:type_name -> cloud.TestWorkflowNotificationType 12, // 5: cloud.ProContextResponse.capabilities:type_name -> cloud.Capability - 19, // 6: cloud.ExecuteResponse.headers:type_name -> cloud.ExecuteResponse.HeadersEntry + 21, // 6: cloud.ExecuteResponse.headers:type_name -> cloud.ExecuteResponse.HeadersEntry 3, // 7: cloud.WebsocketData.opcode:type_name -> cloud.Opcode - 13, // 8: cloud.ExecuteRequest.HeadersEntry.value:type_name -> cloud.HeaderValue - 13, // 9: cloud.ExecuteResponse.HeadersEntry.value:type_name -> cloud.HeaderValue - 14, // 10: cloud.TestKubeCloudAPI.Execute:input_type -> cloud.ExecuteResponse - 15, // 11: cloud.TestKubeCloudAPI.Send:input_type -> cloud.WebsocketData - 6, // 12: cloud.TestKubeCloudAPI.Call:input_type -> cloud.CommandRequest - 14, // 13: cloud.TestKubeCloudAPI.ExecuteAsync:input_type -> cloud.ExecuteResponse - 5, // 14: cloud.TestKubeCloudAPI.GetLogsStream:input_type -> cloud.LogsStreamResponse - 10, // 15: cloud.TestKubeCloudAPI.GetTestWorkflowNotificationsStream:input_type -> cloud.TestWorkflowNotificationsResponse - 21, // 16: cloud.TestKubeCloudAPI.GetProContext:input_type -> google.protobuf.Empty - 16, // 17: cloud.TestKubeCloudAPI.GetCredential:input_type -> cloud.CredentialRequest - 8, // 18: cloud.TestKubeCloudAPI.Execute:output_type -> cloud.ExecuteRequest - 21, // 19: cloud.TestKubeCloudAPI.Send:output_type -> google.protobuf.Empty - 7, // 20: cloud.TestKubeCloudAPI.Call:output_type -> cloud.CommandResponse - 8, // 21: cloud.TestKubeCloudAPI.ExecuteAsync:output_type -> cloud.ExecuteRequest - 4, // 22: cloud.TestKubeCloudAPI.GetLogsStream:output_type -> cloud.LogsStreamRequest - 9, // 23: cloud.TestKubeCloudAPI.GetTestWorkflowNotificationsStream:output_type -> cloud.TestWorkflowNotificationsRequest - 11, // 24: cloud.TestKubeCloudAPI.GetProContext:output_type -> cloud.ProContextResponse - 17, // 25: cloud.TestKubeCloudAPI.GetCredential:output_type -> cloud.CredentialResponse - 18, // [18:26] is the sub-list for method output_type - 10, // [10:18] is the sub-list for method input_type - 10, // [10:10] is the sub-list for extension type_name - 10, // [10:10] is the sub-list for extension extendee - 0, // [0:10] is the sub-list for field type_name + 1, // 8: cloud.TestWorkflowServiceNotificationsRequest.request_type:type_name -> cloud.TestWorkflowNotificationsRequestType + 2, // 9: cloud.TestWorkflowServiceNotificationsResponse.type:type_name -> cloud.TestWorkflowNotificationType + 13, // 10: cloud.ExecuteRequest.HeadersEntry.value:type_name -> cloud.HeaderValue + 13, // 11: cloud.ExecuteResponse.HeadersEntry.value:type_name -> cloud.HeaderValue + 14, // 12: cloud.TestKubeCloudAPI.Execute:input_type -> cloud.ExecuteResponse + 15, // 13: cloud.TestKubeCloudAPI.Send:input_type -> cloud.WebsocketData + 6, // 14: cloud.TestKubeCloudAPI.Call:input_type -> cloud.CommandRequest + 14, // 15: cloud.TestKubeCloudAPI.ExecuteAsync:input_type -> cloud.ExecuteResponse + 5, // 16: cloud.TestKubeCloudAPI.GetLogsStream:input_type -> cloud.LogsStreamResponse + 10, // 17: cloud.TestKubeCloudAPI.GetTestWorkflowNotificationsStream:input_type -> cloud.TestWorkflowNotificationsResponse + 19, // 18: cloud.TestKubeCloudAPI.GetTestWorkflowServiceNotificationsStream:input_type -> cloud.TestWorkflowServiceNotificationsResponse + 23, // 19: cloud.TestKubeCloudAPI.GetProContext:input_type -> google.protobuf.Empty + 16, // 20: cloud.TestKubeCloudAPI.GetCredential:input_type -> cloud.CredentialRequest + 8, // 21: cloud.TestKubeCloudAPI.Execute:output_type -> cloud.ExecuteRequest + 23, // 22: cloud.TestKubeCloudAPI.Send:output_type -> google.protobuf.Empty + 7, // 23: cloud.TestKubeCloudAPI.Call:output_type -> cloud.CommandResponse + 8, // 24: cloud.TestKubeCloudAPI.ExecuteAsync:output_type -> cloud.ExecuteRequest + 4, // 25: cloud.TestKubeCloudAPI.GetLogsStream:output_type -> cloud.LogsStreamRequest + 9, // 26: cloud.TestKubeCloudAPI.GetTestWorkflowNotificationsStream:output_type -> cloud.TestWorkflowNotificationsRequest + 18, // 27: cloud.TestKubeCloudAPI.GetTestWorkflowServiceNotificationsStream:output_type -> cloud.TestWorkflowServiceNotificationsRequest + 11, // 28: cloud.TestKubeCloudAPI.GetProContext:output_type -> cloud.ProContextResponse + 17, // 29: cloud.TestKubeCloudAPI.GetCredential:output_type -> cloud.CredentialResponse + 21, // [21:30] is the sub-list for method output_type + 12, // [12:21] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_proto_service_proto_init() } @@ -1506,6 +1717,30 @@ func file_proto_service_proto_init() { return nil } } + file_proto_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestWorkflowServiceNotificationsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestWorkflowServiceNotificationsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1513,7 +1748,7 @@ func file_proto_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_service_proto_rawDesc, NumEnums: 4, - NumMessages: 16, + NumMessages: 18, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/cloud/service_grpc.pb.go b/pkg/cloud/service_grpc.pb.go index 5b329874fe..01464de17a 100644 --- a/pkg/cloud/service_grpc.pb.go +++ b/pkg/cloud/service_grpc.pb.go @@ -31,6 +31,7 @@ type TestKubeCloudAPIClient interface { ExecuteAsync(ctx context.Context, opts ...grpc.CallOption) (TestKubeCloudAPI_ExecuteAsyncClient, error) GetLogsStream(ctx context.Context, opts ...grpc.CallOption) (TestKubeCloudAPI_GetLogsStreamClient, error) GetTestWorkflowNotificationsStream(ctx context.Context, opts ...grpc.CallOption) (TestKubeCloudAPI_GetTestWorkflowNotificationsStreamClient, error) + GetTestWorkflowServiceNotificationsStream(ctx context.Context, opts ...grpc.CallOption) (TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamClient, error) GetProContext(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ProContextResponse, error) GetCredential(ctx context.Context, in *CredentialRequest, opts ...grpc.CallOption) (*CredentialResponse, error) } @@ -210,6 +211,37 @@ func (x *testKubeCloudAPIGetTestWorkflowNotificationsStreamClient) Recv() (*Test return m, nil } +func (c *testKubeCloudAPIClient) GetTestWorkflowServiceNotificationsStream(ctx context.Context, opts ...grpc.CallOption) (TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamClient, error) { + stream, err := c.cc.NewStream(ctx, &TestKubeCloudAPI_ServiceDesc.Streams[5], "/cloud.TestKubeCloudAPI/GetTestWorkflowServiceNotificationsStream", opts...) + if err != nil { + return nil, err + } + x := &testKubeCloudAPIGetTestWorkflowServiceNotificationsStreamClient{stream} + return x, nil +} + +type TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamClient interface { + Send(*TestWorkflowServiceNotificationsResponse) error + Recv() (*TestWorkflowServiceNotificationsRequest, error) + grpc.ClientStream +} + +type testKubeCloudAPIGetTestWorkflowServiceNotificationsStreamClient struct { + grpc.ClientStream +} + +func (x *testKubeCloudAPIGetTestWorkflowServiceNotificationsStreamClient) Send(m *TestWorkflowServiceNotificationsResponse) error { + return x.ClientStream.SendMsg(m) +} + +func (x *testKubeCloudAPIGetTestWorkflowServiceNotificationsStreamClient) Recv() (*TestWorkflowServiceNotificationsRequest, error) { + m := new(TestWorkflowServiceNotificationsRequest) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func (c *testKubeCloudAPIClient) GetProContext(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ProContextResponse, error) { out := new(ProContextResponse) err := c.cc.Invoke(ctx, "/cloud.TestKubeCloudAPI/GetProContext", in, out, opts...) @@ -240,6 +272,7 @@ type TestKubeCloudAPIServer interface { ExecuteAsync(TestKubeCloudAPI_ExecuteAsyncServer) error GetLogsStream(TestKubeCloudAPI_GetLogsStreamServer) error GetTestWorkflowNotificationsStream(TestKubeCloudAPI_GetTestWorkflowNotificationsStreamServer) error + GetTestWorkflowServiceNotificationsStream(TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamServer) error GetProContext(context.Context, *emptypb.Empty) (*ProContextResponse, error) GetCredential(context.Context, *CredentialRequest) (*CredentialResponse, error) mustEmbedUnimplementedTestKubeCloudAPIServer() @@ -267,6 +300,9 @@ func (UnimplementedTestKubeCloudAPIServer) GetLogsStream(TestKubeCloudAPI_GetLog func (UnimplementedTestKubeCloudAPIServer) GetTestWorkflowNotificationsStream(TestKubeCloudAPI_GetTestWorkflowNotificationsStreamServer) error { return status.Errorf(codes.Unimplemented, "method GetTestWorkflowNotificationsStream not implemented") } +func (UnimplementedTestKubeCloudAPIServer) GetTestWorkflowServiceNotificationsStream(TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamServer) error { + return status.Errorf(codes.Unimplemented, "method GetTestWorkflowServiceNotificationsStream not implemented") +} func (UnimplementedTestKubeCloudAPIServer) GetProContext(context.Context, *emptypb.Empty) (*ProContextResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetProContext not implemented") } @@ -434,6 +470,32 @@ func (x *testKubeCloudAPIGetTestWorkflowNotificationsStreamServer) Recv() (*Test return m, nil } +func _TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStream_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(TestKubeCloudAPIServer).GetTestWorkflowServiceNotificationsStream(&testKubeCloudAPIGetTestWorkflowServiceNotificationsStreamServer{stream}) +} + +type TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamServer interface { + Send(*TestWorkflowServiceNotificationsRequest) error + Recv() (*TestWorkflowServiceNotificationsResponse, error) + grpc.ServerStream +} + +type testKubeCloudAPIGetTestWorkflowServiceNotificationsStreamServer struct { + grpc.ServerStream +} + +func (x *testKubeCloudAPIGetTestWorkflowServiceNotificationsStreamServer) Send(m *TestWorkflowServiceNotificationsRequest) error { + return x.ServerStream.SendMsg(m) +} + +func (x *testKubeCloudAPIGetTestWorkflowServiceNotificationsStreamServer) Recv() (*TestWorkflowServiceNotificationsResponse, error) { + m := new(TestWorkflowServiceNotificationsResponse) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func _TestKubeCloudAPI_GetProContext_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(emptypb.Empty) if err := dec(in); err != nil { @@ -520,6 +582,12 @@ var TestKubeCloudAPI_ServiceDesc = grpc.ServiceDesc{ ServerStreams: true, ClientStreams: true, }, + { + StreamName: "GetTestWorkflowServiceNotificationsStream", + Handler: _TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStream_Handler, + ServerStreams: true, + ClientStreams: true, + }, }, Metadata: "proto/service.proto", } diff --git a/proto/service.proto b/proto/service.proto index 7ed7f0db95..9d56e88d6c 100644 --- a/proto/service.proto +++ b/proto/service.proto @@ -16,6 +16,7 @@ service TestKubeCloudAPI { rpc ExecuteAsync(stream ExecuteResponse) returns (stream ExecuteRequest); rpc GetLogsStream(stream LogsStreamResponse) returns (stream LogsStreamRequest); rpc GetTestWorkflowNotificationsStream(stream TestWorkflowNotificationsResponse) returns (stream TestWorkflowNotificationsRequest); + rpc GetTestWorkflowServiceNotificationsStream(stream TestWorkflowServiceNotificationsResponse) returns (stream TestWorkflowServiceNotificationsRequest); rpc GetProContext(google.protobuf.Empty) returns (ProContextResponse); rpc GetCredential(CredentialRequest) returns (CredentialResponse); } @@ -124,3 +125,20 @@ message CredentialRequest { message CredentialResponse { bytes content = 1; } + +message TestWorkflowServiceNotificationsRequest { + string stream_id = 1; + string execution_id = 2; + string service_name = 3; + int32 service_index = 4; + TestWorkflowNotificationsRequestType request_type = 5; +} + +message TestWorkflowServiceNotificationsResponse { + string stream_id = 1; + uint32 seq_no = 2; + string timestamp = 3; + string ref = 4; + TestWorkflowNotificationType type = 5; + string message = 6; // based on type: log/error = inline, others = serialized to JSON +} From 9c03fe4c1a54ede2d11bb573aa6b49ca567aea64 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Wed, 27 Nov 2024 20:56:29 +0300 Subject: [PATCH 14/40] feat: add cloud grpc method for server notifications Signed-off-by: Vladislav Sukhin --- cmd/api-server/commons/commons.go | 25 ++-- cmd/api-server/main.go | 17 +++ internal/config/config.go | 85 +++++++------- internal/config/procontext.go | 25 ++-- pkg/agent/agent.go | 28 ++++- pkg/agent/agent_test.go | 9 +- pkg/agent/events_test.go | 9 +- pkg/agent/logs_test.go | 8 +- pkg/agent/testworkflows.go | 187 ++++++++++++++++++++++++++++++ 9 files changed, 319 insertions(+), 74 deletions(-) diff --git a/cmd/api-server/commons/commons.go b/cmd/api-server/commons/commons.go index 2754634026..b689d51935 100644 --- a/cmd/api-server/commons/commons.go +++ b/cmd/api-server/commons/commons.go @@ -282,18 +282,19 @@ func ReadDefaultExecutors(cfg *config.Config) (executors []testkube.ExecutorDeta func ReadProContext(ctx context.Context, cfg *config.Config, grpcClient cloud.TestKubeCloudAPIClient) config.ProContext { proContext := config.ProContext{ - APIKey: cfg.TestkubeProAPIKey, - URL: cfg.TestkubeProURL, - TLSInsecure: cfg.TestkubeProTLSInsecure, - WorkerCount: cfg.TestkubeProWorkerCount, - LogStreamWorkerCount: cfg.TestkubeProLogStreamWorkerCount, - WorkflowNotificationsWorkerCount: cfg.TestkubeProWorkflowNotificationsWorkerCount, - SkipVerify: cfg.TestkubeProSkipVerify, - EnvID: cfg.TestkubeProEnvID, - OrgID: cfg.TestkubeProOrgID, - Migrate: cfg.TestkubeProMigrate, - ConnectionTimeout: cfg.TestkubeProConnectionTimeout, - DashboardURI: cfg.TestkubeDashboardURI, + APIKey: cfg.TestkubeProAPIKey, + URL: cfg.TestkubeProURL, + TLSInsecure: cfg.TestkubeProTLSInsecure, + WorkerCount: cfg.TestkubeProWorkerCount, + LogStreamWorkerCount: cfg.TestkubeProLogStreamWorkerCount, + WorkflowNotificationsWorkerCount: cfg.TestkubeProWorkflowNotificationsWorkerCount, + WorkflowServiceNotificationsWorkerCount: cfg.TestkubeProWorkflowServiceNotificationsWorkerCount, + SkipVerify: cfg.TestkubeProSkipVerify, + EnvID: cfg.TestkubeProEnvID, + OrgID: cfg.TestkubeProOrgID, + Migrate: cfg.TestkubeProMigrate, + ConnectionTimeout: cfg.TestkubeProConnectionTimeout, + DashboardURI: cfg.TestkubeDashboardURI, } if cfg.TestkubeProAPIKey == "" || grpcClient == nil { diff --git a/cmd/api-server/main.go b/cmd/api-server/main.go index f3bcd976f2..8a349b80f5 100644 --- a/cmd/api-server/main.go +++ b/cmd/api-server/main.go @@ -325,6 +325,22 @@ func main() { } return notifications.Channel(), nil } + getTestWorkflowServiceNotificationsStream := func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) { + execution, err := testWorkflowResultsRepository.Get(ctx, executionID) + if err != nil { + return nil, err + } + notifications := executionWorker.Notifications(ctx, fmt.Sprintf("%s-%s-%d", execution.Id, serviceName, serviceIndex), executionworkertypes.NotificationsOptions{ + Hints: executionworkertypes.Hints{ + Namespace: execution.Namespace, + ScheduledAt: common.Ptr(execution.ScheduledAt), + }, + }) + if notifications.Err() != nil { + return nil, notifications.Err() + } + return notifications.Channel(), nil + } getDeprecatedLogStream := func(ctx context.Context, executionID string) (chan output.Output, error) { return nil, errors.New("deprecated features have been disabled") } @@ -337,6 +353,7 @@ func main() { grpcClient, getDeprecatedLogStream, getTestWorkflowNotificationsStream, + getTestWorkflowServiceNotificationsStream, clusterId, cfg.TestkubeClusterName, features, diff --git a/internal/config/config.go b/internal/config/config.go index 9c2d6fc83f..0394c8d981 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -40,48 +40,49 @@ type Config struct { LogsStorage string `envconfig:"LOGS_STORAGE" default:""` WorkflowStorage string `envconfig:"WORKFLOW_STORAGE" default:"crd"` // WhitelistedContainers is a list of containers from which logs should be collected. - WhitelistedContainers []string `envconfig:"WHITELISTED_CONTAINERS" default:"init,logs,scraper"` - NatsEmbedded bool `envconfig:"NATS_EMBEDDED" default:"false"` - NatsEmbeddedStoreDir string `envconfig:"NATS_EMBEDDED_STORE_DIR" default:"/app/nats"` - NatsURI string `envconfig:"NATS_URI" default:"nats://localhost:4222"` - NatsSecure bool `envconfig:"NATS_SECURE" default:"false"` - NatsSkipVerify bool `envconfig:"NATS_SKIP_VERIFY" default:"false"` - NatsCertFile string `envconfig:"NATS_CERT_FILE" default:""` - NatsKeyFile string `envconfig:"NATS_KEY_FILE" default:""` - NatsCAFile string `envconfig:"NATS_CA_FILE" default:""` - NatsConnectTimeout time.Duration `envconfig:"NATS_CONNECT_TIMEOUT" default:"5s"` - JobServiceAccountName string `envconfig:"JOB_SERVICE_ACCOUNT_NAME" default:""` - JobTemplateFile string `envconfig:"JOB_TEMPLATE_FILE" default:""` - DisableTestTriggers bool `envconfig:"DISABLE_TEST_TRIGGERS" default:"false"` - TestkubeDefaultExecutors string `envconfig:"TESTKUBE_DEFAULT_EXECUTORS" default:""` - TestkubeEnabledExecutors string `envconfig:"TESTKUBE_ENABLED_EXECUTORS" default:""` - TestkubeTemplateJob string `envconfig:"TESTKUBE_TEMPLATE_JOB" default:""` - TestkubeContainerTemplateJob string `envconfig:"TESTKUBE_CONTAINER_TEMPLATE_JOB" default:""` - TestkubeContainerTemplateScraper string `envconfig:"TESTKUBE_CONTAINER_TEMPLATE_SCRAPER" default:""` - TestkubeContainerTemplatePVC string `envconfig:"TESTKUBE_CONTAINER_TEMPLATE_PVC" default:""` - TestkubeTemplateSlavePod string `envconfig:"TESTKUBE_TEMPLATE_SLAVE_POD" default:""` - TestkubeConfigDir string `envconfig:"TESTKUBE_CONFIG_DIR" default:"config"` - TestkubeAnalyticsEnabled bool `envconfig:"TESTKUBE_ANALYTICS_ENABLED" default:"false"` - TestkubeReadonlyExecutors bool `envconfig:"TESTKUBE_READONLY_EXECUTORS" default:"false"` - TestkubeNamespace string `envconfig:"TESTKUBE_NAMESPACE" default:"testkube"` - TestkubeProAPIKey string `envconfig:"TESTKUBE_PRO_API_KEY" default:""` - TestkubeProURL string `envconfig:"TESTKUBE_PRO_URL" default:""` - TestkubeProTLSInsecure bool `envconfig:"TESTKUBE_PRO_TLS_INSECURE" default:"false"` - TestkubeProWorkerCount int `envconfig:"TESTKUBE_PRO_WORKER_COUNT" default:"50"` - TestkubeProLogStreamWorkerCount int `envconfig:"TESTKUBE_PRO_LOG_STREAM_WORKER_COUNT" default:"25"` - TestkubeProWorkflowNotificationsWorkerCount int `envconfig:"TESTKUBE_PRO_WORKFLOW_NOTIFICATIONS_STREAM_WORKER_COUNT" default:"25"` - TestkubeProSkipVerify bool `envconfig:"TESTKUBE_PRO_SKIP_VERIFY" default:"false"` - TestkubeProEnvID string `envconfig:"TESTKUBE_PRO_ENV_ID" default:""` - TestkubeProOrgID string `envconfig:"TESTKUBE_PRO_ORG_ID" default:""` - TestkubeProMigrate string `envconfig:"TESTKUBE_PRO_MIGRATE" default:"false"` - TestkubeProConnectionTimeout int `envconfig:"TESTKUBE_PRO_CONNECTION_TIMEOUT" default:"10"` - TestkubeProCertFile string `envconfig:"TESTKUBE_PRO_CERT_FILE" default:""` - TestkubeProKeyFile string `envconfig:"TESTKUBE_PRO_KEY_FILE" default:""` - TestkubeProTLSSecret string `envconfig:"TESTKUBE_PRO_TLS_SECRET" default:""` - TestkubeProRunnerCustomCASecret string `envconfig:"TESTKUBE_PRO_RUNNER_CUSTOM_CA_SECRET" default:""` - TestkubeWatcherNamespaces string `envconfig:"TESTKUBE_WATCHER_NAMESPACES" default:""` - TestkubeRegistry string `envconfig:"TESTKUBE_REGISTRY" default:""` - TestkubePodStartTimeout time.Duration `envconfig:"TESTKUBE_POD_START_TIMEOUT" default:"30m"` + WhitelistedContainers []string `envconfig:"WHITELISTED_CONTAINERS" default:"init,logs,scraper"` + NatsEmbedded bool `envconfig:"NATS_EMBEDDED" default:"false"` + NatsEmbeddedStoreDir string `envconfig:"NATS_EMBEDDED_STORE_DIR" default:"/app/nats"` + NatsURI string `envconfig:"NATS_URI" default:"nats://localhost:4222"` + NatsSecure bool `envconfig:"NATS_SECURE" default:"false"` + NatsSkipVerify bool `envconfig:"NATS_SKIP_VERIFY" default:"false"` + NatsCertFile string `envconfig:"NATS_CERT_FILE" default:""` + NatsKeyFile string `envconfig:"NATS_KEY_FILE" default:""` + NatsCAFile string `envconfig:"NATS_CA_FILE" default:""` + NatsConnectTimeout time.Duration `envconfig:"NATS_CONNECT_TIMEOUT" default:"5s"` + JobServiceAccountName string `envconfig:"JOB_SERVICE_ACCOUNT_NAME" default:""` + JobTemplateFile string `envconfig:"JOB_TEMPLATE_FILE" default:""` + DisableTestTriggers bool `envconfig:"DISABLE_TEST_TRIGGERS" default:"false"` + TestkubeDefaultExecutors string `envconfig:"TESTKUBE_DEFAULT_EXECUTORS" default:""` + TestkubeEnabledExecutors string `envconfig:"TESTKUBE_ENABLED_EXECUTORS" default:""` + TestkubeTemplateJob string `envconfig:"TESTKUBE_TEMPLATE_JOB" default:""` + TestkubeContainerTemplateJob string `envconfig:"TESTKUBE_CONTAINER_TEMPLATE_JOB" default:""` + TestkubeContainerTemplateScraper string `envconfig:"TESTKUBE_CONTAINER_TEMPLATE_SCRAPER" default:""` + TestkubeContainerTemplatePVC string `envconfig:"TESTKUBE_CONTAINER_TEMPLATE_PVC" default:""` + TestkubeTemplateSlavePod string `envconfig:"TESTKUBE_TEMPLATE_SLAVE_POD" default:""` + TestkubeConfigDir string `envconfig:"TESTKUBE_CONFIG_DIR" default:"config"` + TestkubeAnalyticsEnabled bool `envconfig:"TESTKUBE_ANALYTICS_ENABLED" default:"false"` + TestkubeReadonlyExecutors bool `envconfig:"TESTKUBE_READONLY_EXECUTORS" default:"false"` + TestkubeNamespace string `envconfig:"TESTKUBE_NAMESPACE" default:"testkube"` + TestkubeProAPIKey string `envconfig:"TESTKUBE_PRO_API_KEY" default:""` + TestkubeProURL string `envconfig:"TESTKUBE_PRO_URL" default:""` + TestkubeProTLSInsecure bool `envconfig:"TESTKUBE_PRO_TLS_INSECURE" default:"false"` + TestkubeProWorkerCount int `envconfig:"TESTKUBE_PRO_WORKER_COUNT" default:"50"` + TestkubeProLogStreamWorkerCount int `envconfig:"TESTKUBE_PRO_LOG_STREAM_WORKER_COUNT" default:"25"` + TestkubeProWorkflowNotificationsWorkerCount int `envconfig:"TESTKUBE_PRO_WORKFLOW_NOTIFICATIONS_STREAM_WORKER_COUNT" default:"25"` + TestkubeProWorkflowServiceNotificationsWorkerCount int `envconfig:"TESTKUBE_PRO_WORKFLOW_SERVICE_NOTIFICATIONS_STREAM_WORKER_COUNT" default:"25"` + TestkubeProSkipVerify bool `envconfig:"TESTKUBE_PRO_SKIP_VERIFY" default:"false"` + TestkubeProEnvID string `envconfig:"TESTKUBE_PRO_ENV_ID" default:""` + TestkubeProOrgID string `envconfig:"TESTKUBE_PRO_ORG_ID" default:""` + TestkubeProMigrate string `envconfig:"TESTKUBE_PRO_MIGRATE" default:"false"` + TestkubeProConnectionTimeout int `envconfig:"TESTKUBE_PRO_CONNECTION_TIMEOUT" default:"10"` + TestkubeProCertFile string `envconfig:"TESTKUBE_PRO_CERT_FILE" default:""` + TestkubeProKeyFile string `envconfig:"TESTKUBE_PRO_KEY_FILE" default:""` + TestkubeProTLSSecret string `envconfig:"TESTKUBE_PRO_TLS_SECRET" default:""` + TestkubeProRunnerCustomCASecret string `envconfig:"TESTKUBE_PRO_RUNNER_CUSTOM_CA_SECRET" default:""` + TestkubeWatcherNamespaces string `envconfig:"TESTKUBE_WATCHER_NAMESPACES" default:""` + TestkubeRegistry string `envconfig:"TESTKUBE_REGISTRY" default:""` + TestkubePodStartTimeout time.Duration `envconfig:"TESTKUBE_POD_START_TIMEOUT" default:"30m"` // TestkubeImageCredentialsCacheTTL is the duration for which the image pull credentials should be cached provided as a Go duration string. // If set to 0, the cache is disabled. TestkubeImageCredentialsCacheTTL time.Duration `envconfig:"TESTKUBE_IMAGE_CREDENTIALS_CACHE_TTL" default:"30m"` diff --git a/internal/config/procontext.go b/internal/config/procontext.go index aa3b090be8..4bfcb41acf 100644 --- a/internal/config/procontext.go +++ b/internal/config/procontext.go @@ -1,16 +1,17 @@ package config type ProContext struct { - APIKey string - URL string - TLSInsecure bool - WorkerCount int - LogStreamWorkerCount int - WorkflowNotificationsWorkerCount int - SkipVerify bool - EnvID string - OrgID string - Migrate string - ConnectionTimeout int - DashboardURI string + APIKey string + URL string + TLSInsecure bool + WorkerCount int + LogStreamWorkerCount int + WorkflowNotificationsWorkerCount int + WorkflowServiceNotificationsWorkerCount int + SkipVerify bool + EnvID string + OrgID string + Migrate string + ConnectionTimeout int + DashboardURI string } diff --git a/pkg/agent/agent.go b/pkg/agent/agent.go index b612770d26..e11fb03983 100644 --- a/pkg/agent/agent.go +++ b/pkg/agent/agent.go @@ -55,6 +55,11 @@ type Agent struct { testWorkflowNotificationsResponseBuffer chan *cloud.TestWorkflowNotificationsResponse testWorkflowNotificationsFunc func(ctx context.Context, executionID string) (<-chan testkube.TestWorkflowExecutionNotification, error) + testWorkflowServiceNotificationsWorkerCount int + testWorkflowServiceNotificationsRequestBuffer chan *cloud.TestWorkflowServiceNotificationsRequest + testWorkflowServiceNotificationsResponseBuffer chan *cloud.TestWorkflowServiceNotificationsResponse + testWorkflowServiceNotificationsFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) + events chan testkube.Event sendTimeout time.Duration receiveTimeout time.Duration @@ -73,6 +78,7 @@ func NewAgent(logger *zap.SugaredLogger, client cloud.TestKubeCloudAPIClient, logStreamFunc func(ctx context.Context, executionID string) (chan output.Output, error), workflowNotificationsFunc func(ctx context.Context, executionID string) (<-chan testkube.TestWorkflowExecutionNotification, error), + workflowServiceNotificationsFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error), clusterID string, clusterName string, features featureflags.FeatureFlags, @@ -99,11 +105,16 @@ func NewAgent(logger *zap.SugaredLogger, testWorkflowNotificationsRequestBuffer: make(chan *cloud.TestWorkflowNotificationsRequest, bufferSizePerWorker*proContext.WorkflowNotificationsWorkerCount), testWorkflowNotificationsResponseBuffer: make(chan *cloud.TestWorkflowNotificationsResponse, bufferSizePerWorker*proContext.WorkflowNotificationsWorkerCount), testWorkflowNotificationsFunc: workflowNotificationsFunc, - clusterID: clusterID, - clusterName: clusterName, - features: features, - proContext: proContext, - dockerImageVersion: dockerImageVersion, + testWorkflowServiceNotificationsWorkerCount: proContext.WorkflowServiceNotificationsWorkerCount, + testWorkflowServiceNotificationsRequestBuffer: make(chan *cloud.TestWorkflowServiceNotificationsRequest, bufferSizePerWorker*proContext.WorkflowServiceNotificationsWorkerCount), + testWorkflowServiceNotificationsResponseBuffer: make(chan *cloud.TestWorkflowServiceNotificationsResponse, bufferSizePerWorker*proContext.WorkflowServiceNotificationsWorkerCount), + testWorkflowServiceNotificationsFunc: workflowServiceNotificationsFunc, + + clusterID: clusterID, + clusterName: clusterName, + features: features, + proContext: proContext, + dockerImageVersion: dockerImageVersion, }, nil } @@ -151,6 +162,13 @@ func (ag *Agent) run(ctx context.Context) (err error) { return ag.runTestWorkflowNotificationsWorker(groupCtx, ag.testWorkflowNotificationsWorkerCount) }) + g.Go(func() error { + return ag.runTestWorkflowServiceNotificationsLoop(groupCtx) + }) + g.Go(func() error { + return ag.runTestWorkflowServiceNotificationsWorker(groupCtx, ag.testWorkflowServiceNotificationsWorkerCount) + }) + err = g.Wait() return err diff --git a/pkg/agent/agent_test.go b/pkg/agent/agent_test.go index fb6c6d1741..47973e09ac 100644 --- a/pkg/agent/agent_test.go +++ b/pkg/agent/agent_test.go @@ -59,10 +59,11 @@ func TestCommandExecution(t *testing.T) { var logStreamFunc func(ctx context.Context, executionID string) (chan output.Output, error) var workflowNotificationsStreamFunc func(ctx context.Context, executionID string) (<-chan testkube.TestWorkflowExecutionNotification, error) + var workflowServiceNotificationsStreamFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) logger, _ := zap.NewDevelopment() proContext := config.ProContext{APIKey: "api-key", WorkerCount: 5, LogStreamWorkerCount: 5, WorkflowNotificationsWorkerCount: 5} - agent, err := agent.NewAgent(logger.Sugar(), m, grpcClient, logStreamFunc, workflowNotificationsStreamFunc, "", "", featureflags.FeatureFlags{}, &proContext, "") + agent, err := agent.NewAgent(logger.Sugar(), m, grpcClient, logStreamFunc, workflowNotificationsStreamFunc, workflowServiceNotificationsStreamFunc, "", "", featureflags.FeatureFlags{}, &proContext, "") if err != nil { t.Fatal(err) } @@ -97,6 +98,12 @@ func (cs *CloudServer) GetTestWorkflowNotificationsStream(srv cloud.TestKubeClou return nil } +func (cs *CloudServer) GetTestWorkflowServiceNotificationsStream(srv cloud.TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamServer) error { + <-cs.ctx.Done() + + return nil +} + func (cs *CloudServer) ExecuteAsync(srv cloud.TestKubeCloudAPI_ExecuteAsyncServer) error { md, ok := metadata.FromIncomingContext(srv.Context()) if !ok { diff --git a/pkg/agent/events_test.go b/pkg/agent/events_test.go index 663e06ac19..1f52ea26f4 100644 --- a/pkg/agent/events_test.go +++ b/pkg/agent/events_test.go @@ -56,9 +56,10 @@ func TestEventLoop(t *testing.T) { var logStreamFunc func(ctx context.Context, executionID string) (chan output.Output, error) var workflowNotificationsStreamFunc func(ctx context.Context, executionID string) (<-chan testkube.TestWorkflowExecutionNotification, error) + var workflowServiceNotificationsStreamFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) proContext := config.ProContext{APIKey: "api-key", WorkerCount: 5, LogStreamWorkerCount: 5, WorkflowNotificationsWorkerCount: 5} - agent, err := agent.NewAgent(logger.Sugar(), nil, grpcClient, logStreamFunc, workflowNotificationsStreamFunc, "", "", featureflags.FeatureFlags{}, &proContext, "") + agent, err := agent.NewAgent(logger.Sugar(), nil, grpcClient, logStreamFunc, workflowNotificationsStreamFunc, workflowServiceNotificationsStreamFunc, "", "", featureflags.FeatureFlags{}, &proContext, "") assert.NoError(t, err) go func() { l, err := agent.Load() @@ -110,6 +111,12 @@ func (cws *CloudEventServer) GetTestWorkflowNotificationsStream(srv cloud.TestKu return nil } +func (cws *CloudEventServer) GetTestWorkflowServiceNotificationsStream(srv cloud.TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamServer) error { + <-cws.ctx.Done() + + return nil +} + func (cws *CloudEventServer) Send(srv cloud.TestKubeCloudAPI_SendServer) error { md, ok := metadata.FromIncomingContext(srv.Context()) if !ok { diff --git a/pkg/agent/logs_test.go b/pkg/agent/logs_test.go index 0491467415..59eaecf6f0 100644 --- a/pkg/agent/logs_test.go +++ b/pkg/agent/logs_test.go @@ -66,10 +66,11 @@ func TestLogStream(t *testing.T) { return ch, nil } var workflowNotificationsStreamFunc func(ctx context.Context, executionID string) (<-chan testkube.TestWorkflowExecutionNotification, error) + var workflowServiceNotificationsStreamFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) logger, _ := zap.NewDevelopment() proContext := config.ProContext{APIKey: "api-key", WorkerCount: 5, LogStreamWorkerCount: 5, WorkflowNotificationsWorkerCount: 5} - agent, err := agent.NewAgent(logger.Sugar(), m, grpcClient, logStreamFunc, workflowNotificationsStreamFunc, "", "", featureflags.FeatureFlags{}, &proContext, "") + agent, err := agent.NewAgent(logger.Sugar(), m, grpcClient, logStreamFunc, workflowNotificationsStreamFunc, workflowServiceNotificationsStreamFunc, "", "", featureflags.FeatureFlags{}, &proContext, "") if err != nil { t.Fatal(err) } @@ -102,6 +103,11 @@ func (cs *CloudLogsServer) GetTestWorkflowNotificationsStream(srv cloud.TestKube return nil } +func (cs *CloudLogsServer) GetTestWorkflowServiceNotificationsStream(srv cloud.TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamServer) error { + <-cs.ctx.Done() + return nil +} + func (cs *CloudLogsServer) GetLogsStream(srv cloud.TestKubeCloudAPI_GetLogsStreamServer) error { md, ok := metadata.FromIncomingContext(srv.Context()) if !ok { diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index 2001fa9deb..969f443c6c 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -74,6 +74,51 @@ func (ag *Agent) runTestWorkflowNotificationsLoop(ctx context.Context) error { return err } +func (ag *Agent) runTestWorkflowServiceNotificationsLoop(ctx context.Context) error { + ctx = agentclient.AddAPIKeyMeta(ctx, ag.apiKey) + + ag.logger.Infow("initiating workflow service notifications streaming connection with Cloud API") + // creates a new Stream from the client side. ctx is used for the lifetime of the stream. + opts := []grpc.CallOption{grpc.UseCompressor(gzip.Name), grpc.MaxCallRecvMsgSize(math.MaxInt32)} + stream, err := ag.client.GetTestWorkflowServiceNotificationsStream(ctx, opts...) + if err != nil { + ag.logger.Errorf("failed to execute: %w", err) + return errors.Wrap(err, "failed to setup stream") + } + + // GRPC stream have special requirements for concurrency on SendMsg, and RecvMsg calls. + // Please check https://github.com/grpc/grpc-go/blob/master/Documentation/concurrency.md + g, groupCtx := errgroup.WithContext(ctx) + g.Go(func() error { + for { + cmd, err := ag.receiveTestWorkflowServiceNotificationsRequest(groupCtx, stream) + if err != nil { + return err + } + + ag.testWorkflowServiceNotificationsRequestBuffer <- cmd + } + }) + + g.Go(func() error { + for { + select { + case resp := <-ag.testWorkflowServiceNotificationsResponseBuffer: + err := ag.sendTestWorkflowServiceNotificationsResponse(groupCtx, stream, resp) + if err != nil { + return err + } + case <-groupCtx.Done(): + return groupCtx.Err() + } + } + }) + + err = g.Wait() + + return err +} + func (ag *Agent) runTestWorkflowNotificationsWorker(ctx context.Context, numWorkers int) error { g, groupCtx := errgroup.WithContext(ctx) for i := 0; i < numWorkers; i++ { @@ -102,6 +147,34 @@ func (ag *Agent) runTestWorkflowNotificationsWorker(ctx context.Context, numWork return g.Wait() } +func (ag *Agent) runTestWorkflowServiceNotificationsWorker(ctx context.Context, numWorkers int) error { + g, groupCtx := errgroup.WithContext(ctx) + for i := 0; i < numWorkers; i++ { + g.Go(func() error { + for { + select { + case req := <-ag.testWorkflowServiceNotificationsRequestBuffer: + if req.RequestType == cloud.TestWorkflowNotificationsRequestType_WORKFLOW_STREAM_HEALTH_CHECK { + ag.testWorkflowServiceNotificationsResponseBuffer <- &cloud.TestWorkflowServiceNotificationsResponse{ + StreamId: req.StreamId, + SeqNo: 0, + } + break + } + + err := ag.executeWorkflowServiceNotificationsRequest(groupCtx, req) + if err != nil { + ag.logger.Errorf("error executing workflow service notifications request: %s", err.Error()) + } + case <-groupCtx.Done(): + return groupCtx.Err() + } + } + }) + } + return g.Wait() +} + func (ag *Agent) executeWorkflowNotificationsRequest(ctx context.Context, req *cloud.TestWorkflowNotificationsRequest) error { notificationsCh, err := ag.testWorkflowNotificationsFunc(ctx, req.ExecutionId) for i := 0; i < testWorkflowNotificationsRetryCount; i++ { @@ -162,6 +235,66 @@ func (ag *Agent) executeWorkflowNotificationsRequest(ctx context.Context, req *c } } +func (ag *Agent) executeWorkflowServiceNotificationsRequest(ctx context.Context, req *cloud.TestWorkflowServiceNotificationsRequest) error { + notificationsCh, err := ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.ServiceName, int(req.ServiceIndex)) + for i := 0; i < testWorkflowNotificationsRetryCount; i++ { + if err != nil { + // We have a race condition here + // Cloud sometimes slow to insert execution or test + // while WorkflowNotifications request from websockets comes in faster + // so we retry up to testWorkflowNotificationsRetryCount times. + time.Sleep(100 * time.Millisecond) + notificationsCh, err = ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.ServiceName, int(req.ServiceIndex)) + } + } + if err != nil { + message := fmt.Sprintf("cannot get pod logs: %s", err.Error()) + ag.testWorkflowServiceNotificationsResponseBuffer <- &cloud.TestWorkflowServiceNotificationsResponse{ + StreamId: req.StreamId, + SeqNo: 0, + Type: cloud.TestWorkflowNotificationType_WORKFLOW_STREAM_ERROR, + Message: fmt.Sprintf("%s %s", time.Now().Format(controller.KubernetesLogTimeFormat), message), + } + return nil + } + + for { + var i uint32 + select { + case n, ok := <-notificationsCh: + if !ok { + return nil + } + t := getTestWorkflowNotificationType(n) + msg := &cloud.TestWorkflowServiceNotificationsResponse{ + StreamId: req.StreamId, + SeqNo: i, + Timestamp: n.Ts.Format(time.RFC3339Nano), + Ref: n.Ref, + Type: t, + } + if n.Result != nil { + m, _ := json.Marshal(n.Result) + msg.Message = string(m) + } else if n.Output != nil { + m, _ := json.Marshal(n.Output) + msg.Message = string(m) + } else { + msg.Message = n.Log + } + i++ + + select { + case ag.testWorkflowServiceNotificationsResponseBuffer <- msg: + case <-ctx.Done(): + return ctx.Err() + } + case <-ctx.Done(): + return ctx.Err() + } + } +} + func (ag *Agent) receiveTestWorkflowNotificationsRequest(ctx context.Context, stream cloud.TestKubeCloudAPI_GetTestWorkflowNotificationsStreamClient) (*cloud.TestWorkflowNotificationsRequest, error) { respChan := make(chan testWorkflowNotificationsRequest, 1) go func() { @@ -191,6 +324,35 @@ type testWorkflowNotificationsRequest struct { err error } +func (ag *Agent) receiveTestWorkflowServiceNotificationsRequest(ctx context.Context, stream cloud.TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamClient) (*cloud.TestWorkflowServiceNotificationsRequest, error) { + respChan := make(chan testWorkflowServiceNotificationsRequest, 1) + go func() { + cmd, err := stream.Recv() + respChan <- testWorkflowServiceNotificationsRequest{resp: cmd, err: err} + }() + + var cmd *cloud.TestWorkflowServiceNotificationsRequest + select { + case resp := <-respChan: + cmd = resp.resp + err := resp.err + + if err != nil { + ag.logger.Errorf("agent stream receive: %v", err) + return nil, err + } + case <-ctx.Done(): + return nil, ctx.Err() + } + + return cmd, nil +} + +type testWorkflowServiceNotificationsRequest struct { + resp *cloud.TestWorkflowServiceNotificationsRequest + err error +} + func (ag *Agent) sendTestWorkflowNotificationsResponse(ctx context.Context, stream cloud.TestKubeCloudAPI_GetTestWorkflowNotificationsStreamClient, resp *cloud.TestWorkflowNotificationsResponse) error { errChan := make(chan error, 1) go func() { @@ -215,3 +377,28 @@ func (ag *Agent) sendTestWorkflowNotificationsResponse(ctx context.Context, stre return errors.New("send response too slow") } } + +func (ag *Agent) sendTestWorkflowServiceNotificationsResponse(ctx context.Context, stream cloud.TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamClient, resp *cloud.TestWorkflowServiceNotificationsResponse) error { + errChan := make(chan error, 1) + go func() { + errChan <- stream.Send(resp) + close(errChan) + }() + + t := time.NewTimer(ag.sendTimeout) + select { + case err := <-errChan: + if !t.Stop() { + <-t.C + } + return err + case <-ctx.Done(): + if !t.Stop() { + <-t.C + } + + return ctx.Err() + case <-t.C: + return errors.New("send response too slow") + } +} From 9d85b355ca68f8dca2dbac6a0f2c4346c1624bf9 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 28 Nov 2024 17:01:49 +0300 Subject: [PATCH 15/40] fix: change timeeout Signed-off-by: Vladislav Sukhin --- pkg/agent/testworkflows.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index 969f443c6c..26d16f7947 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -243,12 +243,12 @@ func (ag *Agent) executeWorkflowServiceNotificationsRequest(ctx context.Context, // Cloud sometimes slow to insert execution or test // while WorkflowNotifications request from websockets comes in faster // so we retry up to testWorkflowNotificationsRetryCount times. - time.Sleep(100 * time.Millisecond) + time.Sleep(time.Second) notificationsCh, err = ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.ServiceName, int(req.ServiceIndex)) } } if err != nil { - message := fmt.Sprintf("cannot get pod logs: %s", err.Error()) + message := fmt.Sprintf("cannot get service pod logs: %s", err.Error()) ag.testWorkflowServiceNotificationsResponseBuffer <- &cloud.TestWorkflowServiceNotificationsResponse{ StreamId: req.StreamId, SeqNo: 0, From 57db7a02dd8c0740b5ec3dbd2bad7f54dc07b8ec Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 28 Nov 2024 18:12:03 +0300 Subject: [PATCH 16/40] fix: waiting for service pod Signed-off-by: Vladislav Sukhin --- cmd/api-server/main.go | 7 ++++++- pkg/agent/testworkflows.go | 29 +++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/cmd/api-server/main.go b/cmd/api-server/main.go index 8a349b80f5..a21e36a8ed 100644 --- a/cmd/api-server/main.go +++ b/cmd/api-server/main.go @@ -328,8 +328,13 @@ func main() { getTestWorkflowServiceNotificationsStream := func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) { execution, err := testWorkflowResultsRepository.Get(ctx, executionID) if err != nil { - return nil, err + return nil, errors.Join(err, agent.ErrGetTestWorkflowExecution) + } + + if execution.Result != nil && execution.Result.IsFinished() { + return nil, agent.ErrFinishedTestWorkflowExecution } + notifications := executionWorker.Notifications(ctx, fmt.Sprintf("%s-%s-%d", execution.Id, serviceName, serviceIndex), executionworkertypes.NotificationsOptions{ Hints: executionworkertypes.Hints{ Namespace: execution.Namespace, diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index 26d16f7947..697b801722 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -20,6 +20,11 @@ import ( const testWorkflowNotificationsRetryCount = 10 +var ( + ErrGetTestWorkflowExecution = errors.New("can't get test workflow execution") + ErrFinishedTestWorkflowExecution = errors.New("test workflow execution is finished") +) + func getTestWorkflowNotificationType(n testkube.TestWorkflowExecutionNotification) cloud.TestWorkflowNotificationType { if n.Result != nil { return cloud.TestWorkflowNotificationType_WORKFLOW_STREAM_RESULT @@ -236,17 +241,29 @@ func (ag *Agent) executeWorkflowNotificationsRequest(ctx context.Context, req *c } func (ag *Agent) executeWorkflowServiceNotificationsRequest(ctx context.Context, req *cloud.TestWorkflowServiceNotificationsRequest) error { - notificationsCh, err := ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.ServiceName, int(req.ServiceIndex)) - for i := 0; i < testWorkflowNotificationsRetryCount; i++ { + var ( + notificationsCh <-chan testkube.TestWorkflowExecutionNotification + err error + ) + + for { + notificationsCh, err = ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.ServiceName, int(req.ServiceIndex)) + if errors.Is(err, ErrGetTestWorkflowExecution) || errors.Is(ErrFinishedTestWorkflowExecution) { + break + } + if err != nil { // We have a race condition here - // Cloud sometimes slow to insert execution or test + // Cloud sometimes slow to start service // while WorkflowNotifications request from websockets comes in faster - // so we retry up to testWorkflowNotificationsRetryCount times. - time.Sleep(time.Second) - notificationsCh, err = ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.ServiceName, int(req.ServiceIndex)) + // so we retry up to wait till service pod is uo or execution is finished. + time.Sleep(100 * time.Millisecond) + continue } + + break } + if err != nil { message := fmt.Sprintf("cannot get service pod logs: %s", err.Error()) ag.testWorkflowServiceNotificationsResponseBuffer <- &cloud.TestWorkflowServiceNotificationsResponse{ From cccfcb748b00d5573fe3559058ba94d553157965 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 28 Nov 2024 18:19:10 +0300 Subject: [PATCH 17/40] fix: typo Signed-off-by: Vladislav Sukhin --- pkg/agent/testworkflows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index 697b801722..65fec85ca1 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -248,7 +248,7 @@ func (ag *Agent) executeWorkflowServiceNotificationsRequest(ctx context.Context, for { notificationsCh, err = ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.ServiceName, int(req.ServiceIndex)) - if errors.Is(err, ErrGetTestWorkflowExecution) || errors.Is(ErrFinishedTestWorkflowExecution) { + if errors.Is(err, ErrGetTestWorkflowExecution) || errors.Is(err, ErrFinishedTestWorkflowExecution) { break } From c4658c55dbd185d89f21063ac05784b4581932aa Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 28 Nov 2024 18:35:25 +0300 Subject: [PATCH 18/40] fix: waiting for service pod Signed-off-by: Vladislav Sukhin --- cmd/api-server/main.go | 4 ++-- pkg/agent/testworkflows.go | 12 ++---------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/cmd/api-server/main.go b/cmd/api-server/main.go index a21e36a8ed..f110d0f1d9 100644 --- a/cmd/api-server/main.go +++ b/cmd/api-server/main.go @@ -328,11 +328,11 @@ func main() { getTestWorkflowServiceNotificationsStream := func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) { execution, err := testWorkflowResultsRepository.Get(ctx, executionID) if err != nil { - return nil, errors.Join(err, agent.ErrGetTestWorkflowExecution) + return nil, err } if execution.Result != nil && execution.Result.IsFinished() { - return nil, agent.ErrFinishedTestWorkflowExecution + return nil, errors.New("test workflow execution is finished") } notifications := executionWorker.Notifications(ctx, fmt.Sprintf("%s-%s-%d", execution.Id, serviceName, serviceIndex), executionworkertypes.NotificationsOptions{ diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index 65fec85ca1..8924284b50 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -16,15 +16,11 @@ import ( "github.com/kubeshop/testkube/pkg/api/v1/testkube" "github.com/kubeshop/testkube/pkg/cloud" "github.com/kubeshop/testkube/pkg/testworkflows/executionworker/controller" + "github.com/kubeshop/testkube/pkg/testworkflows/executionworker/registry" ) const testWorkflowNotificationsRetryCount = 10 -var ( - ErrGetTestWorkflowExecution = errors.New("can't get test workflow execution") - ErrFinishedTestWorkflowExecution = errors.New("test workflow execution is finished") -) - func getTestWorkflowNotificationType(n testkube.TestWorkflowExecutionNotification) cloud.TestWorkflowNotificationType { if n.Result != nil { return cloud.TestWorkflowNotificationType_WORKFLOW_STREAM_RESULT @@ -248,11 +244,7 @@ func (ag *Agent) executeWorkflowServiceNotificationsRequest(ctx context.Context, for { notificationsCh, err = ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.ServiceName, int(req.ServiceIndex)) - if errors.Is(err, ErrGetTestWorkflowExecution) || errors.Is(err, ErrFinishedTestWorkflowExecution) { - break - } - - if err != nil { + if errors.Is(err, registry.ErrResourceNotFound) { // We have a race condition here // Cloud sometimes slow to start service // while WorkflowNotifications request from websockets comes in faster From 37685502d6d762c1b3746f4a944fe33cc3870ab4 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Thu, 28 Nov 2024 21:26:34 +0300 Subject: [PATCH 19/40] fix: add service name check Signed-off-by: Vladislav Sukhin --- .../commands/testworkflows/run.go | 4 ++-- internal/app/api/v1/testworkflowexecutions.go | 6 +++--- .../testkube/model_test_workflow_extended.go | 19 +++++++++++++++++ .../model_test_workflow_step_extended.go | 21 +++++++++++++++++++ 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index cbe7061a6b..c4deb975c5 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -198,8 +198,8 @@ func uiWatch(execution testkube.TestWorkflowExecution, serviceName string, servi result, err = watchTestWorkflowLogs(execution.Id, execution.Signature, client) } else { found := false - if execution.Workflow != nil && execution.Workflow.Spec != nil { - _, found = execution.Workflow.Spec.Services[serviceName] + if execution.Workflow != nil { + found = execution.Workflow.HasService(serviceName) } if !found { diff --git a/internal/app/api/v1/testworkflowexecutions.go b/internal/app/api/v1/testworkflowexecutions.go index a806588161..3670613fb7 100644 --- a/internal/app/api/v1/testworkflowexecutions.go +++ b/internal/app/api/v1/testworkflowexecutions.go @@ -104,8 +104,8 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionServiceNotificationsHandler() f } found := false - if execution.Workflow != nil && execution.Workflow.Spec != nil { - _, found = execution.Workflow.Spec.Services[serviceName] + if execution.Workflow != nil { + found = execution.Workflow.HasService(serviceName) } if !found { @@ -189,7 +189,7 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionServiceNotificationsWebSocketHa found := false if execution.Workflow != nil && execution.Workflow.Spec != nil { - _, found = execution.Workflow.Spec.Services[serviceName] + found = execution.Workflow.HasService(serviceName) } if !found { diff --git a/pkg/api/v1/testkube/model_test_workflow_extended.go b/pkg/api/v1/testkube/model_test_workflow_extended.go index 2150f76030..846218c83e 100644 --- a/pkg/api/v1/testkube/model_test_workflow_extended.go +++ b/pkg/api/v1/testkube/model_test_workflow_extended.go @@ -96,3 +96,22 @@ func (w TestWorkflow) GetLabels() map[string]string { func (w TestWorkflow) GetAnnotations() map[string]string { return w.Annotations } + +func (w TestWorkflow) HasService(name string) bool { + if w.Spec == nil { + return false + } + + steps := append(w.Spec.Setup, append(w.Spec.Steps, w.Spec.After...)...) + for _, step := range steps { + if step.HasService(name) { + return true + } + } + + if _, ok := w.Spec.Services[name]; ok { + return true + } + + return false +} diff --git a/pkg/api/v1/testkube/model_test_workflow_step_extended.go b/pkg/api/v1/testkube/model_test_workflow_step_extended.go index b8ddb9db83..b4e87b99f1 100644 --- a/pkg/api/v1/testkube/model_test_workflow_step_extended.go +++ b/pkg/api/v1/testkube/model_test_workflow_step_extended.go @@ -65,3 +65,24 @@ func (w *TestWorkflowStep) GetTemplateRefs() []TestWorkflowTemplateRef { return templateRefs } + +func (w *TestWorkflowStep) HasService(name string) bool { + steps := append(w.Setup, w.Steps...) + if w.Parallel != nil { + steps = append(steps, w.Parallel.Setup...) + steps = append(steps, w.Parallel.Steps...) + steps = append(steps, w.Parallel.After...) + } + + for _, step := range steps { + if step.HasService(name) { + return true + } + } + + if _, ok := w.Services[name]; ok { + return true + } + + return false +} From c2fd448025a2b9e99d0b02565c774934b32895fc Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 29 Nov 2024 15:04:16 +0300 Subject: [PATCH 20/40] fix: adjust help Signed-off-by: Vladislav Sukhin --- cmd/kubectl-testkube/commands/testworkflows/run.go | 2 +- cmd/kubectl-testkube/commands/testworkflows/watch.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index c4deb975c5..dcbe35b261 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -185,7 +185,7 @@ func NewRunTestWorkflowCmd() *cobra.Command { cmd.Flags().StringToStringVarP(&tags, "tag", "", map[string]string{}, "execution tags in a form of name1=val1 passed to executor") cmd.Flags().StringSliceVarP(&selectors, "label", "l", nil, "label key value pair: --label key1=value1 or label expression") cmd.Flags().StringVar(&serviceName, "service-name", "", "test workflow service name") - cmd.Flags().IntVar(&serviceIndex, "service-index", 0, "test workflow service index") + cmd.Flags().IntVar(&serviceIndex, "service-index", 0, "test workflow service index starting from 0") return cmd } diff --git a/cmd/kubectl-testkube/commands/testworkflows/watch.go b/cmd/kubectl-testkube/commands/testworkflows/watch.go index 3992ec3337..35c6e918ec 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/watch.go +++ b/cmd/kubectl-testkube/commands/testworkflows/watch.go @@ -49,7 +49,7 @@ func NewWatchTestWorkflowExecutionCmd() *cobra.Command { } cmd.Flags().StringVar(&serviceName, "service-name", "", "test workflow service name") - cmd.Flags().IntVar(&serviceIndex, "service-index", 0, "test workflow service index") + cmd.Flags().IntVar(&serviceIndex, "service-index", 0, "test workflow service index starting from 0") return cmd } From b46bb41d776202a87ac40abab98a56eddf1cbffa Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 29 Nov 2024 15:23:28 +0300 Subject: [PATCH 21/40] fix: add method to parallel step Signed-off-by: Vladislav Sukhin --- .../testkube/model_test_workflow_step_extended.go | 8 +++----- .../model_test_workflow_step_parallel_extended.go | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/pkg/api/v1/testkube/model_test_workflow_step_extended.go b/pkg/api/v1/testkube/model_test_workflow_step_extended.go index b4e87b99f1..4dd28c868f 100644 --- a/pkg/api/v1/testkube/model_test_workflow_step_extended.go +++ b/pkg/api/v1/testkube/model_test_workflow_step_extended.go @@ -67,13 +67,11 @@ func (w *TestWorkflowStep) GetTemplateRefs() []TestWorkflowTemplateRef { } func (w *TestWorkflowStep) HasService(name string) bool { - steps := append(w.Setup, w.Steps...) - if w.Parallel != nil { - steps = append(steps, w.Parallel.Setup...) - steps = append(steps, w.Parallel.Steps...) - steps = append(steps, w.Parallel.After...) + if w.Parallel != nil && w.Parallel.HasService(name) { + return true } + steps := append(w.Setup, w.Steps...) for _, step := range steps { if step.HasService(name) { return true diff --git a/pkg/api/v1/testkube/model_test_workflow_step_parallel_extended.go b/pkg/api/v1/testkube/model_test_workflow_step_parallel_extended.go index 7ad342975e..2a9ccadf86 100644 --- a/pkg/api/v1/testkube/model_test_workflow_step_parallel_extended.go +++ b/pkg/api/v1/testkube/model_test_workflow_step_parallel_extended.go @@ -29,3 +29,18 @@ func (w *TestWorkflowStepParallel) GetTemplateRefs() []TestWorkflowTemplateRef { return templateRefs } + +func (w *TestWorkflowStepParallel) HasService(name string) bool { + steps := append(w.Setup, append(w.Steps, w.After...)...) + for _, step := range steps { + if step.HasService(name) { + return true + } + } + + if _, ok := w.Services[name]; ok { + return true + } + + return false +} From 59bdce302d569b2416ea43340966e6ad501d38f0 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 29 Nov 2024 16:07:56 +0300 Subject: [PATCH 22/40] fix: use retry library Signed-off-by: Vladislav Sukhin --- pkg/agent/testworkflows.go | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index 8924284b50..5e02576384 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -7,6 +7,7 @@ import ( "math" "time" + "github.com/avast/retry-go/v4" "github.com/pkg/errors" "golang.org/x/sync/errgroup" "google.golang.org/grpc" @@ -21,6 +22,11 @@ import ( const testWorkflowNotificationsRetryCount = 10 +var ( + retryDelay = 100 * time.Millisecond + waitTimeout = 24 * time.Hour +) + func getTestWorkflowNotificationType(n testkube.TestWorkflowExecutionNotification) cloud.TestWorkflowNotificationType { if n.Result != nil { return cloud.TestWorkflowNotificationType_WORKFLOW_STREAM_RESULT @@ -184,7 +190,7 @@ func (ag *Agent) executeWorkflowNotificationsRequest(ctx context.Context, req *c // Cloud sometimes slow to insert execution or test // while WorkflowNotifications request from websockets comes in faster // so we retry up to testWorkflowNotificationsRetryCount times. - time.Sleep(100 * time.Millisecond) + time.Sleep(retryDelay) notificationsCh, err = ag.testWorkflowNotificationsFunc(ctx, req.ExecutionId) } } @@ -237,24 +243,24 @@ func (ag *Agent) executeWorkflowNotificationsRequest(ctx context.Context, req *c } func (ag *Agent) executeWorkflowServiceNotificationsRequest(ctx context.Context, req *cloud.TestWorkflowServiceNotificationsRequest) error { - var ( - notificationsCh <-chan testkube.TestWorkflowExecutionNotification - err error - ) + timeoutCtx, cancel := context.WithTimeout(ctx, waitTimeout) + defer cancel() - for { - notificationsCh, err = ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.ServiceName, int(req.ServiceIndex)) - if errors.Is(err, registry.ErrResourceNotFound) { + notificationsCh, err := retry.DoWithData( + func() (<-chan testkube.TestWorkflowExecutionNotification, error) { // We have a race condition here // Cloud sometimes slow to start service // while WorkflowNotifications request from websockets comes in faster // so we retry up to wait till service pod is uo or execution is finished. - time.Sleep(100 * time.Millisecond) - continue - } - - break - } + return ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.ServiceName, int(req.ServiceIndex)) + }, + retry.DelayType(retry.FixedDelay), + retry.Delay(retryDelay), + retry.Context(timeoutCtx), + retry.RetryIf(func(err error) bool { + return errors.Is(err, registry.ErrResourceNotFound) + }), + ) if err != nil { message := fmt.Sprintf("cannot get service pod logs: %s", err.Error()) From 42249308ef5f267abd20a8b4bbb25ddaaeab2688 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 29 Nov 2024 16:15:46 +0300 Subject: [PATCH 23/40] fix: rename const Signed-off-by: Vladislav Sukhin --- pkg/agent/testworkflows.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index 5e02576384..94437742ec 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -23,8 +23,8 @@ import ( const testWorkflowNotificationsRetryCount = 10 var ( - retryDelay = 100 * time.Millisecond - waitTimeout = 24 * time.Hour + logRetryDelay = 100 * time.Millisecond + serviceWaitTimeout = 24 * time.Hour ) func getTestWorkflowNotificationType(n testkube.TestWorkflowExecutionNotification) cloud.TestWorkflowNotificationType { @@ -190,7 +190,7 @@ func (ag *Agent) executeWorkflowNotificationsRequest(ctx context.Context, req *c // Cloud sometimes slow to insert execution or test // while WorkflowNotifications request from websockets comes in faster // so we retry up to testWorkflowNotificationsRetryCount times. - time.Sleep(retryDelay) + time.Sleep(logRetryDelay) notificationsCh, err = ag.testWorkflowNotificationsFunc(ctx, req.ExecutionId) } } @@ -243,7 +243,7 @@ func (ag *Agent) executeWorkflowNotificationsRequest(ctx context.Context, req *c } func (ag *Agent) executeWorkflowServiceNotificationsRequest(ctx context.Context, req *cloud.TestWorkflowServiceNotificationsRequest) error { - timeoutCtx, cancel := context.WithTimeout(ctx, waitTimeout) + timeoutCtx, cancel := context.WithTimeout(ctx, serviceWaitTimeout) defer cancel() notificationsCh, err := retry.DoWithData( @@ -255,7 +255,7 @@ func (ag *Agent) executeWorkflowServiceNotificationsRequest(ctx context.Context, return ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.ServiceName, int(req.ServiceIndex)) }, retry.DelayType(retry.FixedDelay), - retry.Delay(retryDelay), + retry.Delay(logRetryDelay), retry.Context(timeoutCtx), retry.RetryIf(func(err error) bool { return errors.Is(err, registry.ErrResourceNotFound) From bcda47f107caba132f81f5c858a75f399145ce36 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 29 Nov 2024 17:07:26 +0300 Subject: [PATCH 24/40] fix: 0 attempts Signed-off-by: Vladislav Sukhin --- pkg/agent/testworkflows.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index 94437742ec..5edc96336a 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -260,6 +260,7 @@ func (ag *Agent) executeWorkflowServiceNotificationsRequest(ctx context.Context, retry.RetryIf(func(err error) bool { return errors.Is(err, registry.ErrResourceNotFound) }), + retry.Attempts(0), ) if err != nil { From 97b5bd3bce3065d2b2a57f485c41fc58af0f2b25 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 29 Nov 2024 17:20:14 +0300 Subject: [PATCH 25/40] fix: use option Signed-off-by: Vladislav Sukhin --- pkg/agent/testworkflows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index 5edc96336a..bd477932a0 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -260,7 +260,7 @@ func (ag *Agent) executeWorkflowServiceNotificationsRequest(ctx context.Context, retry.RetryIf(func(err error) bool { return errors.Is(err, registry.ErrResourceNotFound) }), - retry.Attempts(0), + retry.UntilSucceeded(), ) if err != nil { From 3e2c45f31951c61db0a825b014928e5b2f6a173c Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Fri, 29 Nov 2024 17:26:51 +0300 Subject: [PATCH 26/40] fix: remove ctx Signed-off-by: Vladislav Sukhin --- pkg/agent/testworkflows.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index bd477932a0..c70a28224f 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -243,9 +243,6 @@ func (ag *Agent) executeWorkflowNotificationsRequest(ctx context.Context, req *c } func (ag *Agent) executeWorkflowServiceNotificationsRequest(ctx context.Context, req *cloud.TestWorkflowServiceNotificationsRequest) error { - timeoutCtx, cancel := context.WithTimeout(ctx, serviceWaitTimeout) - defer cancel() - notificationsCh, err := retry.DoWithData( func() (<-chan testkube.TestWorkflowExecutionNotification, error) { // We have a race condition here @@ -256,7 +253,6 @@ func (ag *Agent) executeWorkflowServiceNotificationsRequest(ctx context.Context, }, retry.DelayType(retry.FixedDelay), retry.Delay(logRetryDelay), - retry.Context(timeoutCtx), retry.RetryIf(func(err error) bool { return errors.Is(err, registry.ErrResourceNotFound) }), From 2819e435cce9f45f47975ea794106ecbec2c3dca Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 2 Dec 2024 15:01:29 +0300 Subject: [PATCH 27/40] feat: add cli support for parallel steps Signed-off-by: Vladislav Sukhin --- .../commands/testworkflows/run.go | 73 ++++++++++++++++--- .../commands/testworkflows/watch.go | 10 ++- pkg/agent/testworkflows.go | 3 +- pkg/api/v1/client/interface.go | 1 + pkg/api/v1/client/testworkflow.go | 8 ++ .../model_test_workflow_execution_extended.go | 15 ++++ .../model_test_workflow_signature_extended.go | 21 ++++++ 7 files changed, 117 insertions(+), 14 deletions(-) diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index dcbe35b261..5028778074 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -27,9 +27,9 @@ import ( ) const ( - LogTimestampLength = 30 // time.RFC3339Nano without 00:00 timezone - apiErrorMessage = "processing error:" - serviceLogsCheckDelay = 100 * time.Millisecond + LogTimestampLength = 30 // time.RFC3339Nano without 00:00 timezone + apiErrorMessage = "processing error:" + logsCheckDelay = 100 * time.Millisecond ) var ( @@ -49,7 +49,9 @@ func NewRunTestWorkflowCmd() *cobra.Command { tags map[string]string selectors []string serviceName string + parallelStepName string serviceIndex int + parallelStepIndex int ) cmd := &cobra.Command{ @@ -149,7 +151,7 @@ func NewRunTestWorkflowCmd() *cobra.Command { ui.NL() if !execution.FailedToInitialize() { if watchEnabled && len(args) > 0 { - exitCode = uiWatch(execution, serviceName, serviceIndex, client) + exitCode = uiWatch(execution, serviceName, serviceIndex, parallelStepName, parallelStepIndex, client) ui.NL() if downloadArtifactsEnabled { tests.DownloadTestWorkflowArtifacts(execution.Id, downloadDir, format, masks, client, outputPretty) @@ -186,17 +188,19 @@ func NewRunTestWorkflowCmd() *cobra.Command { cmd.Flags().StringSliceVarP(&selectors, "label", "l", nil, "label key value pair: --label key1=value1 or label expression") cmd.Flags().StringVar(&serviceName, "service-name", "", "test workflow service name") cmd.Flags().IntVar(&serviceIndex, "service-index", 0, "test workflow service index starting from 0") + cmd.Flags().StringVar(¶llelStepName, "parallel-step-name", "", "test workflow parallel step name or reference") + cmd.Flags().IntVar(¶llelStepIndex, "parallel-step-index", 0, "test workflow parallel step index starting from 0") return cmd } -func uiWatch(execution testkube.TestWorkflowExecution, serviceName string, serviceIndex int, client apiclientv1.Client) int { +func uiWatch(execution testkube.TestWorkflowExecution, serviceName string, serviceIndex int, + parallelStepName string, parallelStepIndex int, client apiclientv1.Client) int { var result *testkube.TestWorkflowResult var err error - if serviceName == "" { - result, err = watchTestWorkflowLogs(execution.Id, execution.Signature, client) - } else { + switch { + case serviceName != "": found := false if execution.Workflow != nil { found = execution.Workflow.HasService(serviceName) @@ -207,6 +211,16 @@ func uiWatch(execution testkube.TestWorkflowExecution, serviceName string, servi } result, err = watchTestWorkflowServiceLogs(execution.Id, serviceName, serviceIndex, execution.Signature, client) + case parallelStepName != "": + ref := execution.GetParallelStepReference(parallelStepName) + if ref == "" { + ui.Failf("unknown parallel step '%s' for test workflow execution %s", parallelStepName, execution.Id) + } + + result, err = watchTestWorkflowParallelStepLogs(execution.Id, parallelStepName, parallelStepIndex, execution.Signature, client) + default: + result, err = watchTestWorkflowLogs(execution.Id, execution.Signature, client) + } ui.ExitOnError("reading test workflow execution logs", err) @@ -362,7 +376,48 @@ func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, if execution.Result.IsFinished() { nErr = errors.New("test workflow execution is finished") } else { - time.Sleep(serviceLogsCheckDelay) + time.Sleep(logsCheckDelay) + continue + } + } + } + + if nErr != nil { + spinner.Fail() + return nil, nErr + } + + break + } + + spinner.Success() + return printTestWorkflowLogs(signature, notifications), nil +} + +func watchTestWorkflowParallelStepLogs(id, parallelStepName string, parallelStepIndex int, + signature []testkube.TestWorkflowSignature, client apiclientv1.Client) (*testkube.TestWorkflowResult, error) { + ui.Info("Getting logs from test workflow parallel step job", fmt.Sprintf("%s-%s-%d", id, parallelStepName, parallelStepIndex)) + + var ( + notifications chan testkube.TestWorkflowExecutionNotification + nErr error + ) + + spinner := ui.NewSpinner("Waiting for parallel step logs") + for { + notifications, nErr = client.GetTestWorkflowExecutionParallelStepNotifications(id, parallelStepName, parallelStepIndex) + if nErr != nil { + execution, cErr := client.GetTestWorkflowExecution(id) + if cErr != nil { + spinner.Fail() + return nil, cErr + } + + if execution.Result != nil { + if execution.Result.IsFinished() { + nErr = errors.New("test workflow execution is finished") + } else { + time.Sleep(logsCheckDelay) continue } } diff --git a/cmd/kubectl-testkube/commands/testworkflows/watch.go b/cmd/kubectl-testkube/commands/testworkflows/watch.go index 35c6e918ec..790d0f3fea 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/watch.go +++ b/cmd/kubectl-testkube/commands/testworkflows/watch.go @@ -14,8 +14,10 @@ import ( func NewWatchTestWorkflowExecutionCmd() *cobra.Command { var ( - serviceName string - serviceIndex int + serviceName string + parallelStepName string + serviceIndex int + parallelStepIndex int ) cmd := &cobra.Command{ @@ -36,7 +38,7 @@ func NewWatchTestWorkflowExecutionCmd() *cobra.Command { ui.ExitOnError("render test workflow execution", err) ui.NL() - exitCode := uiWatch(execution, serviceName, serviceIndex, client) + exitCode := uiWatch(execution, serviceName, serviceIndex, parallelStepName, parallelStepIndex, client) ui.NL() execution, err = client.GetTestWorkflowExecution(execution.Id) @@ -50,6 +52,8 @@ func NewWatchTestWorkflowExecutionCmd() *cobra.Command { cmd.Flags().StringVar(&serviceName, "service-name", "", "test workflow service name") cmd.Flags().IntVar(&serviceIndex, "service-index", 0, "test workflow service index starting from 0") + cmd.Flags().StringVar(¶llelStepName, "parallel-step-name", "", "test workflow parallel step name or reference") + cmd.Flags().IntVar(¶llelStepIndex, "parallel-step-index", 0, "test workflow parallel step index starting from 0") return cmd } diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index c70a28224f..3a1ce2f54b 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -23,8 +23,7 @@ import ( const testWorkflowNotificationsRetryCount = 10 var ( - logRetryDelay = 100 * time.Millisecond - serviceWaitTimeout = 24 * time.Hour + logRetryDelay = 100 * time.Millisecond ) func getTestWorkflowNotificationType(n testkube.TestWorkflowExecutionNotification) cloud.TestWorkflowNotificationType { diff --git a/pkg/api/v1/client/interface.go b/pkg/api/v1/client/interface.go index 73a3f6c48a..e5635a31d9 100644 --- a/pkg/api/v1/client/interface.go +++ b/pkg/api/v1/client/interface.go @@ -155,6 +155,7 @@ type TestWorkflowAPI interface { GetTestWorkflowExecutionNotifications(id string) (chan testkube.TestWorkflowExecutionNotification, error) GetTestWorkflowExecutionLogs(id string) ([]byte, error) GetTestWorkflowExecutionServiceNotifications(id, serviceName string, serviceIndex int) (chan testkube.TestWorkflowExecutionNotification, error) + GetTestWorkflowExecutionParallelStepNotifications(id, parallelStepName string, parallelStepIndex int) (chan testkube.TestWorkflowExecutionNotification, error) } // TestWorkflowExecutionAPI describes test workflow api methods diff --git a/pkg/api/v1/client/testworkflow.go b/pkg/api/v1/client/testworkflow.go index 8bffb81d28..77c4299ed7 100644 --- a/pkg/api/v1/client/testworkflow.go +++ b/pkg/api/v1/client/testworkflow.go @@ -154,6 +154,14 @@ func (c TestWorkflowClient) GetTestWorkflowExecutionServiceNotifications(id, ser return notifications, err } +// GetTestWorkflowExecutionParallelStepNotifications returns events stream from job pods, based on job pods logs +func (c TestWorkflowClient) GetTestWorkflowExecutionParallelStepNotifications(id, parallelStepName string, parallelStepIndex int) (notifications chan testkube.TestWorkflowExecutionNotification, err error) { + notifications = make(chan testkube.TestWorkflowExecutionNotification) + uri := c.testWorkflowTransport.GetURI("/test-workflow-executions/%s/notifications/%s/%d", id, parallelStepName, parallelStepIndex) + err = c.testWorkflowTransport.GetTestWorkflowExecutionNotifications(uri, notifications) + return notifications, err +} + // GetTestWorkflowExecution returns single test workflow execution by id func (c TestWorkflowClient) GetTestWorkflowExecution(id string) (testkube.TestWorkflowExecution, error) { uri := c.testWorkflowExecutionTransport.GetURI("/test-workflow-executions/%s", id) diff --git a/pkg/api/v1/testkube/model_test_workflow_execution_extended.go b/pkg/api/v1/testkube/model_test_workflow_execution_extended.go index dc1c4e0736..4b758c5abd 100644 --- a/pkg/api/v1/testkube/model_test_workflow_execution_extended.go +++ b/pkg/api/v1/testkube/model_test_workflow_execution_extended.go @@ -115,3 +115,18 @@ func (e *TestWorkflowExecution) InitializationError(header string, err error) { func (e *TestWorkflowExecution) FailedToInitialize() bool { return e.Result.Status != nil && *e.Result.Status == ABORTED_TestWorkflowStatus && e.Result.QueuedAt.IsZero() } + +func (e *TestWorkflowExecution) GetParallelStepReference(nameOrReference string) string { + if e == nil { + return "" + } + + for _, signature := range e.Signature { + ref := signature.GetParallelStepReference(nameOrReference) + if ref != "" { + return ref + } + } + + return "" +} diff --git a/pkg/api/v1/testkube/model_test_workflow_signature_extended.go b/pkg/api/v1/testkube/model_test_workflow_signature_extended.go index cd5979e1f6..b9d2e98617 100644 --- a/pkg/api/v1/testkube/model_test_workflow_signature_extended.go +++ b/pkg/api/v1/testkube/model_test_workflow_signature_extended.go @@ -14,3 +14,24 @@ func (s *TestWorkflowSignature) Sequence() []TestWorkflowSignature { } return result } + +func (s *TestWorkflowSignature) GetParallelStepReference(nameOrReference string) string { + if s.Category == "Run in parallel" { + if nameOrReference == "" { + return s.Ref + } + + if s.Name == nameOrReference || s.Ref == nameOrReference { + return s.Ref + } + } + + for _, child := range s.Children { + ref := child.GetParallelStepReference(nameOrReference) + if ref != "" { + return ref + } + } + + return "" +} From 81b0295842c49298293f3daffb0ebc93c8714b1a Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 2 Dec 2024 15:13:12 +0300 Subject: [PATCH 28/40] fix: rename url Signed-off-by: Vladislav Sukhin --- pkg/api/v1/client/testworkflow.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/api/v1/client/testworkflow.go b/pkg/api/v1/client/testworkflow.go index 77c4299ed7..d683374809 100644 --- a/pkg/api/v1/client/testworkflow.go +++ b/pkg/api/v1/client/testworkflow.go @@ -149,7 +149,7 @@ func (c TestWorkflowClient) GetTestWorkflowExecutionNotifications(id string) (no // GetTestWorkflowExecutionServiceNotifications returns events stream from job pods, based on job pods logs func (c TestWorkflowClient) GetTestWorkflowExecutionServiceNotifications(id, serviceName string, serviceIndex int) (notifications chan testkube.TestWorkflowExecutionNotification, err error) { notifications = make(chan testkube.TestWorkflowExecutionNotification) - uri := c.testWorkflowTransport.GetURI("/test-workflow-executions/%s/notifications/%s/%d", id, serviceName, serviceIndex) + uri := c.testWorkflowTransport.GetURI("/test-workflow-executions/%s/notifications/services/%s/%d", id, serviceName, serviceIndex) err = c.testWorkflowTransport.GetTestWorkflowExecutionNotifications(uri, notifications) return notifications, err } @@ -157,7 +157,7 @@ func (c TestWorkflowClient) GetTestWorkflowExecutionServiceNotifications(id, ser // GetTestWorkflowExecutionParallelStepNotifications returns events stream from job pods, based on job pods logs func (c TestWorkflowClient) GetTestWorkflowExecutionParallelStepNotifications(id, parallelStepName string, parallelStepIndex int) (notifications chan testkube.TestWorkflowExecutionNotification, err error) { notifications = make(chan testkube.TestWorkflowExecutionNotification) - uri := c.testWorkflowTransport.GetURI("/test-workflow-executions/%s/notifications/%s/%d", id, parallelStepName, parallelStepIndex) + uri := c.testWorkflowTransport.GetURI("/test-workflow-executions/%s/notifications/parallel-steps/%s/%d", id, parallelStepName, parallelStepIndex) err = c.testWorkflowTransport.GetTestWorkflowExecutionNotifications(uri, notifications) return notifications, err } From c71fb91ac90b1ceef5c21be534df43982fcd493c Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 2 Dec 2024 15:53:41 +0300 Subject: [PATCH 29/40] feat: api methods for parallel steps Signed-off-by: Vladislav Sukhin --- internal/app/api/v1/server.go | 6 +- internal/app/api/v1/testworkflowexecutions.go | 81 +++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/internal/app/api/v1/server.go b/internal/app/api/v1/server.go index 816783fee4..4fc844e93d 100644 --- a/internal/app/api/v1/server.go +++ b/internal/app/api/v1/server.go @@ -150,9 +150,11 @@ func (s *TestkubeAPI) Init(server server.HTTPServer) { testWorkflowExecutions.Post("/", s.ExecuteTestWorkflowHandler()) testWorkflowExecutions.Get("/:executionID", s.GetTestWorkflowExecutionHandler()) testWorkflowExecutions.Get("/:executionID/notifications", s.StreamTestWorkflowExecutionNotificationsHandler()) - testWorkflowExecutions.Get("/:executionID/notifications/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/services/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/parallel-steps/:parallelStepName/:parallelStepIndex", s.StreamTestWorkflowExecutionParallelStepNotificationsHandler()) testWorkflowExecutions.Get("/:executionID/notifications/stream", s.StreamTestWorkflowExecutionNotificationsWebSocketHandler()) - testWorkflowExecutions.Get("/:executionID/notifications/stream/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsWebSocketHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/stream/services/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsWebSocketHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/stream/parallel-steps/:parallelStepName/:parallelStepIndex", s.StreamTestWorkflowExecutionParallelStepNotificationsWebSocketHandler()) testWorkflowExecutions.Post("/:executionID/abort", s.AbortTestWorkflowExecutionHandler()) testWorkflowExecutions.Post("/:executionID/pause", s.PauseTestWorkflowExecutionHandler()) testWorkflowExecutions.Post("/:executionID/resume", s.ResumeTestWorkflowExecutionHandler()) diff --git a/internal/app/api/v1/testworkflowexecutions.go b/internal/app/api/v1/testworkflowexecutions.go index 3670613fb7..be91185fd2 100644 --- a/internal/app/api/v1/testworkflowexecutions.go +++ b/internal/app/api/v1/testworkflowexecutions.go @@ -129,6 +129,43 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionServiceNotificationsHandler() f } } +func (s *TestkubeAPI) StreamTestWorkflowExecutionParallelStepNotificationsHandler() fiber.Handler { + return func(c *fiber.Ctx) error { + ctx := c.Context() + executionID := c.Params("executionID") + parallelStepName := c.Params("parallelStepName") + parallelStepIndex := c.Params("parallelStepIndex") + errPrefix := fmt.Sprintf("failed to stream test workflow execution parallel step '%s' instance '%s' notifications '%s'", + parallelStepName, parallelStepIndex, executionID) + + // Fetch execution from database + execution, err := s.TestWorkflowResults.Get(ctx, executionID) + if err != nil { + return s.ClientError(c, errPrefix, err) + } + + ref := execution.GetParallelStepReference(parallelStepName) + if ref == "" { + return s.ClientError(c, errPrefix, errors.New("unknown parallel step for test workflow execution")) + } + + // Check for the logs + id := fmt.Sprintf("%s-%s-%s", execution.Id, ref, parallelStepIndex) + notifications := s.ExecutionWorkerClient.Notifications(ctx, id, executionworkertypes.NotificationsOptions{ + Hints: executionworkertypes.Hints{ + Namespace: execution.Namespace, + ScheduledAt: common.Ptr(execution.ScheduledAt), + }, + }) + if notifications.Err() != nil { + return s.BadRequest(c, errPrefix, "fetching notifications", notifications.Err()) + } + + s.streamNotifications(ctx, id, notifications) + return nil + } +} + func (s *TestkubeAPI) StreamTestWorkflowExecutionNotificationsWebSocketHandler() fiber.Handler { return websocket.New(func(c *websocket.Conn) { ctx, ctxCancel := context.WithCancel(context.Background()) @@ -214,6 +251,50 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionServiceNotificationsWebSocketHa }) } +func (s *TestkubeAPI) StreamTestWorkflowExecutionParallelStepNotificationsWebSocketHandler() fiber.Handler { + return websocket.New(func(c *websocket.Conn) { + ctx, ctxCancel := context.WithCancel(context.Background()) + executionID := c.Params("executionID") + parallelStepName := c.Params("parallelStepName") + parallelStepIndex := c.Params("parallelStepIndex") + + // Stop reading when the WebSocket connection is already closed + originalClose := c.CloseHandler() + c.SetCloseHandler(func(code int, text string) error { + ctxCancel() + return originalClose(code, text) + }) + defer c.Conn.Close() + + // Fetch execution from database + execution, err := s.TestWorkflowResults.Get(ctx, executionID) + if err != nil { + return + } + + ref := execution.GetParallelStepReference(parallelStepName) + if ref == "" { + return + } + + // Check for the logs + id := fmt.Sprintf("%s-%s-%s", execution.Id, ref, parallelStepIndex) + notifications := s.ExecutionWorkerClient.Notifications(ctx, id, executionworkertypes.NotificationsOptions{ + Hints: executionworkertypes.Hints{ + Namespace: execution.Namespace, + ScheduledAt: common.Ptr(execution.ScheduledAt), + }, + }) + if notifications.Err() != nil { + return + } + + for n := range notifications.Channel() { + _ = c.WriteJSON(n) + } + }) +} + func (s *TestkubeAPI) ListTestWorkflowExecutionsHandler() fiber.Handler { return func(c *fiber.Ctx) error { errPrefix := "failed to list test workflow executions" From 6003cded2792237758f2d2ca0dda4e65f2a42818 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 2 Dec 2024 16:54:45 +0300 Subject: [PATCH 30/40] fix: tune parallel step detection Signed-off-by: Vladislav Sukhin --- .../model_test_workflow_signature_extended.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pkg/api/v1/testkube/model_test_workflow_signature_extended.go b/pkg/api/v1/testkube/model_test_workflow_signature_extended.go index b9d2e98617..0fdc70686c 100644 --- a/pkg/api/v1/testkube/model_test_workflow_signature_extended.go +++ b/pkg/api/v1/testkube/model_test_workflow_signature_extended.go @@ -16,17 +16,18 @@ func (s *TestWorkflowSignature) Sequence() []TestWorkflowSignature { } func (s *TestWorkflowSignature) GetParallelStepReference(nameOrReference string) string { - if s.Category == "Run in parallel" { - if nameOrReference == "" { - return s.Ref - } - - if s.Name == nameOrReference || s.Ref == nameOrReference { - return s.Ref - } + if s.Category == "Run in parallel" && (nameOrReference == "" || s.Ref == nameOrReference) { + return s.Ref } for _, child := range s.Children { + if s.Name == nameOrReference { + ref := child.GetParallelStepReference("") + if ref != "" { + return ref + } + } + ref := child.GetParallelStepReference(nameOrReference) if ref != "" { return ref From 5136c312b8cec4ba94bb5660e6af7fea0f3eaec8 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 2 Dec 2024 17:31:42 +0300 Subject: [PATCH 31/40] fix: typo Signed-off-by: Vladislav Sukhin --- cmd/kubectl-testkube/commands/testworkflows/run.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index 5028778074..e9dec5ff4e 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -217,7 +217,7 @@ func uiWatch(execution testkube.TestWorkflowExecution, serviceName string, servi ui.Failf("unknown parallel step '%s' for test workflow execution %s", parallelStepName, execution.Id) } - result, err = watchTestWorkflowParallelStepLogs(execution.Id, parallelStepName, parallelStepIndex, execution.Signature, client) + result, err = watchTestWorkflowParallelStepLogs(execution.Id, ref, parallelStepIndex, execution.Signature, client) default: result, err = watchTestWorkflowLogs(execution.Id, execution.Signature, client) From 6b89ab0c33e9896ca1cbb68c7a735a5c6468253b Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 2 Dec 2024 18:57:26 +0300 Subject: [PATCH 32/40] fix: cli Signed-off-by: Vladislav Sukhin --- .../commands/testworkflows/run.go | 28 ++++++++++++------- .../commands/testworkflows/watch.go | 10 ++++++- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index e9dec5ff4e..14dc9cac44 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -151,7 +151,15 @@ func NewRunTestWorkflowCmd() *cobra.Command { ui.NL() if !execution.FailedToInitialize() { if watchEnabled && len(args) > 0 { - exitCode = uiWatch(execution, serviceName, serviceIndex, parallelStepName, parallelStepIndex, client) + var pServiceName, pParallelStepName *string + if cmd.Flag("service-name").Changed || cmd.Flag("service-index").Changed { + pServiceName = &serviceName + } + if cmd.Flag("parallel-step-name").Changed || cmd.Flag("parallel-step-index").Changed { + pParallelStepName = ¶llelStepName + } + + exitCode = uiWatch(execution, pServiceName, serviceIndex, pParallelStepName, parallelStepIndex, client) ui.NL() if downloadArtifactsEnabled { tests.DownloadTestWorkflowArtifacts(execution.Id, downloadDir, format, masks, client, outputPretty) @@ -194,27 +202,27 @@ func NewRunTestWorkflowCmd() *cobra.Command { return cmd } -func uiWatch(execution testkube.TestWorkflowExecution, serviceName string, serviceIndex int, - parallelStepName string, parallelStepIndex int, client apiclientv1.Client) int { +func uiWatch(execution testkube.TestWorkflowExecution, serviceName *string, serviceIndex int, + parallelStepName *string, parallelStepIndex int, client apiclientv1.Client) int { var result *testkube.TestWorkflowResult var err error switch { - case serviceName != "": + case serviceName != nil: found := false if execution.Workflow != nil { - found = execution.Workflow.HasService(serviceName) + found = execution.Workflow.HasService(*serviceName) } if !found { - ui.Failf("unknown service '%s' for test workflow execution %s", serviceName, execution.Id) + ui.Failf("unknown service '%s' for test workflow execution %s", *serviceName, execution.Id) } - result, err = watchTestWorkflowServiceLogs(execution.Id, serviceName, serviceIndex, execution.Signature, client) - case parallelStepName != "": - ref := execution.GetParallelStepReference(parallelStepName) + result, err = watchTestWorkflowServiceLogs(execution.Id, *serviceName, serviceIndex, execution.Signature, client) + case parallelStepName != nil: + ref := execution.GetParallelStepReference(*parallelStepName) if ref == "" { - ui.Failf("unknown parallel step '%s' for test workflow execution %s", parallelStepName, execution.Id) + ui.Failf("unknown parallel step '%s' for test workflow execution %s", *parallelStepName, execution.Id) } result, err = watchTestWorkflowParallelStepLogs(execution.Id, ref, parallelStepIndex, execution.Signature, client) diff --git a/cmd/kubectl-testkube/commands/testworkflows/watch.go b/cmd/kubectl-testkube/commands/testworkflows/watch.go index 790d0f3fea..eb9c7c7769 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/watch.go +++ b/cmd/kubectl-testkube/commands/testworkflows/watch.go @@ -38,7 +38,15 @@ func NewWatchTestWorkflowExecutionCmd() *cobra.Command { ui.ExitOnError("render test workflow execution", err) ui.NL() - exitCode := uiWatch(execution, serviceName, serviceIndex, parallelStepName, parallelStepIndex, client) + var pServiceName, pParallelStepName *string + if cmd.Flag("service-name").Changed || cmd.Flag("service-index").Changed { + pServiceName = &serviceName + } + if cmd.Flag("parallel-step-name").Changed || cmd.Flag("parallel-step-index").Changed { + pParallelStepName = ¶llelStepName + } + + exitCode := uiWatch(execution, pServiceName, serviceIndex, pParallelStepName, parallelStepIndex, client) ui.NL() execution, err = client.GetTestWorkflowExecution(execution.Id) From bcffbd56bce304e051834201bc9779d6e68afeeb Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Mon, 2 Dec 2024 20:05:39 +0300 Subject: [PATCH 33/40] feat: add proto for parallel step logs Signed-off-by: Vladislav Sukhin --- cmd/api-server/commons/commons.go | 13 +- cmd/api-server/main.go | 22 ++ internal/config/config.go | 87 +++--- internal/config/procontext.go | 27 +- pkg/agent/agent.go | 6 + pkg/agent/agent_test.go | 4 +- pkg/agent/events_test.go | 4 +- pkg/agent/logs_test.go | 4 +- pkg/cloud/service.pb.go | 491 ++++++++++++++++++++++-------- pkg/cloud/service_grpc.pb.go | 68 +++++ proto/service.proto | 18 ++ 11 files changed, 552 insertions(+), 192 deletions(-) diff --git a/cmd/api-server/commons/commons.go b/cmd/api-server/commons/commons.go index b689d51935..e10813b5c6 100644 --- a/cmd/api-server/commons/commons.go +++ b/cmd/api-server/commons/commons.go @@ -289,12 +289,13 @@ func ReadProContext(ctx context.Context, cfg *config.Config, grpcClient cloud.Te LogStreamWorkerCount: cfg.TestkubeProLogStreamWorkerCount, WorkflowNotificationsWorkerCount: cfg.TestkubeProWorkflowNotificationsWorkerCount, WorkflowServiceNotificationsWorkerCount: cfg.TestkubeProWorkflowServiceNotificationsWorkerCount, - SkipVerify: cfg.TestkubeProSkipVerify, - EnvID: cfg.TestkubeProEnvID, - OrgID: cfg.TestkubeProOrgID, - Migrate: cfg.TestkubeProMigrate, - ConnectionTimeout: cfg.TestkubeProConnectionTimeout, - DashboardURI: cfg.TestkubeDashboardURI, + WorkflowParallelStepNotificationsWorkerCount: cfg.TestkubeProWorkflowParallelStepNotificationsWorkerCount, + SkipVerify: cfg.TestkubeProSkipVerify, + EnvID: cfg.TestkubeProEnvID, + OrgID: cfg.TestkubeProOrgID, + Migrate: cfg.TestkubeProMigrate, + ConnectionTimeout: cfg.TestkubeProConnectionTimeout, + DashboardURI: cfg.TestkubeDashboardURI, } if cfg.TestkubeProAPIKey == "" || grpcClient == nil { diff --git a/cmd/api-server/main.go b/cmd/api-server/main.go index f110d0f1d9..4ea389ae3f 100644 --- a/cmd/api-server/main.go +++ b/cmd/api-server/main.go @@ -346,6 +346,27 @@ func main() { } return notifications.Channel(), nil } + getTestWorkflowParallelStepNotificationsStream := func(ctx context.Context, executionID, ref string, parallelStepIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) { + execution, err := testWorkflowResultsRepository.Get(ctx, executionID) + if err != nil { + return nil, err + } + + if execution.Result != nil && execution.Result.IsFinished() { + return nil, errors.New("test workflow execution is finished") + } + + notifications := executionWorker.Notifications(ctx, fmt.Sprintf("%s-%s-%d", execution.Id, ref, parallelStepIndex), executionworkertypes.NotificationsOptions{ + Hints: executionworkertypes.Hints{ + Namespace: execution.Namespace, + ScheduledAt: common.Ptr(execution.ScheduledAt), + }, + }) + if notifications.Err() != nil { + return nil, notifications.Err() + } + return notifications.Channel(), nil + } getDeprecatedLogStream := func(ctx context.Context, executionID string) (chan output.Output, error) { return nil, errors.New("deprecated features have been disabled") } @@ -359,6 +380,7 @@ func main() { getDeprecatedLogStream, getTestWorkflowNotificationsStream, getTestWorkflowServiceNotificationsStream, + getTestWorkflowParallelStepNotificationsStream, clusterId, cfg.TestkubeClusterName, features, diff --git a/internal/config/config.go b/internal/config/config.go index 0394c8d981..d3a4d14fbc 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -40,49 +40,50 @@ type Config struct { LogsStorage string `envconfig:"LOGS_STORAGE" default:""` WorkflowStorage string `envconfig:"WORKFLOW_STORAGE" default:"crd"` // WhitelistedContainers is a list of containers from which logs should be collected. - WhitelistedContainers []string `envconfig:"WHITELISTED_CONTAINERS" default:"init,logs,scraper"` - NatsEmbedded bool `envconfig:"NATS_EMBEDDED" default:"false"` - NatsEmbeddedStoreDir string `envconfig:"NATS_EMBEDDED_STORE_DIR" default:"/app/nats"` - NatsURI string `envconfig:"NATS_URI" default:"nats://localhost:4222"` - NatsSecure bool `envconfig:"NATS_SECURE" default:"false"` - NatsSkipVerify bool `envconfig:"NATS_SKIP_VERIFY" default:"false"` - NatsCertFile string `envconfig:"NATS_CERT_FILE" default:""` - NatsKeyFile string `envconfig:"NATS_KEY_FILE" default:""` - NatsCAFile string `envconfig:"NATS_CA_FILE" default:""` - NatsConnectTimeout time.Duration `envconfig:"NATS_CONNECT_TIMEOUT" default:"5s"` - JobServiceAccountName string `envconfig:"JOB_SERVICE_ACCOUNT_NAME" default:""` - JobTemplateFile string `envconfig:"JOB_TEMPLATE_FILE" default:""` - DisableTestTriggers bool `envconfig:"DISABLE_TEST_TRIGGERS" default:"false"` - TestkubeDefaultExecutors string `envconfig:"TESTKUBE_DEFAULT_EXECUTORS" default:""` - TestkubeEnabledExecutors string `envconfig:"TESTKUBE_ENABLED_EXECUTORS" default:""` - TestkubeTemplateJob string `envconfig:"TESTKUBE_TEMPLATE_JOB" default:""` - TestkubeContainerTemplateJob string `envconfig:"TESTKUBE_CONTAINER_TEMPLATE_JOB" default:""` - TestkubeContainerTemplateScraper string `envconfig:"TESTKUBE_CONTAINER_TEMPLATE_SCRAPER" default:""` - TestkubeContainerTemplatePVC string `envconfig:"TESTKUBE_CONTAINER_TEMPLATE_PVC" default:""` - TestkubeTemplateSlavePod string `envconfig:"TESTKUBE_TEMPLATE_SLAVE_POD" default:""` - TestkubeConfigDir string `envconfig:"TESTKUBE_CONFIG_DIR" default:"config"` - TestkubeAnalyticsEnabled bool `envconfig:"TESTKUBE_ANALYTICS_ENABLED" default:"false"` - TestkubeReadonlyExecutors bool `envconfig:"TESTKUBE_READONLY_EXECUTORS" default:"false"` - TestkubeNamespace string `envconfig:"TESTKUBE_NAMESPACE" default:"testkube"` - TestkubeProAPIKey string `envconfig:"TESTKUBE_PRO_API_KEY" default:""` - TestkubeProURL string `envconfig:"TESTKUBE_PRO_URL" default:""` - TestkubeProTLSInsecure bool `envconfig:"TESTKUBE_PRO_TLS_INSECURE" default:"false"` - TestkubeProWorkerCount int `envconfig:"TESTKUBE_PRO_WORKER_COUNT" default:"50"` - TestkubeProLogStreamWorkerCount int `envconfig:"TESTKUBE_PRO_LOG_STREAM_WORKER_COUNT" default:"25"` - TestkubeProWorkflowNotificationsWorkerCount int `envconfig:"TESTKUBE_PRO_WORKFLOW_NOTIFICATIONS_STREAM_WORKER_COUNT" default:"25"` - TestkubeProWorkflowServiceNotificationsWorkerCount int `envconfig:"TESTKUBE_PRO_WORKFLOW_SERVICE_NOTIFICATIONS_STREAM_WORKER_COUNT" default:"25"` - TestkubeProSkipVerify bool `envconfig:"TESTKUBE_PRO_SKIP_VERIFY" default:"false"` - TestkubeProEnvID string `envconfig:"TESTKUBE_PRO_ENV_ID" default:""` - TestkubeProOrgID string `envconfig:"TESTKUBE_PRO_ORG_ID" default:""` - TestkubeProMigrate string `envconfig:"TESTKUBE_PRO_MIGRATE" default:"false"` - TestkubeProConnectionTimeout int `envconfig:"TESTKUBE_PRO_CONNECTION_TIMEOUT" default:"10"` - TestkubeProCertFile string `envconfig:"TESTKUBE_PRO_CERT_FILE" default:""` - TestkubeProKeyFile string `envconfig:"TESTKUBE_PRO_KEY_FILE" default:""` - TestkubeProTLSSecret string `envconfig:"TESTKUBE_PRO_TLS_SECRET" default:""` - TestkubeProRunnerCustomCASecret string `envconfig:"TESTKUBE_PRO_RUNNER_CUSTOM_CA_SECRET" default:""` - TestkubeWatcherNamespaces string `envconfig:"TESTKUBE_WATCHER_NAMESPACES" default:""` - TestkubeRegistry string `envconfig:"TESTKUBE_REGISTRY" default:""` - TestkubePodStartTimeout time.Duration `envconfig:"TESTKUBE_POD_START_TIMEOUT" default:"30m"` + WhitelistedContainers []string `envconfig:"WHITELISTED_CONTAINERS" default:"init,logs,scraper"` + NatsEmbedded bool `envconfig:"NATS_EMBEDDED" default:"false"` + NatsEmbeddedStoreDir string `envconfig:"NATS_EMBEDDED_STORE_DIR" default:"/app/nats"` + NatsURI string `envconfig:"NATS_URI" default:"nats://localhost:4222"` + NatsSecure bool `envconfig:"NATS_SECURE" default:"false"` + NatsSkipVerify bool `envconfig:"NATS_SKIP_VERIFY" default:"false"` + NatsCertFile string `envconfig:"NATS_CERT_FILE" default:""` + NatsKeyFile string `envconfig:"NATS_KEY_FILE" default:""` + NatsCAFile string `envconfig:"NATS_CA_FILE" default:""` + NatsConnectTimeout time.Duration `envconfig:"NATS_CONNECT_TIMEOUT" default:"5s"` + JobServiceAccountName string `envconfig:"JOB_SERVICE_ACCOUNT_NAME" default:""` + JobTemplateFile string `envconfig:"JOB_TEMPLATE_FILE" default:""` + DisableTestTriggers bool `envconfig:"DISABLE_TEST_TRIGGERS" default:"false"` + TestkubeDefaultExecutors string `envconfig:"TESTKUBE_DEFAULT_EXECUTORS" default:""` + TestkubeEnabledExecutors string `envconfig:"TESTKUBE_ENABLED_EXECUTORS" default:""` + TestkubeTemplateJob string `envconfig:"TESTKUBE_TEMPLATE_JOB" default:""` + TestkubeContainerTemplateJob string `envconfig:"TESTKUBE_CONTAINER_TEMPLATE_JOB" default:""` + TestkubeContainerTemplateScraper string `envconfig:"TESTKUBE_CONTAINER_TEMPLATE_SCRAPER" default:""` + TestkubeContainerTemplatePVC string `envconfig:"TESTKUBE_CONTAINER_TEMPLATE_PVC" default:""` + TestkubeTemplateSlavePod string `envconfig:"TESTKUBE_TEMPLATE_SLAVE_POD" default:""` + TestkubeConfigDir string `envconfig:"TESTKUBE_CONFIG_DIR" default:"config"` + TestkubeAnalyticsEnabled bool `envconfig:"TESTKUBE_ANALYTICS_ENABLED" default:"false"` + TestkubeReadonlyExecutors bool `envconfig:"TESTKUBE_READONLY_EXECUTORS" default:"false"` + TestkubeNamespace string `envconfig:"TESTKUBE_NAMESPACE" default:"testkube"` + TestkubeProAPIKey string `envconfig:"TESTKUBE_PRO_API_KEY" default:""` + TestkubeProURL string `envconfig:"TESTKUBE_PRO_URL" default:""` + TestkubeProTLSInsecure bool `envconfig:"TESTKUBE_PRO_TLS_INSECURE" default:"false"` + TestkubeProWorkerCount int `envconfig:"TESTKUBE_PRO_WORKER_COUNT" default:"50"` + TestkubeProLogStreamWorkerCount int `envconfig:"TESTKUBE_PRO_LOG_STREAM_WORKER_COUNT" default:"25"` + TestkubeProWorkflowNotificationsWorkerCount int `envconfig:"TESTKUBE_PRO_WORKFLOW_NOTIFICATIONS_STREAM_WORKER_COUNT" default:"25"` + TestkubeProWorkflowServiceNotificationsWorkerCount int `envconfig:"TESTKUBE_PRO_WORKFLOW_SERVICE_NOTIFICATIONS_STREAM_WORKER_COUNT" default:"25"` + TestkubeProWorkflowParallelStepNotificationsWorkerCount int `envconfig:"TESTKUBE_PRO_WORKFLOW_PARALLEL_STEP_NOTIFICATIONS_STREAM_WORKER_COUNT" default:"25"` + TestkubeProSkipVerify bool `envconfig:"TESTKUBE_PRO_SKIP_VERIFY" default:"false"` + TestkubeProEnvID string `envconfig:"TESTKUBE_PRO_ENV_ID" default:""` + TestkubeProOrgID string `envconfig:"TESTKUBE_PRO_ORG_ID" default:""` + TestkubeProMigrate string `envconfig:"TESTKUBE_PRO_MIGRATE" default:"false"` + TestkubeProConnectionTimeout int `envconfig:"TESTKUBE_PRO_CONNECTION_TIMEOUT" default:"10"` + TestkubeProCertFile string `envconfig:"TESTKUBE_PRO_CERT_FILE" default:""` + TestkubeProKeyFile string `envconfig:"TESTKUBE_PRO_KEY_FILE" default:""` + TestkubeProTLSSecret string `envconfig:"TESTKUBE_PRO_TLS_SECRET" default:""` + TestkubeProRunnerCustomCASecret string `envconfig:"TESTKUBE_PRO_RUNNER_CUSTOM_CA_SECRET" default:""` + TestkubeWatcherNamespaces string `envconfig:"TESTKUBE_WATCHER_NAMESPACES" default:""` + TestkubeRegistry string `envconfig:"TESTKUBE_REGISTRY" default:""` + TestkubePodStartTimeout time.Duration `envconfig:"TESTKUBE_POD_START_TIMEOUT" default:"30m"` // TestkubeImageCredentialsCacheTTL is the duration for which the image pull credentials should be cached provided as a Go duration string. // If set to 0, the cache is disabled. TestkubeImageCredentialsCacheTTL time.Duration `envconfig:"TESTKUBE_IMAGE_CREDENTIALS_CACHE_TTL" default:"30m"` diff --git a/internal/config/procontext.go b/internal/config/procontext.go index 4bfcb41acf..ed8cf5d03b 100644 --- a/internal/config/procontext.go +++ b/internal/config/procontext.go @@ -1,17 +1,18 @@ package config type ProContext struct { - APIKey string - URL string - TLSInsecure bool - WorkerCount int - LogStreamWorkerCount int - WorkflowNotificationsWorkerCount int - WorkflowServiceNotificationsWorkerCount int - SkipVerify bool - EnvID string - OrgID string - Migrate string - ConnectionTimeout int - DashboardURI string + APIKey string + URL string + TLSInsecure bool + WorkerCount int + LogStreamWorkerCount int + WorkflowNotificationsWorkerCount int + WorkflowServiceNotificationsWorkerCount int + WorkflowParallelStepNotificationsWorkerCount int + SkipVerify bool + EnvID string + OrgID string + Migrate string + ConnectionTimeout int + DashboardURI string } diff --git a/pkg/agent/agent.go b/pkg/agent/agent.go index e11fb03983..45b8a40e56 100644 --- a/pkg/agent/agent.go +++ b/pkg/agent/agent.go @@ -60,6 +60,11 @@ type Agent struct { testWorkflowServiceNotificationsResponseBuffer chan *cloud.TestWorkflowServiceNotificationsResponse testWorkflowServiceNotificationsFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) + testWorkflowParallelStepNotificationsWorkerCount int + testWorkflowParallelStepNotificationsRequestBuffer chan *cloud.TestWorkflowParallelStepNotificationsRequest + testWorkflowParallelStepNotificationsResponseBuffer chan *cloud.TestWorkflowParallelStepNotificationsResponse + testWorkflowParallelStepNotificationsFunc func(ctx context.Context, executionID, ref string, parallelStepIndexIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) + events chan testkube.Event sendTimeout time.Duration receiveTimeout time.Duration @@ -79,6 +84,7 @@ func NewAgent(logger *zap.SugaredLogger, logStreamFunc func(ctx context.Context, executionID string) (chan output.Output, error), workflowNotificationsFunc func(ctx context.Context, executionID string) (<-chan testkube.TestWorkflowExecutionNotification, error), workflowServiceNotificationsFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error), + workflowParallelStepNotificationsFunc func(ctx context.Context, executionID, ref string, parallelStepIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error), clusterID string, clusterName string, features featureflags.FeatureFlags, diff --git a/pkg/agent/agent_test.go b/pkg/agent/agent_test.go index 47973e09ac..4b4936dd6c 100644 --- a/pkg/agent/agent_test.go +++ b/pkg/agent/agent_test.go @@ -60,10 +60,12 @@ func TestCommandExecution(t *testing.T) { var logStreamFunc func(ctx context.Context, executionID string) (chan output.Output, error) var workflowNotificationsStreamFunc func(ctx context.Context, executionID string) (<-chan testkube.TestWorkflowExecutionNotification, error) var workflowServiceNotificationsStreamFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) + var workflowParallelStepNotificationsStreamFunc func(ctx context.Context, executionID, ref string, parallelStepIndexIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) logger, _ := zap.NewDevelopment() proContext := config.ProContext{APIKey: "api-key", WorkerCount: 5, LogStreamWorkerCount: 5, WorkflowNotificationsWorkerCount: 5} - agent, err := agent.NewAgent(logger.Sugar(), m, grpcClient, logStreamFunc, workflowNotificationsStreamFunc, workflowServiceNotificationsStreamFunc, "", "", featureflags.FeatureFlags{}, &proContext, "") + agent, err := agent.NewAgent(logger.Sugar(), m, grpcClient, logStreamFunc, workflowNotificationsStreamFunc, + workflowServiceNotificationsStreamFunc, workflowParallelStepNotificationsStreamFunc, "", "", featureflags.FeatureFlags{}, &proContext, "") if err != nil { t.Fatal(err) } diff --git a/pkg/agent/events_test.go b/pkg/agent/events_test.go index 1f52ea26f4..201b456015 100644 --- a/pkg/agent/events_test.go +++ b/pkg/agent/events_test.go @@ -57,9 +57,11 @@ func TestEventLoop(t *testing.T) { var logStreamFunc func(ctx context.Context, executionID string) (chan output.Output, error) var workflowNotificationsStreamFunc func(ctx context.Context, executionID string) (<-chan testkube.TestWorkflowExecutionNotification, error) var workflowServiceNotificationsStreamFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) + var workflowParallelStepNotificationsStreamFunc func(ctx context.Context, executionID, ref string, parallelStepIndexIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) proContext := config.ProContext{APIKey: "api-key", WorkerCount: 5, LogStreamWorkerCount: 5, WorkflowNotificationsWorkerCount: 5} - agent, err := agent.NewAgent(logger.Sugar(), nil, grpcClient, logStreamFunc, workflowNotificationsStreamFunc, workflowServiceNotificationsStreamFunc, "", "", featureflags.FeatureFlags{}, &proContext, "") + agent, err := agent.NewAgent(logger.Sugar(), nil, grpcClient, logStreamFunc, workflowNotificationsStreamFunc, + workflowServiceNotificationsStreamFunc, workflowParallelStepNotificationsStreamFunc, "", "", featureflags.FeatureFlags{}, &proContext, "") assert.NoError(t, err) go func() { l, err := agent.Load() diff --git a/pkg/agent/logs_test.go b/pkg/agent/logs_test.go index 59eaecf6f0..1c4ea04639 100644 --- a/pkg/agent/logs_test.go +++ b/pkg/agent/logs_test.go @@ -67,10 +67,12 @@ func TestLogStream(t *testing.T) { } var workflowNotificationsStreamFunc func(ctx context.Context, executionID string) (<-chan testkube.TestWorkflowExecutionNotification, error) var workflowServiceNotificationsStreamFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) + var workflowParallelStepNotificationsStreamFunc func(ctx context.Context, executionID, ref string, parallelStepIndexIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) logger, _ := zap.NewDevelopment() proContext := config.ProContext{APIKey: "api-key", WorkerCount: 5, LogStreamWorkerCount: 5, WorkflowNotificationsWorkerCount: 5} - agent, err := agent.NewAgent(logger.Sugar(), m, grpcClient, logStreamFunc, workflowNotificationsStreamFunc, workflowServiceNotificationsStreamFunc, "", "", featureflags.FeatureFlags{}, &proContext, "") + agent, err := agent.NewAgent(logger.Sugar(), m, grpcClient, logStreamFunc, workflowNotificationsStreamFunc, + workflowServiceNotificationsStreamFunc, workflowParallelStepNotificationsStreamFunc, "", "", featureflags.FeatureFlags{}, &proContext, "") if err != nil { t.Fatal(err) } diff --git a/pkg/cloud/service.pb.go b/pkg/cloud/service.pb.go index 5d4252ebfd..f2f3806c57 100644 --- a/pkg/cloud/service.pb.go +++ b/pkg/cloud/service.pb.go @@ -1242,6 +1242,172 @@ func (x *TestWorkflowServiceNotificationsResponse) GetMessage() string { return "" } +type TestWorkflowParallelStepNotificationsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + StreamId string `protobuf:"bytes,1,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + ExecutionId string `protobuf:"bytes,2,opt,name=execution_id,json=executionId,proto3" json:"execution_id,omitempty"` + Ref string `protobuf:"bytes,3,opt,name=ref,proto3" json:"ref,omitempty"` + ParallelStepIndex int32 `protobuf:"varint,4,opt,name=parallel_step_index,json=parallelStepIndex,proto3" json:"parallel_step_index,omitempty"` + RequestType TestWorkflowNotificationsRequestType `protobuf:"varint,5,opt,name=request_type,json=requestType,proto3,enum=cloud.TestWorkflowNotificationsRequestType" json:"request_type,omitempty"` +} + +func (x *TestWorkflowParallelStepNotificationsRequest) Reset() { + *x = TestWorkflowParallelStepNotificationsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_service_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestWorkflowParallelStepNotificationsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestWorkflowParallelStepNotificationsRequest) ProtoMessage() {} + +func (x *TestWorkflowParallelStepNotificationsRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_service_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestWorkflowParallelStepNotificationsRequest.ProtoReflect.Descriptor instead. +func (*TestWorkflowParallelStepNotificationsRequest) Descriptor() ([]byte, []int) { + return file_proto_service_proto_rawDescGZIP(), []int{16} +} + +func (x *TestWorkflowParallelStepNotificationsRequest) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *TestWorkflowParallelStepNotificationsRequest) GetExecutionId() string { + if x != nil { + return x.ExecutionId + } + return "" +} + +func (x *TestWorkflowParallelStepNotificationsRequest) GetRef() string { + if x != nil { + return x.Ref + } + return "" +} + +func (x *TestWorkflowParallelStepNotificationsRequest) GetParallelStepIndex() int32 { + if x != nil { + return x.ParallelStepIndex + } + return 0 +} + +func (x *TestWorkflowParallelStepNotificationsRequest) GetRequestType() TestWorkflowNotificationsRequestType { + if x != nil { + return x.RequestType + } + return TestWorkflowNotificationsRequestType_WORKFLOW_STREAM_LOG_MESSAGE +} + +type TestWorkflowParallelStepNotificationsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + StreamId string `protobuf:"bytes,1,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + SeqNo uint32 `protobuf:"varint,2,opt,name=seq_no,json=seqNo,proto3" json:"seq_no,omitempty"` + Timestamp string `protobuf:"bytes,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + Ref string `protobuf:"bytes,4,opt,name=ref,proto3" json:"ref,omitempty"` + Type TestWorkflowNotificationType `protobuf:"varint,5,opt,name=type,proto3,enum=cloud.TestWorkflowNotificationType" json:"type,omitempty"` + Message string `protobuf:"bytes,6,opt,name=message,proto3" json:"message,omitempty"` // based on type: log/error = inline, others = serialized to JSON +} + +func (x *TestWorkflowParallelStepNotificationsResponse) Reset() { + *x = TestWorkflowParallelStepNotificationsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_service_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TestWorkflowParallelStepNotificationsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TestWorkflowParallelStepNotificationsResponse) ProtoMessage() {} + +func (x *TestWorkflowParallelStepNotificationsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_service_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TestWorkflowParallelStepNotificationsResponse.ProtoReflect.Descriptor instead. +func (*TestWorkflowParallelStepNotificationsResponse) Descriptor() ([]byte, []int) { + return file_proto_service_proto_rawDescGZIP(), []int{17} +} + +func (x *TestWorkflowParallelStepNotificationsResponse) GetStreamId() string { + if x != nil { + return x.StreamId + } + return "" +} + +func (x *TestWorkflowParallelStepNotificationsResponse) GetSeqNo() uint32 { + if x != nil { + return x.SeqNo + } + return 0 +} + +func (x *TestWorkflowParallelStepNotificationsResponse) GetTimestamp() string { + if x != nil { + return x.Timestamp + } + return "" +} + +func (x *TestWorkflowParallelStepNotificationsResponse) GetRef() string { + if x != nil { + return x.Ref + } + return "" +} + +func (x *TestWorkflowParallelStepNotificationsResponse) GetType() TestWorkflowNotificationType { + if x != nil { + return x.Type + } + return TestWorkflowNotificationType_WORKFLOW_STREAM_ERROR +} + +func (x *TestWorkflowParallelStepNotificationsResponse) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + var File_proto_service_proto protoreflect.FileDescriptor var file_proto_service_proto_rawDesc = []byte{ @@ -1389,80 +1555,121 @@ var file_proto_service_proto_rawDesc = []byte{ 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, - 0x48, 0x0a, 0x15, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x52, 0x45, - 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x00, - 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, - 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x01, 0x2a, 0x69, 0x0a, 0x24, 0x54, 0x65, 0x73, - 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, - 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, - 0x10, 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, - 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, - 0x43, 0x4b, 0x10, 0x01, 0x2a, 0x8a, 0x01, 0x0a, 0x1c, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0x80, 0x02, 0x0a, 0x2c, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x21, 0x0a, + 0x0c, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, + 0x65, 0x66, 0x12, 0x2e, 0x0a, 0x13, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x5f, 0x73, + 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x11, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x49, 0x6e, 0x64, + 0x65, 0x78, 0x12, 0x4e, 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x22, 0xe6, 0x01, 0x0a, 0x2d, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, + 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x37, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, + 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x48, 0x0a, 0x15, 0x4c, + 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, + 0x4f, 0x47, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, + 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, + 0x45, 0x43, 0x4b, 0x10, 0x01, 0x2a, 0x69, 0x0a, 0x24, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, - 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, - 0x12, 0x17, 0x0a, 0x13, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, - 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x4f, 0x52, - 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x52, 0x45, 0x53, - 0x55, 0x4c, 0x54, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, - 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x10, - 0x03, 0x2a, 0x4c, 0x0a, 0x06, 0x4f, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x54, - 0x45, 0x58, 0x54, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x42, - 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, - 0x0c, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x03, 0x32, - 0xe6, 0x05, 0x0a, 0x10, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x43, 0x6c, 0x6f, 0x75, - 0x64, 0x41, 0x50, 0x49, 0x12, 0x3c, 0x0a, 0x07, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, - 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, - 0x30, 0x01, 0x12, 0x36, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x14, 0x2e, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x12, 0x35, 0x0a, 0x04, 0x43, 0x61, - 0x6c, 0x6c, 0x12, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, - 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x41, 0x73, 0x79, 0x6e, - 0x63, 0x12, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, - 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x28, 0x01, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x6f, - 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x1a, 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x7b, - 0x0a, 0x22, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, - 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x27, - 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x90, 0x01, 0x0a, 0x29, - 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x2f, 0x2e, 0x63, 0x6c, 0x6f, 0x75, - 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x2e, 0x2e, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x42, - 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, - 0x50, 0x72, 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, - 0x69, 0x61, 0x6c, 0x12, 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x64, - 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, 0x67, 0x2f, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, + 0x1b, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, + 0x5f, 0x4c, 0x4f, 0x47, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, 0x20, + 0x0a, 0x1c, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, + 0x4d, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x01, + 0x2a, 0x8a, 0x01, 0x0a, 0x1c, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x19, 0x0a, 0x15, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, + 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, + 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, + 0x4c, 0x4f, 0x47, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, + 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, + 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, + 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x10, 0x03, 0x2a, 0x4c, 0x0a, + 0x06, 0x4f, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x55, 0x4e, 0x53, 0x50, 0x45, + 0x43, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x45, 0x58, 0x54, 0x5f, + 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, + 0x59, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x48, 0x45, 0x41, + 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x03, 0x32, 0x88, 0x07, 0x0a, 0x10, + 0x54, 0x65, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x41, 0x50, 0x49, + 0x12, 0x3c, 0x0a, 0x07, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x63, 0x6c, + 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x1a, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x36, + 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x14, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, + 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x12, 0x35, 0x0a, 0x04, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x15, + 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, + 0x0c, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x16, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, + 0x12, 0x48, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x12, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x18, 0x2e, 0x63, + 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x7b, 0x0a, 0x22, 0x47, 0x65, + 0x74, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x12, 0x28, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x27, 0x2e, 0x63, 0x6c, 0x6f, + 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x90, 0x01, 0x0a, 0x29, 0x47, 0x65, 0x74, 0x54, + 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x2f, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, + 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x2e, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, + 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x9f, 0x01, 0x0a, 0x2e, 0x47, + 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, + 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x34, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x1a, 0x33, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, + 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, + 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0d, + 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x50, 0x72, + 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x44, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x12, 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x6c, + 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, 0x67, 0x2f, 0x63, 0x6c, + 0x6f, 0x75, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1478,69 +1685,75 @@ func file_proto_service_proto_rawDescGZIP() []byte { } var file_proto_service_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_proto_service_proto_msgTypes = make([]protoimpl.MessageInfo, 18) +var file_proto_service_proto_msgTypes = make([]protoimpl.MessageInfo, 20) var file_proto_service_proto_goTypes = []interface{}{ - (LogsStreamRequestType)(0), // 0: cloud.LogsStreamRequestType - (TestWorkflowNotificationsRequestType)(0), // 1: cloud.TestWorkflowNotificationsRequestType - (TestWorkflowNotificationType)(0), // 2: cloud.TestWorkflowNotificationType - (Opcode)(0), // 3: cloud.Opcode - (*LogsStreamRequest)(nil), // 4: cloud.LogsStreamRequest - (*LogsStreamResponse)(nil), // 5: cloud.LogsStreamResponse - (*CommandRequest)(nil), // 6: cloud.CommandRequest - (*CommandResponse)(nil), // 7: cloud.CommandResponse - (*ExecuteRequest)(nil), // 8: cloud.ExecuteRequest - (*TestWorkflowNotificationsRequest)(nil), // 9: cloud.TestWorkflowNotificationsRequest - (*TestWorkflowNotificationsResponse)(nil), // 10: cloud.TestWorkflowNotificationsResponse - (*ProContextResponse)(nil), // 11: cloud.ProContextResponse - (*Capability)(nil), // 12: cloud.Capability - (*HeaderValue)(nil), // 13: cloud.HeaderValue - (*ExecuteResponse)(nil), // 14: cloud.ExecuteResponse - (*WebsocketData)(nil), // 15: cloud.WebsocketData - (*CredentialRequest)(nil), // 16: cloud.CredentialRequest - (*CredentialResponse)(nil), // 17: cloud.CredentialResponse - (*TestWorkflowServiceNotificationsRequest)(nil), // 18: cloud.TestWorkflowServiceNotificationsRequest - (*TestWorkflowServiceNotificationsResponse)(nil), // 19: cloud.TestWorkflowServiceNotificationsResponse - nil, // 20: cloud.ExecuteRequest.HeadersEntry - nil, // 21: cloud.ExecuteResponse.HeadersEntry - (*structpb.Struct)(nil), // 22: google.protobuf.Struct - (*emptypb.Empty)(nil), // 23: google.protobuf.Empty + (LogsStreamRequestType)(0), // 0: cloud.LogsStreamRequestType + (TestWorkflowNotificationsRequestType)(0), // 1: cloud.TestWorkflowNotificationsRequestType + (TestWorkflowNotificationType)(0), // 2: cloud.TestWorkflowNotificationType + (Opcode)(0), // 3: cloud.Opcode + (*LogsStreamRequest)(nil), // 4: cloud.LogsStreamRequest + (*LogsStreamResponse)(nil), // 5: cloud.LogsStreamResponse + (*CommandRequest)(nil), // 6: cloud.CommandRequest + (*CommandResponse)(nil), // 7: cloud.CommandResponse + (*ExecuteRequest)(nil), // 8: cloud.ExecuteRequest + (*TestWorkflowNotificationsRequest)(nil), // 9: cloud.TestWorkflowNotificationsRequest + (*TestWorkflowNotificationsResponse)(nil), // 10: cloud.TestWorkflowNotificationsResponse + (*ProContextResponse)(nil), // 11: cloud.ProContextResponse + (*Capability)(nil), // 12: cloud.Capability + (*HeaderValue)(nil), // 13: cloud.HeaderValue + (*ExecuteResponse)(nil), // 14: cloud.ExecuteResponse + (*WebsocketData)(nil), // 15: cloud.WebsocketData + (*CredentialRequest)(nil), // 16: cloud.CredentialRequest + (*CredentialResponse)(nil), // 17: cloud.CredentialResponse + (*TestWorkflowServiceNotificationsRequest)(nil), // 18: cloud.TestWorkflowServiceNotificationsRequest + (*TestWorkflowServiceNotificationsResponse)(nil), // 19: cloud.TestWorkflowServiceNotificationsResponse + (*TestWorkflowParallelStepNotificationsRequest)(nil), // 20: cloud.TestWorkflowParallelStepNotificationsRequest + (*TestWorkflowParallelStepNotificationsResponse)(nil), // 21: cloud.TestWorkflowParallelStepNotificationsResponse + nil, // 22: cloud.ExecuteRequest.HeadersEntry + nil, // 23: cloud.ExecuteResponse.HeadersEntry + (*structpb.Struct)(nil), // 24: google.protobuf.Struct + (*emptypb.Empty)(nil), // 25: google.protobuf.Empty } var file_proto_service_proto_depIdxs = []int32{ 0, // 0: cloud.LogsStreamRequest.request_type:type_name -> cloud.LogsStreamRequestType - 22, // 1: cloud.CommandRequest.payload:type_name -> google.protobuf.Struct - 20, // 2: cloud.ExecuteRequest.headers:type_name -> cloud.ExecuteRequest.HeadersEntry + 24, // 1: cloud.CommandRequest.payload:type_name -> google.protobuf.Struct + 22, // 2: cloud.ExecuteRequest.headers:type_name -> cloud.ExecuteRequest.HeadersEntry 1, // 3: cloud.TestWorkflowNotificationsRequest.request_type:type_name -> cloud.TestWorkflowNotificationsRequestType 2, // 4: cloud.TestWorkflowNotificationsResponse.type:type_name -> cloud.TestWorkflowNotificationType 12, // 5: cloud.ProContextResponse.capabilities:type_name -> cloud.Capability - 21, // 6: cloud.ExecuteResponse.headers:type_name -> cloud.ExecuteResponse.HeadersEntry + 23, // 6: cloud.ExecuteResponse.headers:type_name -> cloud.ExecuteResponse.HeadersEntry 3, // 7: cloud.WebsocketData.opcode:type_name -> cloud.Opcode 1, // 8: cloud.TestWorkflowServiceNotificationsRequest.request_type:type_name -> cloud.TestWorkflowNotificationsRequestType 2, // 9: cloud.TestWorkflowServiceNotificationsResponse.type:type_name -> cloud.TestWorkflowNotificationType - 13, // 10: cloud.ExecuteRequest.HeadersEntry.value:type_name -> cloud.HeaderValue - 13, // 11: cloud.ExecuteResponse.HeadersEntry.value:type_name -> cloud.HeaderValue - 14, // 12: cloud.TestKubeCloudAPI.Execute:input_type -> cloud.ExecuteResponse - 15, // 13: cloud.TestKubeCloudAPI.Send:input_type -> cloud.WebsocketData - 6, // 14: cloud.TestKubeCloudAPI.Call:input_type -> cloud.CommandRequest - 14, // 15: cloud.TestKubeCloudAPI.ExecuteAsync:input_type -> cloud.ExecuteResponse - 5, // 16: cloud.TestKubeCloudAPI.GetLogsStream:input_type -> cloud.LogsStreamResponse - 10, // 17: cloud.TestKubeCloudAPI.GetTestWorkflowNotificationsStream:input_type -> cloud.TestWorkflowNotificationsResponse - 19, // 18: cloud.TestKubeCloudAPI.GetTestWorkflowServiceNotificationsStream:input_type -> cloud.TestWorkflowServiceNotificationsResponse - 23, // 19: cloud.TestKubeCloudAPI.GetProContext:input_type -> google.protobuf.Empty - 16, // 20: cloud.TestKubeCloudAPI.GetCredential:input_type -> cloud.CredentialRequest - 8, // 21: cloud.TestKubeCloudAPI.Execute:output_type -> cloud.ExecuteRequest - 23, // 22: cloud.TestKubeCloudAPI.Send:output_type -> google.protobuf.Empty - 7, // 23: cloud.TestKubeCloudAPI.Call:output_type -> cloud.CommandResponse - 8, // 24: cloud.TestKubeCloudAPI.ExecuteAsync:output_type -> cloud.ExecuteRequest - 4, // 25: cloud.TestKubeCloudAPI.GetLogsStream:output_type -> cloud.LogsStreamRequest - 9, // 26: cloud.TestKubeCloudAPI.GetTestWorkflowNotificationsStream:output_type -> cloud.TestWorkflowNotificationsRequest - 18, // 27: cloud.TestKubeCloudAPI.GetTestWorkflowServiceNotificationsStream:output_type -> cloud.TestWorkflowServiceNotificationsRequest - 11, // 28: cloud.TestKubeCloudAPI.GetProContext:output_type -> cloud.ProContextResponse - 17, // 29: cloud.TestKubeCloudAPI.GetCredential:output_type -> cloud.CredentialResponse - 21, // [21:30] is the sub-list for method output_type - 12, // [12:21] is the sub-list for method input_type - 12, // [12:12] is the sub-list for extension type_name - 12, // [12:12] is the sub-list for extension extendee - 0, // [0:12] is the sub-list for field type_name + 1, // 10: cloud.TestWorkflowParallelStepNotificationsRequest.request_type:type_name -> cloud.TestWorkflowNotificationsRequestType + 2, // 11: cloud.TestWorkflowParallelStepNotificationsResponse.type:type_name -> cloud.TestWorkflowNotificationType + 13, // 12: cloud.ExecuteRequest.HeadersEntry.value:type_name -> cloud.HeaderValue + 13, // 13: cloud.ExecuteResponse.HeadersEntry.value:type_name -> cloud.HeaderValue + 14, // 14: cloud.TestKubeCloudAPI.Execute:input_type -> cloud.ExecuteResponse + 15, // 15: cloud.TestKubeCloudAPI.Send:input_type -> cloud.WebsocketData + 6, // 16: cloud.TestKubeCloudAPI.Call:input_type -> cloud.CommandRequest + 14, // 17: cloud.TestKubeCloudAPI.ExecuteAsync:input_type -> cloud.ExecuteResponse + 5, // 18: cloud.TestKubeCloudAPI.GetLogsStream:input_type -> cloud.LogsStreamResponse + 10, // 19: cloud.TestKubeCloudAPI.GetTestWorkflowNotificationsStream:input_type -> cloud.TestWorkflowNotificationsResponse + 19, // 20: cloud.TestKubeCloudAPI.GetTestWorkflowServiceNotificationsStream:input_type -> cloud.TestWorkflowServiceNotificationsResponse + 21, // 21: cloud.TestKubeCloudAPI.GetTestWorkflowParallelStepNotificationsStream:input_type -> cloud.TestWorkflowParallelStepNotificationsResponse + 25, // 22: cloud.TestKubeCloudAPI.GetProContext:input_type -> google.protobuf.Empty + 16, // 23: cloud.TestKubeCloudAPI.GetCredential:input_type -> cloud.CredentialRequest + 8, // 24: cloud.TestKubeCloudAPI.Execute:output_type -> cloud.ExecuteRequest + 25, // 25: cloud.TestKubeCloudAPI.Send:output_type -> google.protobuf.Empty + 7, // 26: cloud.TestKubeCloudAPI.Call:output_type -> cloud.CommandResponse + 8, // 27: cloud.TestKubeCloudAPI.ExecuteAsync:output_type -> cloud.ExecuteRequest + 4, // 28: cloud.TestKubeCloudAPI.GetLogsStream:output_type -> cloud.LogsStreamRequest + 9, // 29: cloud.TestKubeCloudAPI.GetTestWorkflowNotificationsStream:output_type -> cloud.TestWorkflowNotificationsRequest + 18, // 30: cloud.TestKubeCloudAPI.GetTestWorkflowServiceNotificationsStream:output_type -> cloud.TestWorkflowServiceNotificationsRequest + 20, // 31: cloud.TestKubeCloudAPI.GetTestWorkflowParallelStepNotificationsStream:output_type -> cloud.TestWorkflowParallelStepNotificationsRequest + 11, // 32: cloud.TestKubeCloudAPI.GetProContext:output_type -> cloud.ProContextResponse + 17, // 33: cloud.TestKubeCloudAPI.GetCredential:output_type -> cloud.CredentialResponse + 24, // [24:34] is the sub-list for method output_type + 14, // [14:24] is the sub-list for method input_type + 14, // [14:14] is the sub-list for extension type_name + 14, // [14:14] is the sub-list for extension extendee + 0, // [0:14] is the sub-list for field type_name } func init() { file_proto_service_proto_init() } @@ -1741,6 +1954,30 @@ func file_proto_service_proto_init() { return nil } } + file_proto_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestWorkflowParallelStepNotificationsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TestWorkflowParallelStepNotificationsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1748,7 +1985,7 @@ func file_proto_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_service_proto_rawDesc, NumEnums: 4, - NumMessages: 18, + NumMessages: 20, NumExtensions: 0, NumServices: 1, }, diff --git a/pkg/cloud/service_grpc.pb.go b/pkg/cloud/service_grpc.pb.go index 01464de17a..7efe768671 100644 --- a/pkg/cloud/service_grpc.pb.go +++ b/pkg/cloud/service_grpc.pb.go @@ -32,6 +32,7 @@ type TestKubeCloudAPIClient interface { GetLogsStream(ctx context.Context, opts ...grpc.CallOption) (TestKubeCloudAPI_GetLogsStreamClient, error) GetTestWorkflowNotificationsStream(ctx context.Context, opts ...grpc.CallOption) (TestKubeCloudAPI_GetTestWorkflowNotificationsStreamClient, error) GetTestWorkflowServiceNotificationsStream(ctx context.Context, opts ...grpc.CallOption) (TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamClient, error) + GetTestWorkflowParallelStepNotificationsStream(ctx context.Context, opts ...grpc.CallOption) (TestKubeCloudAPI_GetTestWorkflowParallelStepNotificationsStreamClient, error) GetProContext(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ProContextResponse, error) GetCredential(ctx context.Context, in *CredentialRequest, opts ...grpc.CallOption) (*CredentialResponse, error) } @@ -242,6 +243,37 @@ func (x *testKubeCloudAPIGetTestWorkflowServiceNotificationsStreamClient) Recv() return m, nil } +func (c *testKubeCloudAPIClient) GetTestWorkflowParallelStepNotificationsStream(ctx context.Context, opts ...grpc.CallOption) (TestKubeCloudAPI_GetTestWorkflowParallelStepNotificationsStreamClient, error) { + stream, err := c.cc.NewStream(ctx, &TestKubeCloudAPI_ServiceDesc.Streams[6], "/cloud.TestKubeCloudAPI/GetTestWorkflowParallelStepNotificationsStream", opts...) + if err != nil { + return nil, err + } + x := &testKubeCloudAPIGetTestWorkflowParallelStepNotificationsStreamClient{stream} + return x, nil +} + +type TestKubeCloudAPI_GetTestWorkflowParallelStepNotificationsStreamClient interface { + Send(*TestWorkflowParallelStepNotificationsResponse) error + Recv() (*TestWorkflowParallelStepNotificationsRequest, error) + grpc.ClientStream +} + +type testKubeCloudAPIGetTestWorkflowParallelStepNotificationsStreamClient struct { + grpc.ClientStream +} + +func (x *testKubeCloudAPIGetTestWorkflowParallelStepNotificationsStreamClient) Send(m *TestWorkflowParallelStepNotificationsResponse) error { + return x.ClientStream.SendMsg(m) +} + +func (x *testKubeCloudAPIGetTestWorkflowParallelStepNotificationsStreamClient) Recv() (*TestWorkflowParallelStepNotificationsRequest, error) { + m := new(TestWorkflowParallelStepNotificationsRequest) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func (c *testKubeCloudAPIClient) GetProContext(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ProContextResponse, error) { out := new(ProContextResponse) err := c.cc.Invoke(ctx, "/cloud.TestKubeCloudAPI/GetProContext", in, out, opts...) @@ -273,6 +305,7 @@ type TestKubeCloudAPIServer interface { GetLogsStream(TestKubeCloudAPI_GetLogsStreamServer) error GetTestWorkflowNotificationsStream(TestKubeCloudAPI_GetTestWorkflowNotificationsStreamServer) error GetTestWorkflowServiceNotificationsStream(TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamServer) error + GetTestWorkflowParallelStepNotificationsStream(TestKubeCloudAPI_GetTestWorkflowParallelStepNotificationsStreamServer) error GetProContext(context.Context, *emptypb.Empty) (*ProContextResponse, error) GetCredential(context.Context, *CredentialRequest) (*CredentialResponse, error) mustEmbedUnimplementedTestKubeCloudAPIServer() @@ -303,6 +336,9 @@ func (UnimplementedTestKubeCloudAPIServer) GetTestWorkflowNotificationsStream(Te func (UnimplementedTestKubeCloudAPIServer) GetTestWorkflowServiceNotificationsStream(TestKubeCloudAPI_GetTestWorkflowServiceNotificationsStreamServer) error { return status.Errorf(codes.Unimplemented, "method GetTestWorkflowServiceNotificationsStream not implemented") } +func (UnimplementedTestKubeCloudAPIServer) GetTestWorkflowParallelStepNotificationsStream(TestKubeCloudAPI_GetTestWorkflowParallelStepNotificationsStreamServer) error { + return status.Errorf(codes.Unimplemented, "method GetTestWorkflowParallelStepNotificationsStream not implemented") +} func (UnimplementedTestKubeCloudAPIServer) GetProContext(context.Context, *emptypb.Empty) (*ProContextResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetProContext not implemented") } @@ -496,6 +532,32 @@ func (x *testKubeCloudAPIGetTestWorkflowServiceNotificationsStreamServer) Recv() return m, nil } +func _TestKubeCloudAPI_GetTestWorkflowParallelStepNotificationsStream_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(TestKubeCloudAPIServer).GetTestWorkflowParallelStepNotificationsStream(&testKubeCloudAPIGetTestWorkflowParallelStepNotificationsStreamServer{stream}) +} + +type TestKubeCloudAPI_GetTestWorkflowParallelStepNotificationsStreamServer interface { + Send(*TestWorkflowParallelStepNotificationsRequest) error + Recv() (*TestWorkflowParallelStepNotificationsResponse, error) + grpc.ServerStream +} + +type testKubeCloudAPIGetTestWorkflowParallelStepNotificationsStreamServer struct { + grpc.ServerStream +} + +func (x *testKubeCloudAPIGetTestWorkflowParallelStepNotificationsStreamServer) Send(m *TestWorkflowParallelStepNotificationsRequest) error { + return x.ServerStream.SendMsg(m) +} + +func (x *testKubeCloudAPIGetTestWorkflowParallelStepNotificationsStreamServer) Recv() (*TestWorkflowParallelStepNotificationsResponse, error) { + m := new(TestWorkflowParallelStepNotificationsResponse) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + func _TestKubeCloudAPI_GetProContext_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(emptypb.Empty) if err := dec(in); err != nil { @@ -588,6 +650,12 @@ var TestKubeCloudAPI_ServiceDesc = grpc.ServiceDesc{ ServerStreams: true, ClientStreams: true, }, + { + StreamName: "GetTestWorkflowParallelStepNotificationsStream", + Handler: _TestKubeCloudAPI_GetTestWorkflowParallelStepNotificationsStream_Handler, + ServerStreams: true, + ClientStreams: true, + }, }, Metadata: "proto/service.proto", } diff --git a/proto/service.proto b/proto/service.proto index 9d56e88d6c..b13c0acafc 100644 --- a/proto/service.proto +++ b/proto/service.proto @@ -17,6 +17,7 @@ service TestKubeCloudAPI { rpc GetLogsStream(stream LogsStreamResponse) returns (stream LogsStreamRequest); rpc GetTestWorkflowNotificationsStream(stream TestWorkflowNotificationsResponse) returns (stream TestWorkflowNotificationsRequest); rpc GetTestWorkflowServiceNotificationsStream(stream TestWorkflowServiceNotificationsResponse) returns (stream TestWorkflowServiceNotificationsRequest); + rpc GetTestWorkflowParallelStepNotificationsStream(stream TestWorkflowParallelStepNotificationsResponse) returns (stream TestWorkflowParallelStepNotificationsRequest); rpc GetProContext(google.protobuf.Empty) returns (ProContextResponse); rpc GetCredential(CredentialRequest) returns (CredentialResponse); } @@ -142,3 +143,20 @@ message TestWorkflowServiceNotificationsResponse { TestWorkflowNotificationType type = 5; string message = 6; // based on type: log/error = inline, others = serialized to JSON } + +message TestWorkflowParallelStepNotificationsRequest { + string stream_id = 1; + string execution_id = 2; + string ref = 3; + int32 parallel_step_index = 4; + TestWorkflowNotificationsRequestType request_type = 5; +} + +message TestWorkflowParallelStepNotificationsResponse { + string stream_id = 1; + uint32 seq_no = 2; + string timestamp = 3; + string ref = 4; + TestWorkflowNotificationType type = 5; + string message = 6; // based on type: log/error = inline, others = serialized to JSON +} From bfdc72fc477eb296924ccd14e3e77b7cf49d7767 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Tue, 3 Dec 2024 13:54:21 +0300 Subject: [PATCH 34/40] fix: lint Signed-off-by: Vladislav Sukhin --- pkg/agent/agent.go | 13 ++++++++----- pkg/agent/agent_test.go | 6 ++++++ pkg/agent/events_test.go | 6 ++++++ pkg/agent/logs_test.go | 5 +++++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/pkg/agent/agent.go b/pkg/agent/agent.go index 45b8a40e56..59de74f63c 100644 --- a/pkg/agent/agent.go +++ b/pkg/agent/agent.go @@ -111,11 +111,14 @@ func NewAgent(logger *zap.SugaredLogger, testWorkflowNotificationsRequestBuffer: make(chan *cloud.TestWorkflowNotificationsRequest, bufferSizePerWorker*proContext.WorkflowNotificationsWorkerCount), testWorkflowNotificationsResponseBuffer: make(chan *cloud.TestWorkflowNotificationsResponse, bufferSizePerWorker*proContext.WorkflowNotificationsWorkerCount), testWorkflowNotificationsFunc: workflowNotificationsFunc, - testWorkflowServiceNotificationsWorkerCount: proContext.WorkflowServiceNotificationsWorkerCount, - testWorkflowServiceNotificationsRequestBuffer: make(chan *cloud.TestWorkflowServiceNotificationsRequest, bufferSizePerWorker*proContext.WorkflowServiceNotificationsWorkerCount), - testWorkflowServiceNotificationsResponseBuffer: make(chan *cloud.TestWorkflowServiceNotificationsResponse, bufferSizePerWorker*proContext.WorkflowServiceNotificationsWorkerCount), - testWorkflowServiceNotificationsFunc: workflowServiceNotificationsFunc, - + testWorkflowServiceNotificationsWorkerCount: proContext.WorkflowServiceNotificationsWorkerCount, + testWorkflowServiceNotificationsRequestBuffer: make(chan *cloud.TestWorkflowServiceNotificationsRequest, bufferSizePerWorker*proContext.WorkflowServiceNotificationsWorkerCount), + testWorkflowServiceNotificationsResponseBuffer: make(chan *cloud.TestWorkflowServiceNotificationsResponse, bufferSizePerWorker*proContext.WorkflowServiceNotificationsWorkerCount), + testWorkflowServiceNotificationsFunc: workflowServiceNotificationsFunc, + testWorkflowParallelStepNotificationsWorkerCount: proContext.WorkflowParallelStepNotificationsWorkerCount, + testWorkflowParallelStepNotificationsRequestBuffer: make(chan *cloud.TestWorkflowParallelStepNotificationsRequest, bufferSizePerWorker*proContext.WorkflowParallelStepNotificationsWorkerCount), + testWorkflowParallelStepNotificationsResponseBuffer: make(chan *cloud.TestWorkflowParallelStepNotificationsResponse, bufferSizePerWorker*proContext.WorkflowParallelStepNotificationsWorkerCount), + testWorkflowParallelStepNotificationsFunc: workflowParallelStepNotificationsFunc, clusterID: clusterID, clusterName: clusterName, features: features, diff --git a/pkg/agent/agent_test.go b/pkg/agent/agent_test.go index 4b4936dd6c..8cc2301fa0 100644 --- a/pkg/agent/agent_test.go +++ b/pkg/agent/agent_test.go @@ -106,6 +106,12 @@ func (cs *CloudServer) GetTestWorkflowServiceNotificationsStream(srv cloud.TestK return nil } +func (cs *CloudServer) GetTestWorkflowParallelStepNotificationsStream(srv cloud.TestKubeCloudAPI_GetTestWorkflowParallelStepNotificationsStreamServer) error { + <-cs.ctx.Done() + + return nil +} + func (cs *CloudServer) ExecuteAsync(srv cloud.TestKubeCloudAPI_ExecuteAsyncServer) error { md, ok := metadata.FromIncomingContext(srv.Context()) if !ok { diff --git a/pkg/agent/events_test.go b/pkg/agent/events_test.go index 201b456015..ff08dbd462 100644 --- a/pkg/agent/events_test.go +++ b/pkg/agent/events_test.go @@ -119,6 +119,12 @@ func (cws *CloudEventServer) GetTestWorkflowServiceNotificationsStream(srv cloud return nil } +func (cws *CloudEventServer) GetTestWorkflowParallelStepNotificationsStream(srv cloud.TestKubeCloudAPI_GetTestWorkflowParallelStepNotificationsStreamServer) error { + <-cws.ctx.Done() + + return nil +} + func (cws *CloudEventServer) Send(srv cloud.TestKubeCloudAPI_SendServer) error { md, ok := metadata.FromIncomingContext(srv.Context()) if !ok { diff --git a/pkg/agent/logs_test.go b/pkg/agent/logs_test.go index 1c4ea04639..7f27bccbbf 100644 --- a/pkg/agent/logs_test.go +++ b/pkg/agent/logs_test.go @@ -110,6 +110,11 @@ func (cs *CloudLogsServer) GetTestWorkflowServiceNotificationsStream(srv cloud.T return nil } +func (cs *CloudLogsServer) GetTestWorkflowParallelStepNotificationsStream(srv cloud.TestKubeCloudAPI_GetTestWorkflowParallelStepNotificationsStreamServer) error { + <-cs.ctx.Done() + return nil +} + func (cs *CloudLogsServer) GetLogsStream(srv cloud.TestKubeCloudAPI_GetLogsStreamServer) error { md, ok := metadata.FromIncomingContext(srv.Context()) if !ok { From ce5215f36f0bab39b32e02df153274c0b06964da Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Tue, 3 Dec 2024 14:25:03 +0300 Subject: [PATCH 35/40] add: grpc method for parallel steps Signed-off-by: Vladislav Sukhin --- pkg/agent/agent.go | 7 ++ pkg/agent/testworkflows.go | 192 +++++++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) diff --git a/pkg/agent/agent.go b/pkg/agent/agent.go index 59de74f63c..142b477087 100644 --- a/pkg/agent/agent.go +++ b/pkg/agent/agent.go @@ -178,6 +178,13 @@ func (ag *Agent) run(ctx context.Context) (err error) { return ag.runTestWorkflowServiceNotificationsWorker(groupCtx, ag.testWorkflowServiceNotificationsWorkerCount) }) + g.Go(func() error { + return ag.runTestWorkflowParallelStepNotificationsLoop(groupCtx) + }) + g.Go(func() error { + return ag.runTestWorkflowParallelStepNotificationsWorker(groupCtx, ag.testWorkflowParallelStepNotificationsWorkerCount) + }) + err = g.Wait() return err diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index 3a1ce2f54b..6f20343f95 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -125,6 +125,51 @@ func (ag *Agent) runTestWorkflowServiceNotificationsLoop(ctx context.Context) er return err } +func (ag *Agent) runTestWorkflowParallelStepNotificationsLoop(ctx context.Context) error { + ctx = agentclient.AddAPIKeyMeta(ctx, ag.apiKey) + + ag.logger.Infow("initiating workflow parallel step notifications streaming connection with Cloud API") + // creates a new Stream from the client side. ctx is used for the lifetime of the stream. + opts := []grpc.CallOption{grpc.UseCompressor(gzip.Name), grpc.MaxCallRecvMsgSize(math.MaxInt32)} + stream, err := ag.client.GetTestWorkflowParallelStepNotificationsStream(ctx, opts...) + if err != nil { + ag.logger.Errorf("failed to execute: %w", err) + return errors.Wrap(err, "failed to setup stream") + } + + // GRPC stream have special requirements for concurrency on SendMsg, and RecvMsg calls. + // Please check https://github.com/grpc/grpc-go/blob/master/Documentation/concurrency.md + g, groupCtx := errgroup.WithContext(ctx) + g.Go(func() error { + for { + cmd, err := ag.receiveTestWorkflowParallelStepNotificationsRequest(groupCtx, stream) + if err != nil { + return err + } + + ag.testWorkflowParallelStepNotificationsRequestBuffer <- cmd + } + }) + + g.Go(func() error { + for { + select { + case resp := <-ag.testWorkflowParallelStepNotificationsResponseBuffer: + err := ag.sendTestWorkflowParallelStepNotificationsResponse(groupCtx, stream, resp) + if err != nil { + return err + } + case <-groupCtx.Done(): + return groupCtx.Err() + } + } + }) + + err = g.Wait() + + return err +} + func (ag *Agent) runTestWorkflowNotificationsWorker(ctx context.Context, numWorkers int) error { g, groupCtx := errgroup.WithContext(ctx) for i := 0; i < numWorkers; i++ { @@ -181,6 +226,34 @@ func (ag *Agent) runTestWorkflowServiceNotificationsWorker(ctx context.Context, return g.Wait() } +func (ag *Agent) runTestWorkflowParallelStepNotificationsWorker(ctx context.Context, numWorkers int) error { + g, groupCtx := errgroup.WithContext(ctx) + for i := 0; i < numWorkers; i++ { + g.Go(func() error { + for { + select { + case req := <-ag.testWorkflowParallelStepNotificationsRequestBuffer: + if req.RequestType == cloud.TestWorkflowNotificationsRequestType_WORKFLOW_STREAM_HEALTH_CHECK { + ag.testWorkflowParallelStepNotificationsResponseBuffer <- &cloud.TestWorkflowParallelStepNotificationsResponse{ + StreamId: req.StreamId, + SeqNo: 0, + } + break + } + + err := ag.executeWorkflowParallelStepNotificationsRequest(groupCtx, req) + if err != nil { + ag.logger.Errorf("error executing workflow parallel step notifications request: %s", err.Error()) + } + case <-groupCtx.Done(): + return groupCtx.Err() + } + } + }) + } + return g.Wait() +} + func (ag *Agent) executeWorkflowNotificationsRequest(ctx context.Context, req *cloud.TestWorkflowNotificationsRequest) error { notificationsCh, err := ag.testWorkflowNotificationsFunc(ctx, req.ExecutionId) for i := 0; i < testWorkflowNotificationsRetryCount; i++ { @@ -306,6 +379,71 @@ func (ag *Agent) executeWorkflowServiceNotificationsRequest(ctx context.Context, } } +func (ag *Agent) executeWorkflowParallelStepNotificationsRequest(ctx context.Context, req *cloud.TestWorkflowParallelStepNotificationsRequest) error { + notificationsCh, err := retry.DoWithData( + func() (<-chan testkube.TestWorkflowExecutionNotification, error) { + // We have a race condition here + // Cloud sometimes slow to start service + // while WorkflowNotifications request from websockets comes in faster + // so we retry up to wait till service pod is uo or execution is finished. + return ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.Ref, int(req.ParallelStepIndex)) + }, + retry.DelayType(retry.FixedDelay), + retry.Delay(logRetryDelay), + retry.RetryIf(func(err error) bool { + return errors.Is(err, registry.ErrResourceNotFound) + }), + retry.UntilSucceeded(), + ) + + if err != nil { + message := fmt.Sprintf("cannot get service pod logs: %s", err.Error()) + ag.testWorkflowParallelStepNotificationsResponseBuffer <- &cloud.TestWorkflowParallelStepNotificationsResponse{ + StreamId: req.StreamId, + SeqNo: 0, + Type: cloud.TestWorkflowNotificationType_WORKFLOW_STREAM_ERROR, + Message: fmt.Sprintf("%s %s", time.Now().Format(controller.KubernetesLogTimeFormat), message), + } + return nil + } + + for { + var i uint32 + select { + case n, ok := <-notificationsCh: + if !ok { + return nil + } + t := getTestWorkflowNotificationType(n) + msg := &cloud.TestWorkflowParallelStepNotificationsResponse{ + StreamId: req.StreamId, + SeqNo: i, + Timestamp: n.Ts.Format(time.RFC3339Nano), + Ref: n.Ref, + Type: t, + } + if n.Result != nil { + m, _ := json.Marshal(n.Result) + msg.Message = string(m) + } else if n.Output != nil { + m, _ := json.Marshal(n.Output) + msg.Message = string(m) + } else { + msg.Message = n.Log + } + i++ + + select { + case ag.testWorkflowParallelStepNotificationsResponseBuffer <- msg: + case <-ctx.Done(): + return ctx.Err() + } + case <-ctx.Done(): + return ctx.Err() + } + } +} + func (ag *Agent) receiveTestWorkflowNotificationsRequest(ctx context.Context, stream cloud.TestKubeCloudAPI_GetTestWorkflowNotificationsStreamClient) (*cloud.TestWorkflowNotificationsRequest, error) { respChan := make(chan testWorkflowNotificationsRequest, 1) go func() { @@ -364,6 +502,35 @@ type testWorkflowServiceNotificationsRequest struct { err error } +func (ag *Agent) receiveTestWorkflowParallelStepNotificationsRequest(ctx context.Context, stream cloud.TestKubeCloudAPI_GetTestWorkflowParallelStepNotificationsStreamClient) (*cloud.TestWorkflowParallelStepNotificationsRequest, error) { + respChan := make(chan testWorkflowParallelStepNotificationsRequest, 1) + go func() { + cmd, err := stream.Recv() + respChan <- testWorkflowParallelStepNotificationsRequest{resp: cmd, err: err} + }() + + var cmd *cloud.TestWorkflowParallelStepNotificationsRequest + select { + case resp := <-respChan: + cmd = resp.resp + err := resp.err + + if err != nil { + ag.logger.Errorf("agent stream receive: %v", err) + return nil, err + } + case <-ctx.Done(): + return nil, ctx.Err() + } + + return cmd, nil +} + +type testWorkflowParallelStepNotificationsRequest struct { + resp *cloud.TestWorkflowParallelStepNotificationsRequest + err error +} + func (ag *Agent) sendTestWorkflowNotificationsResponse(ctx context.Context, stream cloud.TestKubeCloudAPI_GetTestWorkflowNotificationsStreamClient, resp *cloud.TestWorkflowNotificationsResponse) error { errChan := make(chan error, 1) go func() { @@ -413,3 +580,28 @@ func (ag *Agent) sendTestWorkflowServiceNotificationsResponse(ctx context.Contex return errors.New("send response too slow") } } + +func (ag *Agent) sendTestWorkflowParallelStepNotificationsResponse(ctx context.Context, stream cloud.TestKubeCloudAPI_GetTestWorkflowParallelStepNotificationsStreamClient, resp *cloud.TestWorkflowParallelStepNotificationsResponse) error { + errChan := make(chan error, 1) + go func() { + errChan <- stream.Send(resp) + close(errChan) + }() + + t := time.NewTimer(ag.sendTimeout) + select { + case err := <-errChan: + if !t.Stop() { + <-t.C + } + return err + case <-ctx.Done(): + if !t.Stop() { + <-t.C + } + + return ctx.Err() + case <-t.C: + return errors.New("send response too slow") + } +} From fdffbc91985a39191c1a83e8098469ebca0a52a5 Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Tue, 3 Dec 2024 14:27:16 +0300 Subject: [PATCH 36/40] fix: comments Signed-off-by: Vladislav Sukhin --- pkg/agent/testworkflows.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index 6f20343f95..c11cdeeb7a 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -383,9 +383,9 @@ func (ag *Agent) executeWorkflowParallelStepNotificationsRequest(ctx context.Con notificationsCh, err := retry.DoWithData( func() (<-chan testkube.TestWorkflowExecutionNotification, error) { // We have a race condition here - // Cloud sometimes slow to start service + // Cloud sometimes slow to start parallel step // while WorkflowNotifications request from websockets comes in faster - // so we retry up to wait till service pod is uo or execution is finished. + // so we retry up to wait till parallel step pod is uo or execution is finished. return ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.Ref, int(req.ParallelStepIndex)) }, retry.DelayType(retry.FixedDelay), From 38379b42652f9ef03870127a2ef8ced081901d3b Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Tue, 3 Dec 2024 14:29:00 +0300 Subject: [PATCH 37/40] fix: comments Signed-off-by: Vladislav Sukhin --- pkg/agent/testworkflows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index c11cdeeb7a..4e13ee0178 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -397,7 +397,7 @@ func (ag *Agent) executeWorkflowParallelStepNotificationsRequest(ctx context.Con ) if err != nil { - message := fmt.Sprintf("cannot get service pod logs: %s", err.Error()) + message := fmt.Sprintf("cannot get parallel step pod logs: %s", err.Error()) ag.testWorkflowParallelStepNotificationsResponseBuffer <- &cloud.TestWorkflowParallelStepNotificationsResponse{ StreamId: req.StreamId, SeqNo: 0, From 8a7f8cb8ef9c14852bf6488ba731abae97a0778e Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Tue, 3 Dec 2024 17:09:14 +0300 Subject: [PATCH 38/40] fix: typo Signed-off-by: Vladislav Sukhin --- pkg/agent/testworkflows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index 4e13ee0178..b65d20954c 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -386,7 +386,7 @@ func (ag *Agent) executeWorkflowParallelStepNotificationsRequest(ctx context.Con // Cloud sometimes slow to start parallel step // while WorkflowNotifications request from websockets comes in faster // so we retry up to wait till parallel step pod is uo or execution is finished. - return ag.testWorkflowServiceNotificationsFunc(ctx, req.ExecutionId, req.Ref, int(req.ParallelStepIndex)) + return ag.testWorkflowParallelStepNotificationsFunc(ctx, req.ExecutionId, req.Ref, int(req.ParallelStepIndex)) }, retry.DelayType(retry.FixedDelay), retry.Delay(logRetryDelay), From 097fb7da994a88b648c7c0e008981e986d183aad Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Tue, 3 Dec 2024 19:31:17 +0300 Subject: [PATCH 39/40] fix: change proto Signed-off-by: Vladislav Sukhin --- cmd/api-server/main.go | 7 +- pkg/agent/agent.go | 2 +- pkg/agent/testworkflows.go | 2 +- pkg/cloud/service.pb.go | 220 +++++++++++++++++++------------------ proto/service.proto | 2 +- 5 files changed, 120 insertions(+), 113 deletions(-) diff --git a/cmd/api-server/main.go b/cmd/api-server/main.go index 4ea389ae3f..a7430f5e01 100644 --- a/cmd/api-server/main.go +++ b/cmd/api-server/main.go @@ -346,7 +346,7 @@ func main() { } return notifications.Channel(), nil } - getTestWorkflowParallelStepNotificationsStream := func(ctx context.Context, executionID, ref string, parallelStepIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) { + getTestWorkflowParallelStepNotificationsStream := func(ctx context.Context, executionID, parallelStepName string, parallelStepIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) { execution, err := testWorkflowResultsRepository.Get(ctx, executionID) if err != nil { return nil, err @@ -356,6 +356,11 @@ func main() { return nil, errors.New("test workflow execution is finished") } + ref := execution.GetParallelStepReference(parallelStepName) + if ref == "" { + return nil, fmt.Errorf("unknown parallel step '%s' for test workflow execution %s", parallelStepName, execution.Id) + } + notifications := executionWorker.Notifications(ctx, fmt.Sprintf("%s-%s-%d", execution.Id, ref, parallelStepIndex), executionworkertypes.NotificationsOptions{ Hints: executionworkertypes.Hints{ Namespace: execution.Namespace, diff --git a/pkg/agent/agent.go b/pkg/agent/agent.go index 142b477087..c86750d0da 100644 --- a/pkg/agent/agent.go +++ b/pkg/agent/agent.go @@ -63,7 +63,7 @@ type Agent struct { testWorkflowParallelStepNotificationsWorkerCount int testWorkflowParallelStepNotificationsRequestBuffer chan *cloud.TestWorkflowParallelStepNotificationsRequest testWorkflowParallelStepNotificationsResponseBuffer chan *cloud.TestWorkflowParallelStepNotificationsResponse - testWorkflowParallelStepNotificationsFunc func(ctx context.Context, executionID, ref string, parallelStepIndexIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) + testWorkflowParallelStepNotificationsFunc func(ctx context.Context, executionID, parallelStepName string, parallelStepIndexIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) events chan testkube.Event sendTimeout time.Duration diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index b65d20954c..b23bfd5955 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -386,7 +386,7 @@ func (ag *Agent) executeWorkflowParallelStepNotificationsRequest(ctx context.Con // Cloud sometimes slow to start parallel step // while WorkflowNotifications request from websockets comes in faster // so we retry up to wait till parallel step pod is uo or execution is finished. - return ag.testWorkflowParallelStepNotificationsFunc(ctx, req.ExecutionId, req.Ref, int(req.ParallelStepIndex)) + return ag.testWorkflowParallelStepNotificationsFunc(ctx, req.ExecutionId, req.ParallelStepName, int(req.ParallelStepIndex)) }, retry.DelayType(retry.FixedDelay), retry.Delay(logRetryDelay), diff --git a/pkg/cloud/service.pb.go b/pkg/cloud/service.pb.go index f2f3806c57..29e7cb0c12 100644 --- a/pkg/cloud/service.pb.go +++ b/pkg/cloud/service.pb.go @@ -1249,7 +1249,7 @@ type TestWorkflowParallelStepNotificationsRequest struct { StreamId string `protobuf:"bytes,1,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` ExecutionId string `protobuf:"bytes,2,opt,name=execution_id,json=executionId,proto3" json:"execution_id,omitempty"` - Ref string `protobuf:"bytes,3,opt,name=ref,proto3" json:"ref,omitempty"` + ParallelStepName string `protobuf:"bytes,3,opt,name=parallel_step_name,json=parallelStepName,proto3" json:"parallel_step_name,omitempty"` ParallelStepIndex int32 `protobuf:"varint,4,opt,name=parallel_step_index,json=parallelStepIndex,proto3" json:"parallel_step_index,omitempty"` RequestType TestWorkflowNotificationsRequestType `protobuf:"varint,5,opt,name=request_type,json=requestType,proto3,enum=cloud.TestWorkflowNotificationsRequestType" json:"request_type,omitempty"` } @@ -1300,9 +1300,9 @@ func (x *TestWorkflowParallelStepNotificationsRequest) GetExecutionId() string { return "" } -func (x *TestWorkflowParallelStepNotificationsRequest) GetRef() string { +func (x *TestWorkflowParallelStepNotificationsRequest) GetParallelStepName() string { if x != nil { - return x.Ref + return x.ParallelStepName } return "" } @@ -1556,120 +1556,122 @@ var file_proto_service_proto_rawDesc = []byte{ 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x80, 0x02, 0x0a, 0x2c, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x9c, 0x02, 0x0a, 0x2c, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, - 0x65, 0x66, 0x12, 0x2e, 0x0a, 0x13, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x5f, 0x73, - 0x74, 0x65, 0x70, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x11, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x4e, 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x22, 0xe6, 0x01, 0x0a, 0x2d, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, - 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, - 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x37, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, + 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x5f, 0x73, 0x74, 0x65, + 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x61, + 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, + 0x0a, 0x13, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, + 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x70, 0x61, 0x72, + 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4e, + 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, + 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x52, 0x0b, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0xe6, + 0x01, 0x0a, 0x2d, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, + 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x15, 0x0a, + 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, + 0x65, 0x71, 0x4e, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x72, 0x65, 0x66, 0x12, 0x37, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x48, 0x0a, 0x15, 0x4c, 0x6f, 0x67, 0x73, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x5f, 0x4d, + 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x52, 0x45, + 0x41, 0x4d, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, + 0x01, 0x2a, 0x69, 0x0a, 0x24, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x57, 0x4f, 0x52, + 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, + 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x57, 0x4f, + 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x48, 0x45, + 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x01, 0x2a, 0x8a, 0x01, 0x0a, + 0x1c, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, + 0x15, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, + 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x57, 0x4f, 0x52, 0x4b, + 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x10, + 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, + 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x02, 0x12, 0x1a, 0x0a, + 0x16, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, + 0x5f, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x10, 0x03, 0x2a, 0x4c, 0x0a, 0x06, 0x4f, 0x70, 0x63, + 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x45, 0x58, 0x54, 0x5f, 0x46, 0x52, 0x41, 0x4d, + 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x46, 0x52, + 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, + 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x03, 0x32, 0x88, 0x07, 0x0a, 0x10, 0x54, 0x65, 0x73, 0x74, + 0x4b, 0x75, 0x62, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x41, 0x50, 0x49, 0x12, 0x3c, 0x0a, 0x07, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, + 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x36, 0x0a, 0x04, 0x53, 0x65, + 0x6e, 0x64, 0x12, 0x14, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, + 0x63, 0x6b, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x28, 0x01, 0x12, 0x35, 0x0a, 0x04, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x15, 0x2e, 0x63, 0x6c, 0x6f, + 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x65, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x1a, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x0d, + 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x19, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x7b, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, + 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x2e, 0x63, + 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x27, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x48, 0x0a, 0x15, 0x4c, - 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, - 0x4f, 0x47, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, - 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, - 0x45, 0x43, 0x4b, 0x10, 0x01, 0x2a, 0x69, 0x0a, 0x24, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, - 0x1b, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, - 0x5f, 0x4c, 0x4f, 0x47, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, 0x20, - 0x0a, 0x1c, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, - 0x4d, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x01, - 0x2a, 0x8a, 0x01, 0x0a, 0x1c, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x19, 0x0a, 0x15, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, - 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, - 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, - 0x4c, 0x4f, 0x47, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, - 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, - 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, - 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x10, 0x03, 0x2a, 0x4c, 0x0a, - 0x06, 0x4f, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x45, 0x58, 0x54, 0x5f, - 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, - 0x59, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x48, 0x45, 0x41, - 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x03, 0x32, 0x88, 0x07, 0x0a, 0x10, - 0x54, 0x65, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x41, 0x50, 0x49, - 0x12, 0x3c, 0x0a, 0x07, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x1a, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x36, - 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x14, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, - 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x12, 0x35, 0x0a, 0x04, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x15, - 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, - 0x0c, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x16, 0x2e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, - 0x12, 0x48, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x12, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x18, 0x2e, 0x63, - 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x7b, 0x0a, 0x22, 0x47, 0x65, - 0x74, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x12, 0x28, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x27, 0x2e, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, - 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x90, 0x01, 0x0a, 0x29, 0x47, 0x65, 0x74, 0x54, - 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x2f, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, - 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x2e, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, - 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x9f, 0x01, 0x0a, 0x2e, 0x47, - 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, + 0x01, 0x30, 0x01, 0x12, 0x90, 0x01, 0x0a, 0x29, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x57, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x12, 0x2f, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x1a, 0x2e, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x9f, 0x01, 0x0a, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x65, + 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, + 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x34, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x34, 0x2e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x1a, 0x33, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, - 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, - 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0d, - 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x50, 0x72, - 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x44, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x12, 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, 0x67, 0x2f, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, + 0x33, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x50, + 0x72, 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x50, 0x72, 0x6f, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x78, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0d, + 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x18, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, + 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, 0x67, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/service.proto b/proto/service.proto index b13c0acafc..afc409b4ac 100644 --- a/proto/service.proto +++ b/proto/service.proto @@ -147,7 +147,7 @@ message TestWorkflowServiceNotificationsResponse { message TestWorkflowParallelStepNotificationsRequest { string stream_id = 1; string execution_id = 2; - string ref = 3; + string parallel_step_name = 3; int32 parallel_step_index = 4; TestWorkflowNotificationsRequestType request_type = 5; } From 75d7f88a94c84577f244907b8e1ffb20b0bbdf6d Mon Sep 17 00:00:00 2001 From: Vladislav Sukhin Date: Tue, 3 Dec 2024 20:11:09 +0300 Subject: [PATCH 40/40] fix: rename fields Signed-off-by: Vladislav Sukhin --- cmd/api-server/main.go | 9 +- .../commands/testworkflows/run.go | 6 +- internal/app/api/v1/server.go | 4 +- internal/app/api/v1/testworkflowexecutions.go | 22 +- pkg/agent/agent.go | 4 +- pkg/agent/agent_test.go | 2 +- pkg/agent/events_test.go | 2 +- pkg/agent/logs_test.go | 2 +- pkg/agent/testworkflows.go | 2 +- pkg/api/v1/client/interface.go | 2 +- pkg/api/v1/client/testworkflow.go | 4 +- pkg/cloud/service.pb.go | 233 +++++++++--------- proto/service.proto | 4 +- 13 files changed, 144 insertions(+), 152 deletions(-) diff --git a/cmd/api-server/main.go b/cmd/api-server/main.go index a7430f5e01..781b7d3229 100644 --- a/cmd/api-server/main.go +++ b/cmd/api-server/main.go @@ -346,7 +346,7 @@ func main() { } return notifications.Channel(), nil } - getTestWorkflowParallelStepNotificationsStream := func(ctx context.Context, executionID, parallelStepName string, parallelStepIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) { + getTestWorkflowParallelStepNotificationsStream := func(ctx context.Context, executionID, ref string, workerIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) { execution, err := testWorkflowResultsRepository.Get(ctx, executionID) if err != nil { return nil, err @@ -356,12 +356,7 @@ func main() { return nil, errors.New("test workflow execution is finished") } - ref := execution.GetParallelStepReference(parallelStepName) - if ref == "" { - return nil, fmt.Errorf("unknown parallel step '%s' for test workflow execution %s", parallelStepName, execution.Id) - } - - notifications := executionWorker.Notifications(ctx, fmt.Sprintf("%s-%s-%d", execution.Id, ref, parallelStepIndex), executionworkertypes.NotificationsOptions{ + notifications := executionWorker.Notifications(ctx, fmt.Sprintf("%s-%s-%d", execution.Id, ref, workerIndex), executionworkertypes.NotificationsOptions{ Hints: executionworkertypes.Hints{ Namespace: execution.Namespace, ScheduledAt: common.Ptr(execution.ScheduledAt), diff --git a/cmd/kubectl-testkube/commands/testworkflows/run.go b/cmd/kubectl-testkube/commands/testworkflows/run.go index 14dc9cac44..4db4d82e47 100644 --- a/cmd/kubectl-testkube/commands/testworkflows/run.go +++ b/cmd/kubectl-testkube/commands/testworkflows/run.go @@ -402,9 +402,9 @@ func watchTestWorkflowServiceLogs(id, serviceName string, serviceIndex int, return printTestWorkflowLogs(signature, notifications), nil } -func watchTestWorkflowParallelStepLogs(id, parallelStepName string, parallelStepIndex int, +func watchTestWorkflowParallelStepLogs(id, ref string, workerIndex int, signature []testkube.TestWorkflowSignature, client apiclientv1.Client) (*testkube.TestWorkflowResult, error) { - ui.Info("Getting logs from test workflow parallel step job", fmt.Sprintf("%s-%s-%d", id, parallelStepName, parallelStepIndex)) + ui.Info("Getting logs from test workflow parallel step job", fmt.Sprintf("%s-%s-%d", id, ref, workerIndex)) var ( notifications chan testkube.TestWorkflowExecutionNotification @@ -413,7 +413,7 @@ func watchTestWorkflowParallelStepLogs(id, parallelStepName string, parallelStep spinner := ui.NewSpinner("Waiting for parallel step logs") for { - notifications, nErr = client.GetTestWorkflowExecutionParallelStepNotifications(id, parallelStepName, parallelStepIndex) + notifications, nErr = client.GetTestWorkflowExecutionParallelStepNotifications(id, ref, workerIndex) if nErr != nil { execution, cErr := client.GetTestWorkflowExecution(id) if cErr != nil { diff --git a/internal/app/api/v1/server.go b/internal/app/api/v1/server.go index 4fc844e93d..93e4b0d79b 100644 --- a/internal/app/api/v1/server.go +++ b/internal/app/api/v1/server.go @@ -151,10 +151,10 @@ func (s *TestkubeAPI) Init(server server.HTTPServer) { testWorkflowExecutions.Get("/:executionID", s.GetTestWorkflowExecutionHandler()) testWorkflowExecutions.Get("/:executionID/notifications", s.StreamTestWorkflowExecutionNotificationsHandler()) testWorkflowExecutions.Get("/:executionID/notifications/services/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsHandler()) - testWorkflowExecutions.Get("/:executionID/notifications/parallel-steps/:parallelStepName/:parallelStepIndex", s.StreamTestWorkflowExecutionParallelStepNotificationsHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/parallel-steps/:ref/:workerIndex", s.StreamTestWorkflowExecutionParallelStepNotificationsHandler()) testWorkflowExecutions.Get("/:executionID/notifications/stream", s.StreamTestWorkflowExecutionNotificationsWebSocketHandler()) testWorkflowExecutions.Get("/:executionID/notifications/stream/services/:serviceName/:serviceIndex", s.StreamTestWorkflowExecutionServiceNotificationsWebSocketHandler()) - testWorkflowExecutions.Get("/:executionID/notifications/stream/parallel-steps/:parallelStepName/:parallelStepIndex", s.StreamTestWorkflowExecutionParallelStepNotificationsWebSocketHandler()) + testWorkflowExecutions.Get("/:executionID/notifications/stream/parallel-steps/:ref/:workerIndex", s.StreamTestWorkflowExecutionParallelStepNotificationsWebSocketHandler()) testWorkflowExecutions.Post("/:executionID/abort", s.AbortTestWorkflowExecutionHandler()) testWorkflowExecutions.Post("/:executionID/pause", s.PauseTestWorkflowExecutionHandler()) testWorkflowExecutions.Post("/:executionID/resume", s.ResumeTestWorkflowExecutionHandler()) diff --git a/internal/app/api/v1/testworkflowexecutions.go b/internal/app/api/v1/testworkflowexecutions.go index be91185fd2..ebd859698d 100644 --- a/internal/app/api/v1/testworkflowexecutions.go +++ b/internal/app/api/v1/testworkflowexecutions.go @@ -133,10 +133,10 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionParallelStepNotificationsHandle return func(c *fiber.Ctx) error { ctx := c.Context() executionID := c.Params("executionID") - parallelStepName := c.Params("parallelStepName") - parallelStepIndex := c.Params("parallelStepIndex") + ref := c.Params("ref") + workerIndex := c.Params("workerIndex") errPrefix := fmt.Sprintf("failed to stream test workflow execution parallel step '%s' instance '%s' notifications '%s'", - parallelStepName, parallelStepIndex, executionID) + ref, workerIndex, executionID) // Fetch execution from database execution, err := s.TestWorkflowResults.Get(ctx, executionID) @@ -144,13 +144,13 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionParallelStepNotificationsHandle return s.ClientError(c, errPrefix, err) } - ref := execution.GetParallelStepReference(parallelStepName) - if ref == "" { + reference := execution.GetParallelStepReference(ref) + if reference == "" { return s.ClientError(c, errPrefix, errors.New("unknown parallel step for test workflow execution")) } // Check for the logs - id := fmt.Sprintf("%s-%s-%s", execution.Id, ref, parallelStepIndex) + id := fmt.Sprintf("%s-%s-%s", execution.Id, reference, workerIndex) notifications := s.ExecutionWorkerClient.Notifications(ctx, id, executionworkertypes.NotificationsOptions{ Hints: executionworkertypes.Hints{ Namespace: execution.Namespace, @@ -255,8 +255,8 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionParallelStepNotificationsWebSoc return websocket.New(func(c *websocket.Conn) { ctx, ctxCancel := context.WithCancel(context.Background()) executionID := c.Params("executionID") - parallelStepName := c.Params("parallelStepName") - parallelStepIndex := c.Params("parallelStepIndex") + ref := c.Params("ref") + workerIndex := c.Params("workerIndex") // Stop reading when the WebSocket connection is already closed originalClose := c.CloseHandler() @@ -272,13 +272,13 @@ func (s *TestkubeAPI) StreamTestWorkflowExecutionParallelStepNotificationsWebSoc return } - ref := execution.GetParallelStepReference(parallelStepName) - if ref == "" { + reference := execution.GetParallelStepReference(ref) + if reference == "" { return } // Check for the logs - id := fmt.Sprintf("%s-%s-%s", execution.Id, ref, parallelStepIndex) + id := fmt.Sprintf("%s-%s-%s", execution.Id, reference, workerIndex) notifications := s.ExecutionWorkerClient.Notifications(ctx, id, executionworkertypes.NotificationsOptions{ Hints: executionworkertypes.Hints{ Namespace: execution.Namespace, diff --git a/pkg/agent/agent.go b/pkg/agent/agent.go index c86750d0da..02acc8c0ee 100644 --- a/pkg/agent/agent.go +++ b/pkg/agent/agent.go @@ -63,7 +63,7 @@ type Agent struct { testWorkflowParallelStepNotificationsWorkerCount int testWorkflowParallelStepNotificationsRequestBuffer chan *cloud.TestWorkflowParallelStepNotificationsRequest testWorkflowParallelStepNotificationsResponseBuffer chan *cloud.TestWorkflowParallelStepNotificationsResponse - testWorkflowParallelStepNotificationsFunc func(ctx context.Context, executionID, parallelStepName string, parallelStepIndexIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) + testWorkflowParallelStepNotificationsFunc func(ctx context.Context, executionID, ref string, workerIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) events chan testkube.Event sendTimeout time.Duration @@ -84,7 +84,7 @@ func NewAgent(logger *zap.SugaredLogger, logStreamFunc func(ctx context.Context, executionID string) (chan output.Output, error), workflowNotificationsFunc func(ctx context.Context, executionID string) (<-chan testkube.TestWorkflowExecutionNotification, error), workflowServiceNotificationsFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error), - workflowParallelStepNotificationsFunc func(ctx context.Context, executionID, ref string, parallelStepIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error), + workflowParallelStepNotificationsFunc func(ctx context.Context, executionID, ref string, workerIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error), clusterID string, clusterName string, features featureflags.FeatureFlags, diff --git a/pkg/agent/agent_test.go b/pkg/agent/agent_test.go index 8cc2301fa0..8df8f8e888 100644 --- a/pkg/agent/agent_test.go +++ b/pkg/agent/agent_test.go @@ -60,7 +60,7 @@ func TestCommandExecution(t *testing.T) { var logStreamFunc func(ctx context.Context, executionID string) (chan output.Output, error) var workflowNotificationsStreamFunc func(ctx context.Context, executionID string) (<-chan testkube.TestWorkflowExecutionNotification, error) var workflowServiceNotificationsStreamFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) - var workflowParallelStepNotificationsStreamFunc func(ctx context.Context, executionID, ref string, parallelStepIndexIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) + var workflowParallelStepNotificationsStreamFunc func(ctx context.Context, executionID, ref string, workerIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) logger, _ := zap.NewDevelopment() proContext := config.ProContext{APIKey: "api-key", WorkerCount: 5, LogStreamWorkerCount: 5, WorkflowNotificationsWorkerCount: 5} diff --git a/pkg/agent/events_test.go b/pkg/agent/events_test.go index ff08dbd462..603c72e07a 100644 --- a/pkg/agent/events_test.go +++ b/pkg/agent/events_test.go @@ -57,7 +57,7 @@ func TestEventLoop(t *testing.T) { var logStreamFunc func(ctx context.Context, executionID string) (chan output.Output, error) var workflowNotificationsStreamFunc func(ctx context.Context, executionID string) (<-chan testkube.TestWorkflowExecutionNotification, error) var workflowServiceNotificationsStreamFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) - var workflowParallelStepNotificationsStreamFunc func(ctx context.Context, executionID, ref string, parallelStepIndexIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) + var workflowParallelStepNotificationsStreamFunc func(ctx context.Context, executionID, ref string, workerIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) proContext := config.ProContext{APIKey: "api-key", WorkerCount: 5, LogStreamWorkerCount: 5, WorkflowNotificationsWorkerCount: 5} agent, err := agent.NewAgent(logger.Sugar(), nil, grpcClient, logStreamFunc, workflowNotificationsStreamFunc, diff --git a/pkg/agent/logs_test.go b/pkg/agent/logs_test.go index 7f27bccbbf..4b66726f68 100644 --- a/pkg/agent/logs_test.go +++ b/pkg/agent/logs_test.go @@ -67,7 +67,7 @@ func TestLogStream(t *testing.T) { } var workflowNotificationsStreamFunc func(ctx context.Context, executionID string) (<-chan testkube.TestWorkflowExecutionNotification, error) var workflowServiceNotificationsStreamFunc func(ctx context.Context, executionID, serviceName string, serviceIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) - var workflowParallelStepNotificationsStreamFunc func(ctx context.Context, executionID, ref string, parallelStepIndexIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) + var workflowParallelStepNotificationsStreamFunc func(ctx context.Context, executionID, ref string, workerIndex int) (<-chan testkube.TestWorkflowExecutionNotification, error) logger, _ := zap.NewDevelopment() proContext := config.ProContext{APIKey: "api-key", WorkerCount: 5, LogStreamWorkerCount: 5, WorkflowNotificationsWorkerCount: 5} diff --git a/pkg/agent/testworkflows.go b/pkg/agent/testworkflows.go index b23bfd5955..12bbbc87c8 100644 --- a/pkg/agent/testworkflows.go +++ b/pkg/agent/testworkflows.go @@ -386,7 +386,7 @@ func (ag *Agent) executeWorkflowParallelStepNotificationsRequest(ctx context.Con // Cloud sometimes slow to start parallel step // while WorkflowNotifications request from websockets comes in faster // so we retry up to wait till parallel step pod is uo or execution is finished. - return ag.testWorkflowParallelStepNotificationsFunc(ctx, req.ExecutionId, req.ParallelStepName, int(req.ParallelStepIndex)) + return ag.testWorkflowParallelStepNotificationsFunc(ctx, req.ExecutionId, req.Ref, int(req.WorkerIndex)) }, retry.DelayType(retry.FixedDelay), retry.Delay(logRetryDelay), diff --git a/pkg/api/v1/client/interface.go b/pkg/api/v1/client/interface.go index e5635a31d9..056844022e 100644 --- a/pkg/api/v1/client/interface.go +++ b/pkg/api/v1/client/interface.go @@ -155,7 +155,7 @@ type TestWorkflowAPI interface { GetTestWorkflowExecutionNotifications(id string) (chan testkube.TestWorkflowExecutionNotification, error) GetTestWorkflowExecutionLogs(id string) ([]byte, error) GetTestWorkflowExecutionServiceNotifications(id, serviceName string, serviceIndex int) (chan testkube.TestWorkflowExecutionNotification, error) - GetTestWorkflowExecutionParallelStepNotifications(id, parallelStepName string, parallelStepIndex int) (chan testkube.TestWorkflowExecutionNotification, error) + GetTestWorkflowExecutionParallelStepNotifications(id, ref string, workerIndex int) (chan testkube.TestWorkflowExecutionNotification, error) } // TestWorkflowExecutionAPI describes test workflow api methods diff --git a/pkg/api/v1/client/testworkflow.go b/pkg/api/v1/client/testworkflow.go index d683374809..e331312627 100644 --- a/pkg/api/v1/client/testworkflow.go +++ b/pkg/api/v1/client/testworkflow.go @@ -155,9 +155,9 @@ func (c TestWorkflowClient) GetTestWorkflowExecutionServiceNotifications(id, ser } // GetTestWorkflowExecutionParallelStepNotifications returns events stream from job pods, based on job pods logs -func (c TestWorkflowClient) GetTestWorkflowExecutionParallelStepNotifications(id, parallelStepName string, parallelStepIndex int) (notifications chan testkube.TestWorkflowExecutionNotification, err error) { +func (c TestWorkflowClient) GetTestWorkflowExecutionParallelStepNotifications(id, ref string, workerIndex int) (notifications chan testkube.TestWorkflowExecutionNotification, err error) { notifications = make(chan testkube.TestWorkflowExecutionNotification) - uri := c.testWorkflowTransport.GetURI("/test-workflow-executions/%s/notifications/parallel-steps/%s/%d", id, parallelStepName, parallelStepIndex) + uri := c.testWorkflowTransport.GetURI("/test-workflow-executions/%s/notifications/parallel-steps/%s/%d", id, ref, workerIndex) err = c.testWorkflowTransport.GetTestWorkflowExecutionNotifications(uri, notifications) return notifications, err } diff --git a/pkg/cloud/service.pb.go b/pkg/cloud/service.pb.go index 29e7cb0c12..5bb59b2773 100644 --- a/pkg/cloud/service.pb.go +++ b/pkg/cloud/service.pb.go @@ -1247,11 +1247,11 @@ type TestWorkflowParallelStepNotificationsRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - StreamId string `protobuf:"bytes,1,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` - ExecutionId string `protobuf:"bytes,2,opt,name=execution_id,json=executionId,proto3" json:"execution_id,omitempty"` - ParallelStepName string `protobuf:"bytes,3,opt,name=parallel_step_name,json=parallelStepName,proto3" json:"parallel_step_name,omitempty"` - ParallelStepIndex int32 `protobuf:"varint,4,opt,name=parallel_step_index,json=parallelStepIndex,proto3" json:"parallel_step_index,omitempty"` - RequestType TestWorkflowNotificationsRequestType `protobuf:"varint,5,opt,name=request_type,json=requestType,proto3,enum=cloud.TestWorkflowNotificationsRequestType" json:"request_type,omitempty"` + StreamId string `protobuf:"bytes,1,opt,name=stream_id,json=streamId,proto3" json:"stream_id,omitempty"` + ExecutionId string `protobuf:"bytes,2,opt,name=execution_id,json=executionId,proto3" json:"execution_id,omitempty"` + Ref string `protobuf:"bytes,3,opt,name=ref,proto3" json:"ref,omitempty"` + WorkerIndex int32 `protobuf:"varint,4,opt,name=worker_index,json=workerIndex,proto3" json:"worker_index,omitempty"` + RequestType TestWorkflowNotificationsRequestType `protobuf:"varint,5,opt,name=request_type,json=requestType,proto3,enum=cloud.TestWorkflowNotificationsRequestType" json:"request_type,omitempty"` } func (x *TestWorkflowParallelStepNotificationsRequest) Reset() { @@ -1300,16 +1300,16 @@ func (x *TestWorkflowParallelStepNotificationsRequest) GetExecutionId() string { return "" } -func (x *TestWorkflowParallelStepNotificationsRequest) GetParallelStepName() string { +func (x *TestWorkflowParallelStepNotificationsRequest) GetRef() string { if x != nil { - return x.ParallelStepName + return x.Ref } return "" } -func (x *TestWorkflowParallelStepNotificationsRequest) GetParallelStepIndex() int32 { +func (x *TestWorkflowParallelStepNotificationsRequest) GetWorkerIndex() int32 { if x != nil { - return x.ParallelStepIndex + return x.WorkerIndex } return 0 } @@ -1556,122 +1556,119 @@ var file_proto_service_proto_rawDesc = []byte{ 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x9c, 0x02, 0x0a, 0x2c, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0xf3, 0x01, 0x0a, 0x2c, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x5f, 0x73, 0x74, 0x65, - 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x61, - 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2e, - 0x0a, 0x13, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x5f, 0x73, 0x74, 0x65, 0x70, 0x5f, - 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x11, 0x70, 0x61, 0x72, - 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4e, - 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, - 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x52, 0x0b, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0xe6, - 0x01, 0x0a, 0x2d, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, - 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x15, 0x0a, - 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, - 0x65, 0x71, 0x4e, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x72, 0x65, 0x66, 0x12, 0x37, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x48, 0x0a, 0x15, 0x4c, 0x6f, 0x67, 0x73, 0x53, - 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x5f, 0x4d, - 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x54, 0x52, 0x45, - 0x41, 0x4d, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, - 0x01, 0x2a, 0x69, 0x0a, 0x24, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x1b, 0x57, 0x4f, 0x52, - 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, - 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x57, 0x4f, - 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x48, 0x45, - 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x01, 0x2a, 0x8a, 0x01, 0x0a, - 0x1c, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, - 0x15, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, - 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x57, 0x4f, 0x52, 0x4b, - 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x10, - 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, - 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x10, 0x02, 0x12, 0x1a, 0x0a, - 0x16, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, - 0x5f, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x10, 0x03, 0x2a, 0x4c, 0x0a, 0x06, 0x4f, 0x70, 0x63, - 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x45, 0x58, 0x54, 0x5f, 0x46, 0x52, 0x41, 0x4d, - 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x49, 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x46, 0x52, - 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, - 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x03, 0x32, 0x88, 0x07, 0x0a, 0x10, 0x54, 0x65, 0x73, 0x74, - 0x4b, 0x75, 0x62, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x41, 0x50, 0x49, 0x12, 0x3c, 0x0a, 0x07, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, - 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x36, 0x0a, 0x04, 0x53, 0x65, - 0x6e, 0x64, 0x12, 0x14, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, - 0x63, 0x6b, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x28, 0x01, 0x12, 0x35, 0x0a, 0x04, 0x43, 0x61, 0x6c, 0x6c, 0x12, 0x15, 0x2e, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x0c, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x65, 0x41, 0x73, 0x79, 0x6e, 0x63, 0x12, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, - 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x1a, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x0d, - 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x19, 0x2e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x7b, 0x0a, 0x22, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, - 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x2e, 0x63, - 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x27, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, - 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, - 0x01, 0x30, 0x01, 0x12, 0x90, 0x01, 0x0a, 0x29, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x12, 0x2f, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x1a, 0x2e, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x9f, 0x01, 0x0a, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x65, - 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, - 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x34, 0x2e, 0x63, 0x6c, 0x6f, 0x75, - 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, - 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, - 0x33, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, + 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, + 0x65, 0x66, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, + 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4e, 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x63, 0x6c, + 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x50, - 0x72, 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x1a, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x50, 0x72, 0x6f, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0d, - 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x12, 0x18, 0x2e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, - 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, 0x67, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0xe6, 0x01, 0x0a, 0x2d, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, + 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x71, 0x5f, 0x6e, 0x6f, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x65, 0x71, 0x4e, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x37, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x48, + 0x0a, 0x15, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x54, 0x52, 0x45, 0x41, + 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x00, 0x12, + 0x17, 0x0a, 0x13, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, + 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x01, 0x2a, 0x69, 0x0a, 0x24, 0x54, 0x65, 0x73, 0x74, + 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x1f, 0x0a, 0x1b, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, + 0x45, 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, + 0x00, 0x12, 0x20, 0x0a, 0x1c, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, + 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, + 0x4b, 0x10, 0x01, 0x2a, 0x8a, 0x01, 0x0a, 0x1c, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x15, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, + 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, + 0x17, 0x0a, 0x13, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, + 0x41, 0x4d, 0x5f, 0x4c, 0x4f, 0x47, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x4f, 0x52, 0x4b, + 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x52, 0x45, 0x53, 0x55, + 0x4c, 0x54, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x57, 0x4f, 0x52, 0x4b, 0x46, 0x4c, 0x4f, 0x57, + 0x5f, 0x53, 0x54, 0x52, 0x45, 0x41, 0x4d, 0x5f, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x10, 0x03, + 0x2a, 0x4c, 0x0a, 0x06, 0x4f, 0x70, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x45, + 0x58, 0x54, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x42, 0x49, + 0x4e, 0x41, 0x52, 0x59, 0x5f, 0x46, 0x52, 0x41, 0x4d, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, + 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x43, 0x48, 0x45, 0x43, 0x4b, 0x10, 0x03, 0x32, 0x88, + 0x07, 0x0a, 0x10, 0x54, 0x65, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x43, 0x6c, 0x6f, 0x75, 0x64, + 0x41, 0x50, 0x49, 0x12, 0x3c, 0x0a, 0x07, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x16, + 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, + 0x01, 0x12, 0x36, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x14, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x12, 0x35, 0x0a, 0x04, 0x43, 0x61, 0x6c, + 0x6c, 0x12, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x41, 0x0a, 0x0c, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x41, 0x73, 0x79, 0x6e, 0x63, + 0x12, 0x16, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x15, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, + 0x01, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x12, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x6f, 0x67, + 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, + 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x4c, 0x6f, 0x67, 0x73, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x7b, 0x0a, + 0x22, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x12, 0x28, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, + 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x27, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x90, 0x01, 0x0a, 0x29, 0x47, + 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x2f, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x2e, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, 0x9f, 0x01, + 0x0a, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x12, 0x34, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, + 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x33, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x54, + 0x65, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x50, 0x61, 0x72, 0x61, 0x6c, + 0x6c, 0x65, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x12, + 0x42, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x50, 0x72, 0x6f, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, + 0x74, 0x69, 0x61, 0x6c, 0x12, 0x18, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x72, 0x65, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, + 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, + 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0b, 0x5a, 0x09, 0x70, 0x6b, 0x67, + 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/service.proto b/proto/service.proto index afc409b4ac..b9ca13dafd 100644 --- a/proto/service.proto +++ b/proto/service.proto @@ -147,8 +147,8 @@ message TestWorkflowServiceNotificationsResponse { message TestWorkflowParallelStepNotificationsRequest { string stream_id = 1; string execution_id = 2; - string parallel_step_name = 3; - int32 parallel_step_index = 4; + string ref = 3; + int32 worker_index = 4; TestWorkflowNotificationsRequestType request_type = 5; }