github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/client/allocrunner/taskrunner/driver_handle.go (about) 1 package taskrunner 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 cstructs "github.com/hashicorp/nomad/client/structs" 9 "github.com/hashicorp/nomad/helper" 10 "github.com/hashicorp/nomad/nomad/structs" 11 "github.com/hashicorp/nomad/plugins/drivers" 12 ) 13 14 // NewDriverHandle returns a handle for task operations on a specific task 15 func NewDriverHandle( 16 driver drivers.DriverPlugin, 17 taskID string, 18 task *structs.Task, 19 maxKillTimeout time.Duration, 20 net *drivers.DriverNetwork) *DriverHandle { 21 return &DriverHandle{ 22 driver: driver, 23 net: net, 24 taskID: taskID, 25 killSignal: task.KillSignal, 26 killTimeout: helper.Min(task.KillTimeout, maxKillTimeout), 27 } 28 } 29 30 // DriverHandle encapsulates a driver plugin client and task identifier and exposes 31 // an api to perform driver operations on the task 32 type DriverHandle struct { 33 driver drivers.DriverPlugin 34 net *drivers.DriverNetwork 35 taskID string 36 killSignal string 37 killTimeout time.Duration 38 } 39 40 func (h *DriverHandle) ID() string { 41 return h.taskID 42 } 43 44 func (h *DriverHandle) WaitCh(ctx context.Context) (<-chan *drivers.ExitResult, error) { 45 return h.driver.WaitTask(ctx, h.taskID) 46 } 47 48 // SetKillSignal allows overriding the signal sent to kill the task. 49 func (h *DriverHandle) SetKillSignal(signal string) { 50 h.killSignal = signal 51 } 52 53 func (h *DriverHandle) Kill() error { 54 return h.driver.StopTask(h.taskID, h.killTimeout, h.killSignal) 55 } 56 57 func (h *DriverHandle) Stats(ctx context.Context, interval time.Duration) (<-chan *cstructs.TaskResourceUsage, error) { 58 return h.driver.TaskStats(ctx, h.taskID, interval) 59 } 60 61 func (h *DriverHandle) Signal(s string) error { 62 return h.driver.SignalTask(h.taskID, s) 63 } 64 65 // Exec is the handled used by client endpoint handler to invoke the appropriate task driver exec. 66 func (h *DriverHandle) Exec(timeout time.Duration, cmd string, args []string) ([]byte, int, error) { 67 command := append([]string{cmd}, args...) 68 res, err := h.driver.ExecTask(h.taskID, command, timeout) 69 if err != nil { 70 return nil, 0, err 71 } 72 return res.Stdout, res.ExitResult.ExitCode, res.ExitResult.Err 73 } 74 75 // ExecStreaming is the handled used by client endpoint handler to invoke the appropriate task driver exec. 76 // while allowing to stream input and output 77 func (h *DriverHandle) ExecStreaming(ctx context.Context, 78 command []string, 79 tty bool, 80 stream drivers.ExecTaskStream) error { 81 82 if impl, ok := h.driver.(drivers.ExecTaskStreamingRawDriver); ok { 83 return impl.ExecTaskStreamingRaw(ctx, h.taskID, command, tty, stream) 84 } 85 86 d, ok := h.driver.(drivers.ExecTaskStreamingDriver) 87 if !ok { 88 return fmt.Errorf("task driver does not support exec") 89 } 90 91 execOpts, doneCh := drivers.StreamToExecOptions( 92 ctx, command, tty, stream) 93 94 result, err := d.ExecTaskStreaming(ctx, h.taskID, execOpts) 95 if err != nil { 96 return err 97 } 98 99 execOpts.Stdout.Close() 100 execOpts.Stderr.Close() 101 102 select { 103 case err = <-doneCh: 104 case <-ctx.Done(): 105 err = fmt.Errorf("exec task timed out: %v", ctx.Err()) 106 } 107 108 if err != nil { 109 return err 110 } 111 112 return stream.Send(drivers.NewExecStreamingResponseExit(result.ExitCode)) 113 } 114 115 func (h *DriverHandle) Network() *drivers.DriverNetwork { 116 return h.net 117 }