Skip to content

Commit

Permalink
feat: [TKC-2299] list test workflow execution tags (#5797)
Browse files Browse the repository at this point in the history
* feat: list test workflow execution tags

Signed-off-by: Vladislav Sukhin <vladislav@kubeshop.io>

* feat: add tags model

Signed-off-by: Vladislav Sukhin <vladislav@kubeshop.io>

* fix: convert dots

Signed-off-by: Vladislav Sukhin <vladislav@kubeshop.io>

* fix: rename error prefix

Signed-off-by: Vladislav Sukhin <vladislav@kubeshop.io>

* fix: add execution tags command

Signed-off-by: Vladislav Sukhin <vladislav@kubeshop.io>

---------

Signed-off-by: Vladislav Sukhin <vladislav@kubeshop.io>
  • Loading branch information
vsukhin committed Sep 3, 2024
1 parent 7d8758f commit 82f854b
Show file tree
Hide file tree
Showing 12 changed files with 208 additions and 40 deletions.
40 changes: 40 additions & 0 deletions api/v1/testkube.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2340,6 +2340,40 @@ paths:
items:
$ref: "#/components/schemas/Problem"

/tags:
get:
tags:
- tags
summary: "List tags"
description: "list all available tags"
operationId: listTags
responses:
200:
description: "successful operation"
content:
application/json:
schema:
type: object
additionalProperties:
type: array
items:
type: string
example:
app:
- backend
env:
- prod
toDelete:
- "yes"
502:
description: "problem with read information from kubernetes cluster"
content:
application/problem+json:
schema:
type: array
items:
$ref: "#/components/schemas/Problem"

/webhooks:
get:
tags:
Expand Down Expand Up @@ -9423,6 +9457,12 @@ components:
tags:
$ref: "#/components/schemas/TestWorkflowTagValue"

TestWorkflowExecutionTags:
type: object
properties:
tags:
$ref: "#/components/schemas/TestWorkflowTagValue"

ContentGitAuthType:
type: string
description: auth type for git requests
Expand Down
40 changes: 0 additions & 40 deletions internal/app/api/v1/labels.go

This file was deleted.

60 changes: 60 additions & 0 deletions internal/app/api/v1/labels_tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package v1

import (
"fmt"
"net/http"

"github.com/gofiber/fiber/v2"
)

func (s TestkubeAPI) ListLabelsHandler() fiber.Handler {
return func(c *fiber.Ctx) error {
labels := make(map[string][]string)
sources := append(*s.LabelSources, s.TestsClient, s.TestsSuitesClient)

for _, source := range sources {
nextLabels, err := source.ListLabels()
if err != nil {
return s.Error(c, http.StatusBadGateway, fmt.Errorf("failed to list labels: %w", err))
}

deduplicateMap(nextLabels, labels)
}

return c.JSON(labels)
}
}

func (s *TestkubeAPI) ListTagsHandler() fiber.Handler {
return func(c *fiber.Ctx) error {
errPrefix := "failed to list execution tags"

tags, err := s.TestWorkflowResults.GetExecutionTags(c.Context())
if err != nil {
return s.ClientError(c, errPrefix, err)
}

results := make(map[string][]string)
deduplicateMap(tags, results)

return c.JSON(results)
}
}

func deduplicateMap(src, dst map[string][]string) {
for key, testValues := range src {
valuesMap := make(map[string]struct{})
if values, ok := dst[key]; ok {
for _, v := range values {
valuesMap[v] = struct{}{}
}
}

for _, testValue := range testValues {
if _, ok := valuesMap[testValue]; !ok {
dst[key] = append(dst[key], testValue)
valuesMap[testValue] = struct{}{}
}
}
}
}
3 changes: 3 additions & 0 deletions internal/app/api/v1/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,9 @@ func (s *TestkubeAPI) InitRoutes() {
labels := root.Group("/labels")
labels.Get("/", s.ListLabelsHandler())

tags := root.Group("/tags")
tags.Get("/", s.ListTagsHandler())

slack := root.Group("/slack")
slack.Get("/", s.OauthHandler())

Expand Down
14 changes: 14 additions & 0 deletions pkg/api/v1/testkube/model_test_workflow_execution_tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Testkube API
*
* Testkube provides a Kubernetes-native framework for test definition, execution and results
*
* API version: 1.0.0
* Contact: testkube@kubeshop.io
* Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
*/
package testkube

type TestWorkflowExecutionTags struct {
Tags map[string]string `json:"tags,omitempty"`
}
18 changes: 18 additions & 0 deletions pkg/api/v1/testkube/model_test_workflow_execution_tags_extended.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package testkube

import "github.com/kubeshop/testkube/pkg/utils"

func (t *TestWorkflowExecutionTags) ConvertDots(fn func(string) string) *TestWorkflowExecutionTags {
if t.Tags != nil {
t.Tags = convertDotsInMap(t.Tags, fn)
}
return t
}

func (t *TestWorkflowExecutionTags) EscapeDots() *TestWorkflowExecutionTags {
return t.ConvertDots(utils.EscapeDots)
}

func (t *TestWorkflowExecutionTags) UnscapeDots() *TestWorkflowExecutionTags {
return t.ConvertDots(utils.UnescapeDots)
}
3 changes: 3 additions & 0 deletions pkg/cloud/data/testworkflow/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const (
CmdTestWorkflowExecutionDeleteByWorkflows executor.Command = "workflow_execution_delete_by_workflows"
CmdTestWorkflowExecutionGetWorkflowMetrics executor.Command = "workflow_execution_get_workflow_metrics"
CmdTestWorkflowExecutionGetNextExecutionNumber executor.Command = "workflow_execution_get_next_execution_number"
CmdTestWorkflowExecutionGetExecutionTags executor.Command = "workflow_execution_get_execution_tags"

CmdTestWorkflowOutputPresignSaveLog executor.Command = "workflow_output_presign_save_log"
CmdTestWorkflowOutputPresignReadLog executor.Command = "workflow_output_presign_read_log"
Expand Down Expand Up @@ -68,6 +69,8 @@ func command(v interface{}) executor.Command {
return CmdTestWorkflowExecutionGetWorkflowMetrics
case ExecutionGetNextExecutionNumberRequest:
return CmdTestWorkflowExecutionGetNextExecutionNumber
case ExecutionGetExecutionTagsRequest:
return CmdTestWorkflowExecutionGetExecutionTags

case OutputPresignSaveLogRequest:
return CmdTestWorkflowOutputPresignSaveLog
Expand Down
8 changes: 8 additions & 0 deletions pkg/cloud/data/testworkflow/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,11 @@ func (r *CloudRepository) GetNextExecutionNumber(ctx context.Context, testWorkfl
}
return commandResponse.TestWorkflowNumber, nil
}

func (r *CloudRepository) GetExecutionTags(ctx context.Context) (tags map[string][]string, err error) {
req := ExecutionGetExecutionTagsRequest{}
process := func(v ExecutionGetExecutionTagsResponse) map[string][]string {
return v.Tags
}
return pass(r.executor, ctx, req, process)
}
7 changes: 7 additions & 0 deletions pkg/cloud/data/testworkflow/execution_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,10 @@ type ExecutionGetNextExecutionNumberRequest struct {
type ExecutionGetNextExecutionNumberResponse struct {
TestWorkflowNumber int32 `json:"testWorkflowNumber"`
}

type ExecutionGetExecutionTagsRequest struct {
}

type ExecutionGetExecutionTagsResponse struct {
Tags map[string][]string `json:"tags"`
}
2 changes: 2 additions & 0 deletions pkg/repository/testworkflow/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ type Repository interface {
DeleteByTestWorkflows(ctx context.Context, workflowNames []string) (err error)
// GetTestWorkflowMetrics get metrics based on the TestWorkflow results
GetTestWorkflowMetrics(ctx context.Context, name string, limit, last int) (metrics testkube.ExecutionsMetrics, err error)
// GetExecutionTags gets execution tags
GetExecutionTags(ctx context.Context) (map[string][]string, error)
}

type Sequences interface {
Expand Down
15 changes: 15 additions & 0 deletions pkg/repository/testworkflow/mock_repository.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions pkg/repository/testworkflow/mongo.go
Original file line number Diff line number Diff line change
Expand Up @@ -507,3 +507,41 @@ func (r *MongoRepository) GetNextExecutionNumber(ctx context.Context, name strin

return r.sequenceRepository.GetNextExecutionNumber(ctx, name, sequence.ExecutionTypeTestWorkflow)
}

func (r *MongoRepository) GetExecutionTags(ctx context.Context) (tags map[string][]string, err error) {
pipeline := []bson.M{
{"$match": bson.M{"tags": bson.M{"$exists": true}}},
{"$project": bson.M{
"tags": 1,
}},
}

opts := options.Aggregate()
if r.allowDiskUse {
opts.SetAllowDiskUse(r.allowDiskUse)
}

cursor, err := r.Coll.Aggregate(ctx, pipeline, opts)
if err != nil {
return nil, err
}

var executions []testkube.TestWorkflowExecutionTags
err = cursor.All(ctx, &executions)
if err != nil {
return nil, err
}

for i := range executions {
executions[i].UnscapeDots()
}

tags = make(map[string][]string)
for _, execution := range executions {
for key, value := range execution.Tags {
tags[key] = append(tags[key], value)
}
}

return tags, nil
}

0 comments on commit 82f854b

Please sign in to comment.