github.com/hernad/nomad@v1.6.112/drivers/nix/_executor/grpc_server.go (about) 1 package executor 2 3 import ( 4 "context" 5 "fmt" 6 "syscall" 7 "time" 8 9 "github.com/golang/protobuf/ptypes" 10 "google.golang.org/grpc/codes" 11 "google.golang.org/grpc/status" 12 13 "github.com/hernad/nomad/drivers/shared/executor/proto" 14 "github.com/hernad/nomad/nomad/structs" 15 "github.com/hernad/nomad/plugins/drivers" 16 sproto "github.com/hernad/nomad/plugins/shared/structs/proto" 17 ) 18 19 type grpcExecutorServer struct { 20 impl Executor 21 } 22 23 func (s *grpcExecutorServer) Launch(ctx context.Context, req *proto.LaunchRequest) (*proto.LaunchResponse, error) { 24 ps, err := s.impl.Launch(&ExecCommand{ 25 Cmd: req.Cmd, 26 Args: req.Args, 27 Resources: drivers.ResourcesFromProto(req.Resources), 28 StdoutPath: req.StdoutPath, 29 StderrPath: req.StderrPath, 30 Env: req.Env, 31 User: req.User, 32 TaskDir: req.TaskDir, 33 ResourceLimits: req.ResourceLimits, 34 BasicProcessCgroup: req.BasicProcessCgroup, 35 NoPivotRoot: req.NoPivotRoot, 36 Mounts: drivers.MountsFromProto(req.Mounts), 37 Devices: drivers.DevicesFromProto(req.Devices), 38 NetworkIsolation: drivers.NetworkIsolationSpecFromProto(req.NetworkIsolation), 39 ModePID: req.DefaultPidMode, 40 ModeIPC: req.DefaultIpcMode, 41 Capabilities: req.Capabilities, 42 }) 43 44 if err != nil { 45 return nil, err 46 } 47 48 process, err := processStateToProto(ps) 49 if err != nil { 50 return nil, err 51 } 52 53 return &proto.LaunchResponse{ 54 Process: process, 55 }, nil 56 } 57 58 func (s *grpcExecutorServer) Wait(ctx context.Context, req *proto.WaitRequest) (*proto.WaitResponse, error) { 59 ps, err := s.impl.Wait(ctx) 60 if err != nil { 61 return nil, err 62 } 63 64 process, err := processStateToProto(ps) 65 if err != nil { 66 return nil, err 67 } 68 69 return &proto.WaitResponse{ 70 Process: process, 71 }, nil 72 } 73 74 func (s *grpcExecutorServer) Shutdown(ctx context.Context, req *proto.ShutdownRequest) (*proto.ShutdownResponse, error) { 75 if err := s.impl.Shutdown(req.Signal, time.Duration(req.GracePeriod)); err != nil { 76 return nil, err 77 } 78 79 return &proto.ShutdownResponse{}, nil 80 } 81 82 func (s *grpcExecutorServer) UpdateResources(ctx context.Context, req *proto.UpdateResourcesRequest) (*proto.UpdateResourcesResponse, error) { 83 if err := s.impl.UpdateResources(drivers.ResourcesFromProto(req.Resources)); err != nil { 84 return nil, err 85 } 86 87 return &proto.UpdateResourcesResponse{}, nil 88 } 89 90 func (s *grpcExecutorServer) Version(context.Context, *proto.VersionRequest) (*proto.VersionResponse, error) { 91 v, err := s.impl.Version() 92 if err != nil { 93 return nil, err 94 } 95 96 return &proto.VersionResponse{ 97 Version: v.Version, 98 }, nil 99 } 100 101 func (s *grpcExecutorServer) Stats(req *proto.StatsRequest, stream proto.Executor_StatsServer) error { 102 interval := time.Duration(req.Interval) 103 if interval == 0 { 104 interval = time.Second 105 } 106 107 outCh, err := s.impl.Stats(stream.Context(), interval) 108 if err != nil { 109 if rec, ok := err.(structs.Recoverable); ok { 110 st := status.New(codes.FailedPrecondition, rec.Error()) 111 st, err := st.WithDetails(&sproto.RecoverableError{Recoverable: rec.IsRecoverable()}) 112 if err != nil { 113 // If this error, it will always error 114 panic(err) 115 } 116 return st.Err() 117 } 118 return err 119 } 120 121 for resp := range outCh { 122 pbStats, err := drivers.TaskStatsToProto(resp) 123 if err != nil { 124 return err 125 } 126 127 presp := &proto.StatsResponse{ 128 Stats: pbStats, 129 } 130 131 // Send the stats 132 if err := stream.Send(presp); err != nil { 133 return err 134 } 135 } 136 137 return nil 138 } 139 140 func (s *grpcExecutorServer) Signal(ctx context.Context, req *proto.SignalRequest) (*proto.SignalResponse, error) { 141 sig := syscall.Signal(req.Signal) 142 if err := s.impl.Signal(sig); err != nil { 143 return nil, err 144 } 145 return &proto.SignalResponse{}, nil 146 } 147 148 func (s *grpcExecutorServer) Exec(ctx context.Context, req *proto.ExecRequest) (*proto.ExecResponse, error) { 149 deadline, err := ptypes.Timestamp(req.Deadline) 150 if err != nil { 151 return nil, err 152 } 153 154 out, exit, err := s.impl.Exec(deadline, req.Cmd, req.Args) 155 if err != nil { 156 return nil, err 157 } 158 159 return &proto.ExecResponse{ 160 Output: out, 161 ExitCode: int32(exit), 162 }, nil 163 } 164 165 func (s *grpcExecutorServer) ExecStreaming(server proto.Executor_ExecStreamingServer) error { 166 msg, err := server.Recv() 167 if err != nil { 168 return fmt.Errorf("failed to receive initial message: %v", err) 169 } 170 171 if msg.Setup == nil { 172 return fmt.Errorf("first message should always be setup") 173 } 174 175 return s.impl.ExecStreaming(server.Context(), 176 msg.Setup.Command, msg.Setup.Tty, 177 server) 178 }