github.com/kubeshop/testkube@v1.17.23/pkg/api/v1/client/test.go (about) 1 package client 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 "net/url" 8 "strconv" 9 10 "github.com/kubeshop/testkube/pkg/api/v1/testkube" 11 "github.com/kubeshop/testkube/pkg/executor/output" 12 "github.com/kubeshop/testkube/pkg/logs/events" 13 ) 14 15 // NewTestClient creates new Test client 16 func NewTestClient( 17 testTransport Transport[testkube.Test], 18 executionTransport Transport[testkube.Execution], 19 testWithExecutionTransport Transport[testkube.TestWithExecution], 20 testWithExecutionSummaryTransport Transport[testkube.TestWithExecutionSummary], 21 executionsResultTransport Transport[testkube.ExecutionsResult], 22 artifactTransport Transport[testkube.Artifact], 23 serverInfoTransport Transport[testkube.ServerInfo], 24 debugInfoTransport Transport[testkube.DebugInfo], 25 ) TestClient { 26 return TestClient{ 27 testTransport: testTransport, 28 executionTransport: executionTransport, 29 testWithExecutionTransport: testWithExecutionTransport, 30 testWithExecutionSummaryTransport: testWithExecutionSummaryTransport, 31 executionsResultTransport: executionsResultTransport, 32 artifactTransport: artifactTransport, 33 serverInfoTransport: serverInfoTransport, 34 debugInfoTransport: debugInfoTransport, 35 } 36 } 37 38 // TestClient is a client for tests 39 type TestClient struct { 40 testTransport Transport[testkube.Test] 41 executionTransport Transport[testkube.Execution] 42 testWithExecutionTransport Transport[testkube.TestWithExecution] 43 testWithExecutionSummaryTransport Transport[testkube.TestWithExecutionSummary] 44 executionsResultTransport Transport[testkube.ExecutionsResult] 45 artifactTransport Transport[testkube.Artifact] 46 serverInfoTransport Transport[testkube.ServerInfo] 47 debugInfoTransport Transport[testkube.DebugInfo] 48 } 49 50 // GetTest returns single test by id 51 func (c TestClient) GetTest(id string) (test testkube.Test, err error) { 52 uri := c.testTransport.GetURI("/tests/%s", id) 53 return c.testTransport.Execute(http.MethodGet, uri, nil, nil) 54 } 55 56 // GetTestWithExecution returns single test by id with execution 57 func (c TestClient) GetTestWithExecution(id string) (test testkube.TestWithExecution, err error) { 58 uri := c.testWithExecutionTransport.GetURI("/test-with-executions/%s", id) 59 return c.testWithExecutionTransport.Execute(http.MethodGet, uri, nil, nil) 60 } 61 62 // ListTests list all tests 63 func (c TestClient) ListTests(selector string) (tests testkube.Tests, err error) { 64 uri := c.testTransport.GetURI("/tests") 65 params := map[string]string{ 66 "selector": selector, 67 } 68 69 return c.testTransport.ExecuteMultiple(http.MethodGet, uri, nil, params) 70 } 71 72 // ListTestWithExecutionSummaries list all test with execution summaries 73 func (c TestClient) ListTestWithExecutionSummaries(selector string) (testWithExecutionSummaries testkube.TestWithExecutionSummaries, err error) { 74 uri := c.testWithExecutionSummaryTransport.GetURI("/test-with-executions") 75 params := map[string]string{ 76 "selector": selector, 77 } 78 79 return c.testWithExecutionSummaryTransport.ExecuteMultiple(http.MethodGet, uri, nil, params) 80 } 81 82 // CreateTest creates new Test Custom Resource 83 func (c TestClient) CreateTest(options UpsertTestOptions) (test testkube.Test, err error) { 84 uri := c.testTransport.GetURI("/tests") 85 request := testkube.TestUpsertRequest(options) 86 87 body, err := json.Marshal(request) 88 if err != nil { 89 return test, err 90 } 91 92 return c.testTransport.Execute(http.MethodPost, uri, body, nil) 93 } 94 95 // UpdateTest updates Test Custom Resource 96 func (c TestClient) UpdateTest(options UpdateTestOptions) (test testkube.Test, err error) { 97 name := "" 98 if options.Name != nil { 99 name = *options.Name 100 } 101 102 uri := c.testTransport.GetURI("/tests/%s", name) 103 request := testkube.TestUpdateRequest(options) 104 105 body, err := json.Marshal(request) 106 if err != nil { 107 return test, err 108 } 109 110 return c.testTransport.Execute(http.MethodPatch, uri, body, nil) 111 } 112 113 // DeleteTests deletes all tests 114 func (c TestClient) DeleteTests(selector string) error { 115 uri := c.testTransport.GetURI("/tests") 116 return c.testTransport.Delete(uri, selector, true) 117 } 118 119 // DeleteTest deletes single test by name 120 func (c TestClient) DeleteTest(name string) error { 121 if name == "" { 122 return fmt.Errorf("test name '%s' is not valid", name) 123 } 124 125 uri := c.testTransport.GetURI("/tests/%s", name) 126 return c.testTransport.Delete(uri, "", true) 127 } 128 129 // GetExecution returns test execution by excution id 130 func (c TestClient) GetExecution(executionID string) (execution testkube.Execution, err error) { 131 uri := c.executionTransport.GetURI("/executions/%s", executionID) 132 return c.executionTransport.Execute(http.MethodGet, uri, nil, nil) 133 } 134 135 // ExecuteTest starts test execution, reads data and returns ID 136 // execution is started asynchronously client can check later for results 137 func (c TestClient) ExecuteTest(id, executionName string, options ExecuteTestOptions) (execution testkube.Execution, err error) { 138 uri := c.executionTransport.GetURI("/tests/%s/executions", id) 139 request := testkube.ExecutionRequest{ 140 Name: executionName, 141 IsVariablesFileUploaded: options.IsVariablesFileUploaded, 142 VariablesFile: options.ExecutionVariablesFileContent, 143 Variables: options.ExecutionVariables, 144 Envs: options.Envs, 145 Command: options.Command, 146 Args: options.Args, 147 ArgsMode: options.ArgsMode, 148 SecretEnvs: options.SecretEnvs, 149 HttpProxy: options.HTTPProxy, 150 HttpsProxy: options.HTTPSProxy, 151 ExecutionLabels: options.ExecutionLabels, 152 Image: options.Image, 153 Uploads: options.Uploads, 154 BucketName: options.BucketName, 155 ArtifactRequest: options.ArtifactRequest, 156 JobTemplate: options.JobTemplate, 157 JobTemplateReference: options.JobTemplateReference, 158 ContentRequest: options.ContentRequest, 159 PreRunScript: options.PreRunScriptContent, 160 PostRunScript: options.PostRunScriptContent, 161 ExecutePostRunScriptBeforeScraping: options.ExecutePostRunScriptBeforeScraping, 162 SourceScripts: options.SourceScripts, 163 ScraperTemplate: options.ScraperTemplate, 164 ScraperTemplateReference: options.ScraperTemplateReference, 165 PvcTemplate: options.PvcTemplate, 166 PvcTemplateReference: options.PvcTemplateReference, 167 NegativeTest: options.NegativeTest, 168 IsNegativeTestChangedOnRun: options.IsNegativeTestChangedOnRun, 169 EnvConfigMaps: options.EnvConfigMaps, 170 EnvSecrets: options.EnvSecrets, 171 RunningContext: options.RunningContext, 172 SlavePodRequest: options.SlavePodRequest, 173 ExecutionNamespace: options.ExecutionNamespace, 174 } 175 176 body, err := json.Marshal(request) 177 if err != nil { 178 return execution, err 179 } 180 181 return c.executionTransport.Execute(http.MethodPost, uri, body, nil) 182 } 183 184 // ExecuteTests starts test executions, reads data and returns IDs 185 // executions are started asynchronously client can check later for results 186 func (c TestClient) ExecuteTests(selector string, concurrencyLevel int, options ExecuteTestOptions) (executions []testkube.Execution, err error) { 187 uri := c.executionTransport.GetURI("/executions") 188 request := testkube.ExecutionRequest{ 189 IsVariablesFileUploaded: options.IsVariablesFileUploaded, 190 VariablesFile: options.ExecutionVariablesFileContent, 191 Variables: options.ExecutionVariables, 192 Envs: options.Envs, 193 Command: options.Command, 194 Args: options.Args, 195 ArgsMode: options.ArgsMode, 196 SecretEnvs: options.SecretEnvs, 197 HttpProxy: options.HTTPProxy, 198 HttpsProxy: options.HTTPSProxy, 199 Uploads: options.Uploads, 200 BucketName: options.BucketName, 201 ArtifactRequest: options.ArtifactRequest, 202 JobTemplate: options.JobTemplate, 203 JobTemplateReference: options.JobTemplateReference, 204 ContentRequest: options.ContentRequest, 205 PreRunScript: options.PreRunScriptContent, 206 PostRunScript: options.PostRunScriptContent, 207 ExecutePostRunScriptBeforeScraping: options.ExecutePostRunScriptBeforeScraping, 208 SourceScripts: options.SourceScripts, 209 ScraperTemplate: options.ScraperTemplate, 210 ScraperTemplateReference: options.ScraperTemplateReference, 211 PvcTemplate: options.PvcTemplate, 212 PvcTemplateReference: options.PvcTemplateReference, 213 NegativeTest: options.NegativeTest, 214 IsNegativeTestChangedOnRun: options.IsNegativeTestChangedOnRun, 215 RunningContext: options.RunningContext, 216 SlavePodRequest: options.SlavePodRequest, 217 ExecutionNamespace: options.ExecutionNamespace, 218 } 219 220 body, err := json.Marshal(request) 221 if err != nil { 222 return executions, err 223 } 224 225 params := map[string]string{ 226 "selector": selector, 227 "concurrency": strconv.Itoa(concurrencyLevel), 228 } 229 230 return c.executionTransport.ExecuteMultiple(http.MethodPost, uri, body, params) 231 } 232 233 // AbortExecution aborts execution by testId and id 234 func (c TestClient) AbortExecution(testID, id string) error { 235 uri := c.executionTransport.GetURI("/tests/%s/executions/%s", testID, id) 236 return c.executionTransport.ExecuteMethod(http.MethodPatch, uri, "", false) 237 } 238 239 // AbortExecutions aborts all the executions of a test 240 func (c TestClient) AbortExecutions(testID string) error { 241 uri := c.executionTransport.GetURI("/tests/%s/abort", testID) 242 return c.executionTransport.ExecuteMethod(http.MethodPost, uri, "", false) 243 } 244 245 // ListExecutions list all executions for given test name 246 func (c TestClient) ListExecutions(id string, limit int, selector string) (executions testkube.ExecutionsResult, err error) { 247 uri := c.executionsResultTransport.GetURI("/executions/") 248 if id != "" { 249 uri = c.executionsResultTransport.GetURI(fmt.Sprintf("/tests/%s/executions", id)) 250 } 251 252 params := map[string]string{ 253 "selector": selector, 254 "pageSize": fmt.Sprintf("%d", limit), 255 } 256 257 return c.executionsResultTransport.Execute(http.MethodGet, uri, nil, params) 258 } 259 260 // Logs returns logs stream from job pods, based on job pods logs 261 func (c TestClient) Logs(id string) (logs chan output.Output, err error) { 262 logs = make(chan output.Output) 263 uri := c.testTransport.GetURI("/executions/%s/logs", id) 264 err = c.testTransport.GetLogs(uri, logs) 265 return logs, err 266 } 267 268 // LogsV2 returns logs version 2 stream from log sever, based on job pods logs 269 func (c TestClient) LogsV2(id string) (logs chan events.Log, err error) { 270 logs = make(chan events.Log) 271 uri := c.testTransport.GetURI("/executions/%s/logs/v2", id) 272 err = c.testTransport.GetLogsV2(uri, logs) 273 return logs, err 274 } 275 276 // GetExecutionArtifacts returns execution artifacts 277 func (c TestClient) GetExecutionArtifacts(executionID string) (artifacts testkube.Artifacts, err error) { 278 uri := c.artifactTransport.GetURI("/executions/%s/artifacts", executionID) 279 return c.artifactTransport.ExecuteMultiple(http.MethodGet, uri, nil, nil) 280 } 281 282 // DownloadFile downloads file 283 func (c TestClient) DownloadFile(executionID, fileName, destination string) (artifact string, err error) { 284 uri := c.executionTransport.GetURI("/executions/%s/artifacts/%s", executionID, url.QueryEscape(fileName)) 285 return c.executionTransport.GetFile(uri, fileName, destination, nil) 286 } 287 288 // DownloadArchive downloads archive 289 func (c TestClient) DownloadArchive(executionID, destination string, masks []string) (archive string, err error) { 290 uri := c.executionTransport.GetURI("/executions/%s/artifact-archive", executionID) 291 return c.executionTransport.GetFile(uri, fmt.Sprintf("%s.tar.gz", executionID), destination, map[string][]string{"mask": masks}) 292 } 293 294 // GetServerInfo returns server info 295 func (c TestClient) GetServerInfo() (info testkube.ServerInfo, err error) { 296 uri := c.serverInfoTransport.GetURI("/info") 297 return c.serverInfoTransport.Execute(http.MethodGet, uri, nil, nil) 298 } 299 300 func (c TestClient) GetDebugInfo() (debugInfo testkube.DebugInfo, err error) { 301 uri := c.debugInfoTransport.GetURI("/debug") 302 return c.debugInfoTransport.Execute(http.MethodGet, uri, nil, nil) 303 }