github.com/kubeshop/testkube@v1.17.23/cmd/kubectl-testkube/commands/common/render/common.go (about)

     1  package render
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  
     9  	"gopkg.in/yaml.v2"
    10  
    11  	"github.com/kubeshop/testkube/pkg/api/v1/client"
    12  	"github.com/kubeshop/testkube/pkg/api/v1/testkube"
    13  	"github.com/kubeshop/testkube/pkg/ui"
    14  	"github.com/kubeshop/testkube/pkg/utils"
    15  )
    16  
    17  type OutputType string
    18  
    19  const (
    20  	OutputGoTemplate OutputType = "go"
    21  	OutputJSON       OutputType = "json"
    22  	OutputYAML       OutputType = "yaml"
    23  	OutputPretty     OutputType = "pretty"
    24  )
    25  
    26  type CliObjRenderer func(client client.Client, ui *ui.UI, obj interface{}) error
    27  
    28  func RenderJSON(obj interface{}, w io.Writer) error {
    29  	return json.NewEncoder(w).Encode(obj)
    30  }
    31  
    32  func RenderYaml(obj interface{}, w io.Writer) error {
    33  	return yaml.NewEncoder(w).Encode(obj)
    34  }
    35  
    36  func RenderGoTemplate(item interface{}, w io.Writer, tpl string) error {
    37  	tmpl, err := utils.NewTemplate("result").Parse(tpl)
    38  	if err != nil {
    39  		return err
    40  	}
    41  
    42  	return tmpl.Execute(w, item)
    43  }
    44  
    45  func RenderGoTemplateList(list []interface{}, w io.Writer, tpl string) error {
    46  	tmpl, err := utils.NewTemplate("result").Parse(tpl)
    47  	if err != nil {
    48  		return err
    49  	}
    50  
    51  	for _, item := range list {
    52  		err := tmpl.Execute(w, item)
    53  		if err != nil {
    54  			return err
    55  		}
    56  	}
    57  
    58  	return nil
    59  }
    60  
    61  func RenderPrettyList(obj ui.TableData, w io.Writer) error {
    62  	ui.NL()
    63  	ui.Table(obj, w)
    64  	ui.NL()
    65  	return nil
    66  }
    67  
    68  func RenderExecutionResult(client client.Client, execution *testkube.Execution, logsOnly bool, showLogs bool) error {
    69  	result := execution.ExecutionResult
    70  	if result == nil {
    71  		ui.Errf("got execution without `Result`")
    72  		return nil
    73  	}
    74  
    75  	info, err := client.GetServerInfo()
    76  	ui.ExitOnError("getting server info", err)
    77  
    78  	ui.NL()
    79  	switch true {
    80  	case result.IsQueued():
    81  		ui.Warn("Test queued for execution")
    82  
    83  	case result.IsRunning():
    84  		ui.Warn("Test execution started")
    85  
    86  	case result.IsPassed():
    87  		if showLogs {
    88  			PrintLogs(client, info, *execution)
    89  		}
    90  
    91  		if !logsOnly {
    92  			duration := execution.EndTime.Sub(execution.StartTime)
    93  			ui.Success("Test execution completed with success in " + duration.String())
    94  			PrintExecutionURIs(execution, info.DashboardUri)
    95  		}
    96  
    97  	case result.IsAborted():
    98  		ui.Warn("Test execution aborted")
    99  
   100  	case result.IsTimeout():
   101  		ui.Warn("Test execution timeout")
   102  
   103  	case result.IsFailed():
   104  		if showLogs {
   105  			PrintLogs(client, info, *execution)
   106  		}
   107  
   108  		if logsOnly {
   109  			ui.Info(result.ErrorMessage)
   110  		} else {
   111  			ui.UseStderr()
   112  			ui.Warn("Test execution failed:\n")
   113  			ui.Errf(result.ErrorMessage)
   114  			PrintExecutionURIs(execution, info.DashboardUri)
   115  		}
   116  
   117  		return errors.New(result.ErrorMessage)
   118  
   119  	default:
   120  		if logsOnly {
   121  			ui.Info(result.ErrorMessage)
   122  		} else {
   123  			ui.UseStderr()
   124  			ui.Warn("Test execution status unknown:\n")
   125  			ui.Errf(result.ErrorMessage)
   126  		}
   127  
   128  		if showLogs {
   129  			PrintLogs(client, info, *execution)
   130  		}
   131  		return errors.New(result.ErrorMessage)
   132  	}
   133  
   134  	return nil
   135  }
   136  
   137  func PrintLogs(client client.Client, info testkube.ServerInfo, execution testkube.Execution) {
   138  	if info.Features == nil || !info.Features.LogsV2 {
   139  		// fallback to default logs
   140  		ui.Info(execution.ExecutionResult.Output)
   141  		return
   142  	}
   143  
   144  	logsCh, err := client.LogsV2(execution.Id)
   145  	ui.ExitOnError("getting logs", err)
   146  
   147  	ui.H1("Logs:")
   148  	lastSource := ""
   149  	for log := range logsCh {
   150  
   151  		if log.Source != lastSource {
   152  			ui.H2("source: " + log.Source)
   153  			ui.NL()
   154  			lastSource = log.Source
   155  		}
   156  
   157  		if ui.Verbose {
   158  			ui.Print(log.Time.Format("2006-01-02 15:04:05") + " " + log.Content)
   159  		} else {
   160  			ui.Print(log.Content)
   161  		}
   162  	}
   163  }
   164  
   165  func PrintExecutionURIs(execution *testkube.Execution, dashboardURI string) {
   166  	ui.NL()
   167  	ui.ExecutionLink("Test URI:", fmt.Sprintf("%s/tests/%s", dashboardURI, execution.TestName))
   168  	ui.ExecutionLink("Test Execution URI:", fmt.Sprintf("%s/tests/%s/executions/%s", dashboardURI,
   169  		execution.TestName, execution.Id))
   170  	ui.NL()
   171  }
   172  
   173  func PrintTestSuiteExecutionURIs(execution *testkube.TestSuiteExecution, dashboardURI string) {
   174  	ui.NL()
   175  	testSuiteName := ""
   176  	if execution.TestSuite != nil {
   177  		testSuiteName = execution.TestSuite.Name
   178  	}
   179  
   180  	ui.ExecutionLink("Test Suite URI:", fmt.Sprintf("%s/test-suites/%s", dashboardURI, testSuiteName))
   181  	ui.ExecutionLink("Test Suite Execution URI:", fmt.Sprintf("%s/test-suites/%s/executions/%s", dashboardURI,
   182  		testSuiteName, execution.Id))
   183  	ui.NL()
   184  }