exec_utils.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. Copyright 2016 The Rook Authors. All rights reserved.
  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 utils
  14. import (
  15. "bufio"
  16. "bytes"
  17. "fmt"
  18. "os/exec"
  19. "strings"
  20. "github.com/coreos/pkg/capnslog"
  21. utilexec "github.com/rook/rook/pkg/util/exec"
  22. )
  23. var logger = capnslog.NewPackageLogger("github.com/rook/rook", "testutil")
  24. // CommandArgs is a wrapper for cmd args
  25. type CommandArgs struct {
  26. Command string
  27. CmdArgs []string
  28. PipeToStdIn string
  29. EnvironmentVariable []string
  30. }
  31. // CommandOut is a wrapper for cmd out returned after executing command args
  32. type CommandOut struct {
  33. StdOut string
  34. StdErr string
  35. ExitCode int
  36. Err error
  37. }
  38. // ExecuteCommand executes a os command with stdin and returns output
  39. func ExecuteCommand(cmdStruct CommandArgs) CommandOut {
  40. logger.Infof("Running %s %v", cmdStruct.Command, cmdStruct.CmdArgs)
  41. var outBuffer, errBuffer bytes.Buffer
  42. cmd := exec.Command(cmdStruct.Command, cmdStruct.CmdArgs...) //nolint:gosec // We safely suppress gosec in tests file
  43. cmd.Env = append(cmd.Env, cmdStruct.EnvironmentVariable...)
  44. stdOut, err := cmd.StdoutPipe()
  45. if err != nil {
  46. return CommandOut{StdErr: errBuffer.String(), StdOut: outBuffer.String(), Err: err}
  47. }
  48. stdin, err := cmd.StdinPipe()
  49. if err != nil {
  50. return CommandOut{Err: err}
  51. }
  52. defer stdOut.Close()
  53. scanner := bufio.NewScanner(stdOut)
  54. go func() {
  55. for scanner.Scan() {
  56. outBuffer.WriteString(scanner.Text())
  57. fmt.Printf("%s\n", scanner.Text())
  58. }
  59. }()
  60. stdErr, err := cmd.StderrPipe()
  61. if err != nil {
  62. return CommandOut{StdErr: errBuffer.String(), StdOut: outBuffer.String(), Err: err}
  63. }
  64. defer stdErr.Close()
  65. stdErrScanner := bufio.NewScanner(stdErr)
  66. go func() {
  67. for stdErrScanner.Scan() {
  68. txt := stdErrScanner.Text()
  69. if !strings.Contains(txt, "no buildable Go source files in") {
  70. errBuffer.WriteString(txt)
  71. fmt.Printf("%s\n", txt)
  72. }
  73. }
  74. }()
  75. err = cmd.Start()
  76. if err != nil {
  77. return CommandOut{StdErr: errBuffer.String(), StdOut: outBuffer.String(), Err: err}
  78. }
  79. if cmdStruct.PipeToStdIn != "" {
  80. _, err = stdin.Write([]byte(cmdStruct.PipeToStdIn))
  81. if err != nil {
  82. return CommandOut{StdErr: errBuffer.String(), StdOut: outBuffer.String(), Err: err}
  83. }
  84. stdin.Close()
  85. }
  86. err = cmd.Wait()
  87. out := CommandOut{StdErr: errBuffer.String(), StdOut: outBuffer.String()}
  88. if err != nil {
  89. out.Err = err
  90. if code, ok := utilexec.ExitStatus(err); ok {
  91. out.ExitCode = code
  92. }
  93. }
  94. return out
  95. }