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 }