executor.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package executor
  2. import (
  3. pb "github.com/jamesread/OliveTin/gen/grpc"
  4. config "github.com/jamesread/OliveTin/internal/config"
  5. log "github.com/sirupsen/logrus"
  6. "context"
  7. "errors"
  8. "os/exec"
  9. "time"
  10. )
  11. // ExecAction executes an action.
  12. func ExecAction(cfg *config.Config, action string) *pb.StartActionResponse {
  13. log.WithFields(log.Fields{
  14. "actionName": action,
  15. }).Infof("StartAction")
  16. actualAction, err := findAction(cfg, action)
  17. if err != nil {
  18. log.Errorf("Error finding action %s, %s", err, action)
  19. return &pb.StartActionResponse{
  20. TimedOut: false,
  21. }
  22. }
  23. return execAction(cfg, actualAction)
  24. }
  25. func execAction(cfg *config.Config, actualAction *config.ActionButton) *pb.StartActionResponse {
  26. res := &pb.StartActionResponse{}
  27. res.TimedOut = false
  28. log.WithFields(log.Fields{
  29. "title": actualAction.Title,
  30. "timeout": actualAction.Timeout,
  31. }).Infof("Found action")
  32. ctx, cancel := context.WithTimeout(context.Background(), time.Duration(actualAction.Timeout) * time.Second)
  33. defer cancel()
  34. cmd := exec.CommandContext(ctx, "sh", "-c", actualAction.Shell)
  35. stdout, stderr := cmd.Output()
  36. res.ExitCode = int32(cmd.ProcessState.ExitCode())
  37. res.Stdout = string(stdout)
  38. if stderr == nil {
  39. res.Stderr = ""
  40. } else {
  41. res.Stderr = stderr.Error()
  42. }
  43. if ctx.Err() == context.DeadlineExceeded {
  44. res.TimedOut = true
  45. }
  46. log.WithFields(log.Fields{
  47. "stdout": res.Stdout,
  48. "stderr": res.Stderr,
  49. "timedOut": res.TimedOut,
  50. "exit": res.ExitCode,
  51. }).Infof("Finished command.")
  52. return res
  53. }
  54. func sanitizeAction(action *config.ActionButton) {
  55. if action.Timeout < 3 {
  56. action.Timeout = 3
  57. }
  58. }
  59. func findAction(cfg *config.Config, actionTitle string) (*config.ActionButton, error) {
  60. for _, action := range cfg.ActionButtons {
  61. if action.Title == actionTitle {
  62. sanitizeAction(&action)
  63. return &action, nil
  64. }
  65. }
  66. return nil, errors.New("Action not found")
  67. }