github.com/kubeshop/testkube@v1.17.23/pkg/tcl/apitcl/v1/testworkflowtemplates.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 "fmt" 13 "net/http" 14 "strings" 15 16 "github.com/gofiber/fiber/v2" 17 "github.com/pkg/errors" 18 19 testworkflowsv1 "github.com/kubeshop/testkube-operator/api/testworkflows/v1" 20 "github.com/kubeshop/testkube/internal/common" 21 "github.com/kubeshop/testkube/pkg/api/v1/testkube" 22 mappers2 "github.com/kubeshop/testkube/pkg/tcl/mapperstcl/testworkflows" 23 ) 24 25 func (s *apiTCL) ListTestWorkflowTemplatesHandler() fiber.Handler { 26 errPrefix := "failed to list test workflow templates" 27 return func(c *fiber.Ctx) (err error) { 28 templates, err := s.getFilteredTestWorkflowTemplateList(c) 29 if err != nil { 30 return s.BadGateway(c, errPrefix, "client problem", err) 31 } 32 err = SendResourceList(c, "TestWorkflowTemplate", testworkflowsv1.GroupVersion, mappers2.MapTestWorkflowTemplateKubeToAPI, templates.Items...) 33 if err != nil { 34 return s.InternalError(c, errPrefix, "serialization problem", err) 35 } 36 return 37 } 38 } 39 40 func (s *apiTCL) GetTestWorkflowTemplateHandler() fiber.Handler { 41 return func(c *fiber.Ctx) (err error) { 42 name := c.Params("id") 43 errPrefix := fmt.Sprintf("failed to get test workflow template '%s'", name) 44 template, err := s.TestWorkflowTemplatesClient.Get(name) 45 if err != nil { 46 return s.ClientError(c, errPrefix, err) 47 } 48 err = SendResource(c, "TestWorkflowTemplate", testworkflowsv1.GroupVersion, mappers2.MapTemplateKubeToAPI, template) 49 if err != nil { 50 return s.InternalError(c, errPrefix, "serialization problem", err) 51 } 52 return 53 } 54 } 55 56 func (s *apiTCL) DeleteTestWorkflowTemplateHandler() fiber.Handler { 57 return func(c *fiber.Ctx) error { 58 name := c.Params("id") 59 errPrefix := fmt.Sprintf("failed to delete test workflow template '%s'", name) 60 err := s.TestWorkflowTemplatesClient.Delete(name) 61 s.Metrics.IncDeleteTestWorkflowTemplate(err) 62 if err != nil { 63 return s.ClientError(c, errPrefix, err) 64 } 65 return c.SendStatus(http.StatusNoContent) 66 } 67 } 68 69 func (s *apiTCL) DeleteTestWorkflowTemplatesHandler() fiber.Handler { 70 errPrefix := "failed to delete test workflow templates" 71 return func(c *fiber.Ctx) error { 72 selector := c.Query("selector") 73 err := s.TestWorkflowTemplatesClient.DeleteByLabels(selector) 74 if err != nil { 75 return s.ClientError(c, errPrefix, err) 76 } 77 return c.SendStatus(http.StatusNoContent) 78 } 79 } 80 81 func (s *apiTCL) CreateTestWorkflowTemplateHandler() fiber.Handler { 82 errPrefix := "failed to create test workflow template" 83 return func(c *fiber.Ctx) (err error) { 84 // Deserialize resource 85 obj := new(testworkflowsv1.TestWorkflowTemplate) 86 if HasYAML(c) { 87 err = common.DeserializeCRD(obj, c.Body()) 88 if err != nil { 89 return s.BadRequest(c, errPrefix, "invalid body", err) 90 } 91 } else { 92 var v *testkube.TestWorkflowTemplate 93 err = c.BodyParser(&v) 94 if err != nil { 95 return s.BadRequest(c, errPrefix, "invalid body", err) 96 } 97 obj = mappers2.MapTemplateAPIToKube(v) 98 } 99 100 // Validate resource 101 if obj == nil || obj.Name == "" { 102 return s.BadRequest(c, errPrefix, "invalid body", errors.New("name is required")) 103 } 104 obj.Namespace = s.Namespace 105 106 // Create the resource 107 obj, err = s.TestWorkflowTemplatesClient.Create(obj) 108 s.Metrics.IncCreateTestWorkflowTemplate(err) 109 if err != nil { 110 return s.BadRequest(c, errPrefix, "client error", err) 111 } 112 s.sendCreateWorkflowTemplateTelemetry(c.Context(), obj) 113 114 err = SendResource(c, "TestWorkflowTemplate", testworkflowsv1.GroupVersion, mappers2.MapTemplateKubeToAPI, obj) 115 if err != nil { 116 return s.InternalError(c, errPrefix, "serialization problem", err) 117 } 118 return 119 } 120 } 121 122 func (s *apiTCL) UpdateTestWorkflowTemplateHandler() fiber.Handler { 123 errPrefix := "failed to update test workflow template" 124 return func(c *fiber.Ctx) (err error) { 125 name := c.Params("id") 126 127 // Deserialize resource 128 obj := new(testworkflowsv1.TestWorkflowTemplate) 129 if HasYAML(c) { 130 err = common.DeserializeCRD(obj, c.Body()) 131 if err != nil { 132 return s.BadRequest(c, errPrefix, "invalid body", err) 133 } 134 } else { 135 var v *testkube.TestWorkflowTemplate 136 err = c.BodyParser(&v) 137 if err != nil { 138 return s.BadRequest(c, errPrefix, "invalid body", err) 139 } 140 obj = mappers2.MapTemplateAPIToKube(v) 141 } 142 143 // Read existing resource 144 template, err := s.TestWorkflowTemplatesClient.Get(name) 145 if err != nil { 146 return s.ClientError(c, errPrefix, err) 147 } 148 149 // Validate resource 150 if obj == nil { 151 return s.BadRequest(c, errPrefix, "invalid body", errors.New("body is required")) 152 } 153 obj.Namespace = template.Namespace 154 obj.Name = template.Name 155 obj.ResourceVersion = template.ResourceVersion 156 157 // Update the resource 158 obj, err = s.TestWorkflowTemplatesClient.Update(obj) 159 s.Metrics.IncUpdateTestWorkflowTemplate(err) 160 if err != nil { 161 return s.BadRequest(c, errPrefix, "client error", err) 162 } 163 164 err = SendResource(c, "TestWorkflowTemplate", testworkflowsv1.GroupVersion, mappers2.MapTemplateKubeToAPI, obj) 165 if err != nil { 166 return s.InternalError(c, errPrefix, "serialization problem", err) 167 } 168 return 169 } 170 } 171 172 func (s *apiTCL) getFilteredTestWorkflowTemplateList(c *fiber.Ctx) (*testworkflowsv1.TestWorkflowTemplateList, error) { 173 crTemplates, err := s.TestWorkflowTemplatesClient.List(c.Query("selector")) 174 if err != nil { 175 return nil, err 176 } 177 178 search := c.Query("textSearch") 179 if search != "" { 180 search = strings.ReplaceAll(search, "/", "--") 181 for i := len(crTemplates.Items) - 1; i >= 0; i-- { 182 if !strings.Contains(crTemplates.Items[i].Name, search) { 183 crTemplates.Items = append(crTemplates.Items[:i], crTemplates.Items[i+1:]...) 184 } 185 } 186 } 187 188 return crTemplates, nil 189 }