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