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  }