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 }