github.com/kubeshop/testkube@v1.17.23/pkg/executor/agent/agent.go (about)

     1  package agent
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"io"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	"github.com/pkg/errors"
    12  
    13  	"github.com/kubeshop/testkube/pkg/api/v1/testkube"
    14  	"github.com/kubeshop/testkube/pkg/envs"
    15  	"github.com/kubeshop/testkube/pkg/executor"
    16  	"github.com/kubeshop/testkube/pkg/executor/output"
    17  	"github.com/kubeshop/testkube/pkg/executor/runner"
    18  )
    19  
    20  // Run starts test runner, test runner can have 3 states
    21  // - pod:success, test execution: success
    22  // - pod:success, test execution: failed
    23  // - pod:failed,  test execution: failed - this one is unusual behaviour
    24  func Run(ctx context.Context, r runner.Runner, args []string) {
    25  
    26  	var test []byte
    27  	var err error
    28  
    29  	stat, _ := os.Stdin.Stat()
    30  	switch {
    31  	case (stat.Mode() & os.ModeCharDevice) == 0:
    32  		test, err = io.ReadAll(os.Stdin)
    33  		if err != nil {
    34  			output.PrintError(os.Stderr, errors.Errorf("can't read stdin input: %v", err))
    35  			os.Exit(1)
    36  		}
    37  	case len(args) > 1:
    38  		test = []byte(args[1])
    39  		hasFileFlag := args[1] == "-f" || args[1] == "--file"
    40  		if hasFileFlag {
    41  			test, err = os.ReadFile(args[2])
    42  			if err != nil {
    43  				output.PrintError(os.Stderr, errors.Errorf("error reading JSON file: %v", err))
    44  				os.Exit(1)
    45  			}
    46  		}
    47  	default:
    48  		output.PrintError(os.Stderr, errors.Errorf("execution json must be provided using stdin, program argument or -f|--file flag"))
    49  		os.Exit(1)
    50  	}
    51  
    52  	e := testkube.Execution{}
    53  
    54  	err = json.Unmarshal(test, &e)
    55  	if err != nil {
    56  		output.PrintError(os.Stderr, errors.Wrap(err, "error unmarshalling execution json"))
    57  		os.Exit(1)
    58  	}
    59  
    60  	params, err := envs.LoadTestkubeVariables()
    61  	if err != nil {
    62  		output.PrintError(os.Stderr, errors.Wrap(err, "error loading env vars"))
    63  		os.Exit(1)
    64  	}
    65  
    66  	if r.GetType().IsMain() {
    67  		envs.PrintParams(params)
    68  	}
    69  
    70  	if r.GetType().IsMain() && e.PreRunScript != "" {
    71  		output.PrintEvent("running prerun script", e.Id)
    72  
    73  		if serr := RunScript(e.PreRunScript, params.WorkingDir); serr != nil {
    74  			output.PrintError(os.Stderr, serr)
    75  			os.Exit(1)
    76  		}
    77  	}
    78  
    79  	// get event only when it's test run in main container
    80  	if r.GetType().IsMain() {
    81  		output.PrintEvent("running test", e.Id)
    82  	}
    83  
    84  	result, err := r.Run(ctx, e)
    85  
    86  	if r.GetType().IsMain() && e.PostRunScript != "" && !e.ExecutePostRunScriptBeforeScraping {
    87  		output.PrintEvent("running postrun script", e.Id)
    88  
    89  		if serr := RunScript(e.PostRunScript, params.WorkingDir); serr != nil {
    90  			output.PrintError(os.Stderr, serr)
    91  			os.Exit(1)
    92  		}
    93  	}
    94  
    95  	if err != nil {
    96  		output.PrintError(os.Stderr, err)
    97  		os.Exit(1)
    98  	}
    99  
   100  	if r.GetType().IsMain() {
   101  		output.PrintEvent("test execution finished", e.Id)
   102  		output.PrintResult(result)
   103  	}
   104  
   105  }
   106  
   107  // RunScript runs script
   108  func RunScript(body, workingDir string) error {
   109  	scriptFile, err := os.CreateTemp("", "runscript*.sh")
   110  	if err != nil {
   111  		return err
   112  	}
   113  
   114  	filename := scriptFile.Name()
   115  	if _, err = io.Copy(scriptFile, strings.NewReader(body)); err != nil {
   116  		return err
   117  	}
   118  
   119  	if err = scriptFile.Close(); err != nil {
   120  		return err
   121  	}
   122  
   123  	if err = os.Chmod(filename, 0777); err != nil {
   124  		return err
   125  	}
   126  
   127  	if _, err = executor.Run(workingDir, "/bin/sh", nil, filename); err != nil {
   128  		return err
   129  	}
   130  
   131  	return nil
   132  }
   133  
   134  // GetDefaultWorkingDir gets default working directory
   135  func GetDefaultWorkingDir(dataDir string, e testkube.Execution) string {
   136  	workingDir := dataDir
   137  	if e.Content != nil {
   138  		isGitFileContentType := e.Content.Type_ == string(testkube.TestContentTypeGitFile)
   139  		isGitDirContentType := e.Content.Type_ == string(testkube.TestContentTypeGitDir)
   140  		isGitContentType := e.Content.Type_ == string(testkube.TestContentTypeGit)
   141  		if isGitFileContentType || isGitDirContentType || isGitContentType {
   142  			workingDir = filepath.Join(dataDir, "repo")
   143  		}
   144  	}
   145  
   146  	return workingDir
   147  }