github.com/kubeshop/testkube@v1.17.23/pkg/tcl/apitcl/v1/server.go (about)

     1  // Copyright 2024 Testkube.
     2  //
     3  // Licensed as a Testkube Pro file under the Testkube Community
     4  // License (the "License"); you may not use this file except in compliance with
     5  // the License. You may obtain a copy of the License at
     6  //
     7  //	https://github.com/kubeshop/testkube/blob/main/licenses/TCL.txt
     8  
     9  package v1
    10  
    11  import (
    12  	"context"
    13  	"errors"
    14  	"fmt"
    15  	"net/http"
    16  
    17  	"github.com/gofiber/fiber/v2"
    18  	kubeclient "sigs.k8s.io/controller-runtime/pkg/client"
    19  
    20  	testworkflowsv1 "github.com/kubeshop/testkube-operator/pkg/client/testworkflows/v1"
    21  	apiv1 "github.com/kubeshop/testkube/internal/app/api/v1"
    22  	"github.com/kubeshop/testkube/internal/config"
    23  	"github.com/kubeshop/testkube/pkg/api/v1/testkube"
    24  	"github.com/kubeshop/testkube/pkg/imageinspector"
    25  	configRepo "github.com/kubeshop/testkube/pkg/repository/config"
    26  	"github.com/kubeshop/testkube/pkg/tcl/repositorytcl/testworkflow"
    27  	"github.com/kubeshop/testkube/pkg/tcl/testworkflowstcl/testworkflowexecutor"
    28  )
    29  
    30  type apiTCL struct {
    31  	apiv1.TestkubeAPI
    32  	ProContext                  *config.ProContext
    33  	ImageInspector              imageinspector.Inspector
    34  	TestWorkflowResults         testworkflow.Repository
    35  	TestWorkflowOutput          testworkflow.OutputRepository
    36  	TestWorkflowsClient         testworkflowsv1.Interface
    37  	TestWorkflowTemplatesClient testworkflowsv1.TestWorkflowTemplatesInterface
    38  	TestWorkflowExecutor        testworkflowexecutor.TestWorkflowExecutor
    39  	ApiUrl                      string
    40  	GlobalTemplateName          string
    41  	configMap                   configRepo.Repository
    42  }
    43  
    44  type ApiTCL interface {
    45  	AppendRoutes()
    46  	GetTestWorkflowNotificationsStream(ctx context.Context, executionID string) (chan testkube.TestWorkflowExecutionNotification, error)
    47  }
    48  
    49  func NewApiTCL(
    50  	testkubeAPI apiv1.TestkubeAPI,
    51  	proContext *config.ProContext,
    52  	kubeClient kubeclient.Client,
    53  	imageInspector imageinspector.Inspector,
    54  	testWorkflowResults testworkflow.Repository,
    55  	testWorkflowOutput testworkflow.OutputRepository,
    56  	apiUrl string,
    57  	globalTemplateName string,
    58  	configMap configRepo.Repository,
    59  ) ApiTCL {
    60  	executor := testworkflowexecutor.New(testkubeAPI.Events, testkubeAPI.Clientset, testWorkflowResults, testWorkflowOutput, testkubeAPI.Namespace)
    61  	go executor.Recover(context.Background())
    62  	return &apiTCL{
    63  		TestkubeAPI:                 testkubeAPI,
    64  		ProContext:                  proContext,
    65  		ImageInspector:              imageInspector,
    66  		TestWorkflowResults:         testWorkflowResults,
    67  		TestWorkflowOutput:          testWorkflowOutput,
    68  		TestWorkflowsClient:         testworkflowsv1.NewClient(kubeClient, testkubeAPI.Namespace),
    69  		TestWorkflowTemplatesClient: testworkflowsv1.NewTestWorkflowTemplatesClient(kubeClient, testkubeAPI.Namespace),
    70  		TestWorkflowExecutor:        executor,
    71  		ApiUrl:                      apiUrl,
    72  		GlobalTemplateName:          globalTemplateName,
    73  		configMap:                   configMap,
    74  	}
    75  }
    76  
    77  func (s *apiTCL) NotImplemented(c *fiber.Ctx) error {
    78  	return s.Error(c, http.StatusNotImplemented, errors.New("not implemented yet"))
    79  }
    80  
    81  func (s *apiTCL) BadGateway(c *fiber.Ctx, prefix, description string, err error) error {
    82  	return s.Error(c, http.StatusBadGateway, fmt.Errorf("%s: %s: %w", prefix, description, err))
    83  }
    84  
    85  func (s *apiTCL) InternalError(c *fiber.Ctx, prefix, description string, err error) error {
    86  	return s.Error(c, http.StatusInternalServerError, fmt.Errorf("%s: %s: %w", prefix, description, err))
    87  }
    88  
    89  func (s *apiTCL) BadRequest(c *fiber.Ctx, prefix, description string, err error) error {
    90  	return s.Error(c, http.StatusBadRequest, fmt.Errorf("%s: %s: %w", prefix, description, err))
    91  }
    92  
    93  func (s *apiTCL) NotFound(c *fiber.Ctx, prefix, description string, err error) error {
    94  	return s.Error(c, http.StatusNotFound, fmt.Errorf("%s: %s: %w", prefix, description, err))
    95  }
    96  
    97  func (s *apiTCL) ClientError(c *fiber.Ctx, prefix string, err error) error {
    98  	if IsNotFound(err) {
    99  		return s.NotFound(c, prefix, "client not found", err)
   100  	}
   101  	return s.BadGateway(c, prefix, "client problem", err)
   102  }
   103  
   104  func (s *apiTCL) AppendRoutes() {
   105  	root := s.Routes
   106  
   107  	// Register TestWorkflows as additional source for labels
   108  	s.WithLabelSources(s.TestWorkflowsClient, s.TestWorkflowTemplatesClient)
   109  
   110  	testWorkflows := root.Group("/test-workflows")
   111  	testWorkflows.Get("/", s.pro(s.ListTestWorkflowsHandler()))
   112  	testWorkflows.Post("/", s.pro(s.CreateTestWorkflowHandler()))
   113  	testWorkflows.Delete("/", s.pro(s.DeleteTestWorkflowsHandler()))
   114  	testWorkflows.Get("/:id", s.pro(s.GetTestWorkflowHandler()))
   115  	testWorkflows.Put("/:id", s.pro(s.UpdateTestWorkflowHandler()))
   116  	testWorkflows.Delete("/:id", s.pro(s.DeleteTestWorkflowHandler()))
   117  	testWorkflows.Get("/:id/executions", s.pro(s.ListTestWorkflowExecutionsHandler()))
   118  	testWorkflows.Post("/:id/executions", s.pro(s.ExecuteTestWorkflowHandler()))
   119  	testWorkflows.Get("/:id/metrics", s.pro(s.GetTestWorkflowMetricsHandler()))
   120  	testWorkflows.Get("/:id/executions/:executionID", s.pro(s.GetTestWorkflowExecutionHandler()))
   121  	testWorkflows.Post("/:id/abort", s.pro(s.AbortAllTestWorkflowExecutionsHandler()))
   122  	testWorkflows.Post("/:id/executions/:executionID/abort", s.pro(s.AbortTestWorkflowExecutionHandler()))
   123  	testWorkflows.Get("/:id/executions/:executionID/logs", s.pro(s.GetTestWorkflowExecutionLogsHandler()))
   124  
   125  	testWorkflowExecutions := root.Group("/test-workflow-executions")
   126  	testWorkflowExecutions.Get("/", s.pro(s.ListTestWorkflowExecutionsHandler()))
   127  	testWorkflowExecutions.Get("/:executionID", s.pro(s.GetTestWorkflowExecutionHandler()))
   128  	testWorkflowExecutions.Get("/:executionID/notifications", s.pro(s.StreamTestWorkflowExecutionNotificationsHandler()))
   129  	testWorkflowExecutions.Get("/:executionID/notifications/stream", s.pro(s.StreamTestWorkflowExecutionNotificationsWebSocketHandler()))
   130  	testWorkflowExecutions.Post("/:executionID/abort", s.pro(s.AbortTestWorkflowExecutionHandler()))
   131  	testWorkflowExecutions.Get("/:executionID/logs", s.pro(s.GetTestWorkflowExecutionLogsHandler()))
   132  	testWorkflowExecutions.Get("/:executionID/artifacts", s.pro(s.ListTestWorkflowExecutionArtifactsHandler()))
   133  	testWorkflowExecutions.Get("/:executionID/artifacts/:filename", s.pro(s.GetTestWorkflowArtifactHandler()))
   134  	testWorkflowExecutions.Get("/:executionID/artifact-archive", s.pro(s.GetTestWorkflowArtifactArchiveHandler()))
   135  
   136  	testWorkflowWithExecutions := root.Group("/test-workflow-with-executions")
   137  	testWorkflowWithExecutions.Get("/", s.pro(s.ListTestWorkflowWithExecutionsHandler()))
   138  	testWorkflowWithExecutions.Get("/:id", s.pro(s.GetTestWorkflowWithExecutionHandler()))
   139  
   140  	root.Post("/preview-test-workflow", s.pro(s.PreviewTestWorkflowHandler()))
   141  
   142  	testWorkflowTemplates := root.Group("/test-workflow-templates")
   143  	testWorkflowTemplates.Get("/", s.pro(s.ListTestWorkflowTemplatesHandler()))
   144  	testWorkflowTemplates.Post("/", s.pro(s.CreateTestWorkflowTemplateHandler()))
   145  	testWorkflowTemplates.Delete("/", s.pro(s.DeleteTestWorkflowTemplatesHandler()))
   146  	testWorkflowTemplates.Get("/:id", s.pro(s.GetTestWorkflowTemplateHandler()))
   147  	testWorkflowTemplates.Put("/:id", s.pro(s.UpdateTestWorkflowTemplateHandler()))
   148  	testWorkflowTemplates.Delete("/:id", s.pro(s.DeleteTestWorkflowTemplateHandler()))
   149  }