e2erunner.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /*
  2. Copyright 2019 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package main
  14. import (
  15. "io"
  16. "io/ioutil"
  17. "log"
  18. "os"
  19. "os/signal"
  20. "path/filepath"
  21. "github.com/pkg/errors"
  22. )
  23. func main() {
  24. env := envWithDefaults(map[string]string{
  25. resultsDirEnvKey: defaultResultsDir,
  26. skipEnvKey: defaultSkip,
  27. focusEnvKey: defaultFocus,
  28. providerEnvKey: defaultProvider,
  29. parallelEnvKey: defaultParallel,
  30. ginkgoEnvKey: defaultGinkgoBinary,
  31. testBinEnvKey: defaultTestBinary,
  32. })
  33. if err := configureAndRunWithEnv(env); err != nil {
  34. log.Fatal(err)
  35. }
  36. }
  37. // configureAndRunWithEnv uses the given environment to configure and then start the test run.
  38. // It will handle TERM signals gracefully and kill the test process and will
  39. // save the logs/results to the location specified via the RESULTS_DIR environment
  40. // variable.
  41. func configureAndRunWithEnv(env Getenver) error {
  42. // Ensure we save results regardless of other errors. This helps any
  43. // consumer who may be polling for the results.
  44. resultsDir := env.Getenv(resultsDirEnvKey)
  45. defer saveResults(resultsDir)
  46. // Print the output to stdout and a logfile which will be returned
  47. // as part of the results tarball.
  48. logFilePath := filepath.Join(resultsDir, logFileName)
  49. logFile, err := os.Create(logFilePath)
  50. if err != nil {
  51. return errors.Wrapf(err, "failed to create log file %v", logFilePath)
  52. }
  53. mw := io.MultiWriter(os.Stdout, logFile)
  54. cmd := getCmd(env, mw)
  55. log.Printf("Running command:\n%v\n", cmdInfo(cmd))
  56. err = cmd.Start()
  57. if err != nil {
  58. return errors.Wrap(err, "starting command")
  59. }
  60. // Handle signals and shutdown process gracefully.
  61. go setupSigHandler(cmd.Process.Pid)
  62. return errors.Wrap(cmd.Wait(), "running command")
  63. }
  64. // setupSigHandler will kill the process identified by the given PID if it
  65. // gets a TERM signal.
  66. func setupSigHandler(pid int) {
  67. c := make(chan os.Signal, 1)
  68. signal.Notify(c, os.Interrupt)
  69. // Block until a signal is received.
  70. log.Println("Now listening for interrupts")
  71. s := <-c
  72. log.Printf("Got signal: %v. Shutting down test process (PID: %v)\n", s, pid)
  73. p, err := os.FindProcess(pid)
  74. if err != nil {
  75. log.Printf("Could not find process %v to shut down.\n", pid)
  76. return
  77. }
  78. if err := p.Signal(s); err != nil {
  79. log.Printf("Failed to signal test process to terminate: %v\n", err)
  80. return
  81. }
  82. log.Printf("Signalled process %v to terminate successfully.\n", pid)
  83. }
  84. // saveResults will tar the results directory and write the resulting tarball path
  85. // into the donefile.
  86. func saveResults(resultsDir string) error {
  87. log.Printf("Saving results at %v\n", resultsDir)
  88. err := tarDir(resultsDir, filepath.Join(resultsDir, resultsTarballName))
  89. if err != nil {
  90. return errors.Wrapf(err, "tar directory %v", resultsDir)
  91. }
  92. doneFile := filepath.Join(resultsDir, doneFileName)
  93. resultsTarball := filepath.Join(resultsDir, resultsTarballName)
  94. resultsTarball, err = filepath.Abs(resultsTarball)
  95. if err != nil {
  96. return errors.Wrapf(err, "failed to find absolute path for %v", resultsTarball)
  97. }
  98. return errors.Wrap(
  99. ioutil.WriteFile(doneFile, []byte(resultsTarball), os.FileMode(0777)),
  100. "writing donefile",
  101. )
  102. }