diff --git a/integration/client.go b/integration/client.go index bb735168..a7eff02d 100644 --- a/integration/client.go +++ b/integration/client.go @@ -712,3 +712,17 @@ func (c *HyperClient) Ping() (*types.PingResponse, error) { return resp, nil } + +// ContainerSignal sends a signal to specified container of specified pod +func (c *HyperClient) ContainerSignal(podID, containerID string, signal int64) error { + _, err := c.client.ContainerSignal(c.ctx, &types.ContainerSignalRequest{ + PodID: podID, + ContainerID: containerID, + Signal: signal, + }) + if err != nil { + return err + } + + return nil +} diff --git a/integration/hyper_test.go b/integration/hyper_test.go index 4cf16d93..f80aa6b7 100644 --- a/integration/hyper_test.go +++ b/integration/hyper_test.go @@ -494,3 +494,41 @@ func (s *TestSuite) TestPing(c *C) { c.Assert(err, IsNil) c.Logf("Got HyperdStats %v", resp) } + +func (s *TestSuite) TestSendContainerSignal(c *C) { + sigKill := int64(9) + spec := types.UserPod{ + Id: "busybox", + } + + pod, err := s.client.CreatePod(&spec) + c.Assert(err, IsNil) + c.Logf("Pod created: %s", pod) + + defer func() { + err = s.client.RemovePod(pod) + c.Assert(err, IsNil) + }() + + container, err := s.client.CreateContainer(pod, &types.UserContainer{Image: "busybox"}) + c.Assert(err, IsNil) + c.Logf("Container created: %s", container) + + err = s.client.StartPod(pod) + c.Assert(err, IsNil) + + containerInfo, err := s.client.GetContainerInfo(container) + c.Assert(err, IsNil) + c.Assert(containerInfo.Status.Phase, Equals, "running") + + err = s.client.ContainerSignal(pod, container, sigKill) + c.Assert(err, IsNil) + + exitCode, err := s.client.Wait(container, "", false) + c.Assert(err, IsNil) + c.Assert(exitCode, Equals, int32(137)) + + containerInfo, err = s.client.GetContainerInfo(container) + c.Assert(err, IsNil) + c.Assert(containerInfo.Status.Phase, Equals, "failed") +} diff --git a/serverrpc/container.go b/serverrpc/container.go index 06881b3a..a38bdf34 100644 --- a/serverrpc/container.go +++ b/serverrpc/container.go @@ -66,3 +66,16 @@ func (s *ServerRPC) ContainerRemove(ctx context.Context, req *types.ContainerRem } return &types.ContainerRemoveResponse{}, nil } + +// ContainerSignal sends a singal to specified container of specified pod +func (s *ServerRPC) ContainerSignal(ctx context.Context, req *types.ContainerSignalRequest) (*types.ContainerSignalResponse, error) { + glog.V(3).Infof("ContainerSignal with request %s", req.String()) + + err := s.daemon.KillPodContainers(req.PodID, req.ContainerID, req.Signal) + if err != nil { + glog.Errorf("Kill Container %s of Pod %s with signal %d failed: %v", req.ContainerID, req.PodID, req.Signal, err) + return nil, err + } + + return &types.ContainerSignalResponse{}, nil +} diff --git a/types/types.pb.go b/types/types.pb.go index 52f38bc6..be26cf30 100644 --- a/types/types.pb.go +++ b/types/types.pb.go @@ -133,6 +133,8 @@ It has these top-level messages: PodStatsResponse PingRequest PingResponse + ContainerSignalRequest + ContainerSignalResponse PersistPodLayout PersistPodMeta SandboxPersistInfo @@ -2022,6 +2024,23 @@ func (m *PingResponse) Reset() { *m = PingResponse{} } func (m *PingResponse) String() string { return proto.CompactTextString(m) } func (*PingResponse) ProtoMessage() {} +type ContainerSignalRequest struct { + PodID string `protobuf:"bytes,1,opt,name=podID,proto3" json:"podID,omitempty"` + ContainerID string `protobuf:"bytes,2,opt,name=containerID,proto3" json:"containerID,omitempty"` + Signal int64 `protobuf:"varint,3,opt,name=signal,proto3" json:"signal,omitempty"` +} + +func (m *ContainerSignalRequest) Reset() { *m = ContainerSignalRequest{} } +func (m *ContainerSignalRequest) String() string { return proto.CompactTextString(m) } +func (*ContainerSignalRequest) ProtoMessage() {} + +type ContainerSignalResponse struct { +} + +func (m *ContainerSignalResponse) Reset() { *m = ContainerSignalResponse{} } +func (m *ContainerSignalResponse) String() string { return proto.CompactTextString(m) } +func (*ContainerSignalResponse) ProtoMessage() {} + func init() { proto.RegisterType((*ContainerPort)(nil), "types.ContainerPort") proto.RegisterType((*EnvironmentVar)(nil), "types.EnvironmentVar") @@ -2146,6 +2165,8 @@ func init() { proto.RegisterType((*PodStatsResponse)(nil), "types.PodStatsResponse") proto.RegisterType((*PingRequest)(nil), "types.PingRequest") proto.RegisterType((*PingResponse)(nil), "types.PingResponse") + proto.RegisterType((*ContainerSignalRequest)(nil), "types.ContainerSignalRequest") + proto.RegisterType((*ContainerSignalResponse)(nil), "types.ContainerSignalResponse") proto.RegisterEnum("types.UserContainer_ContainerType", UserContainer_ContainerType_name, UserContainer_ContainerType_value) } @@ -2168,7 +2189,7 @@ type PublicAPIClient interface { PodStart(ctx context.Context, in *PodStartRequest, opts ...grpc.CallOption) (*PodStartResponse, error) // PodStop stops a pod PodStop(ctx context.Context, in *PodStopRequest, opts ...grpc.CallOption) (*PodStopResponse, error) - // PodSignal sends a singal to all containers of specified pod + // PodSignal sends a signal to all containers of specified pod PodSignal(ctx context.Context, in *PodSignalRequest, opts ...grpc.CallOption) (*PodSignalResponse, error) // PodPause pauses a pod PodPause(ctx context.Context, in *PodPauseRequest, opts ...grpc.CallOption) (*PodPauseResponse, error) @@ -2195,7 +2216,8 @@ type PublicAPIClient interface { // ContainerRename renames a container ContainerRename(ctx context.Context, in *ContainerRenameRequest, opts ...grpc.CallOption) (*ContainerRenameResponse, error) // TODO: ContainerCommit commits the changes of the specified container - // TODO: ContainerSignal sends a singla to specified container + // ContainerSignal sends a signal to specified container + ContainerSignal(ctx context.Context, in *ContainerSignalRequest, opts ...grpc.CallOption) (*ContainerSignalResponse, error) // TODO: ContainerLabels updates labels of the specified container // ContainerStop stops the specified container ContainerStop(ctx context.Context, in *ContainerStopRequest, opts ...grpc.CallOption) (*ContainerStopResponse, error) @@ -2433,6 +2455,15 @@ func (c *publicAPIClient) ContainerRename(ctx context.Context, in *ContainerRena return out, nil } +func (c *publicAPIClient) ContainerSignal(ctx context.Context, in *ContainerSignalRequest, opts ...grpc.CallOption) (*ContainerSignalResponse, error) { + out := new(ContainerSignalResponse) + err := grpc.Invoke(ctx, "/types.PublicAPI/ContainerSignal", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *publicAPIClient) ContainerStop(ctx context.Context, in *ContainerStopRequest, opts ...grpc.CallOption) (*ContainerStopResponse, error) { out := new(ContainerStopResponse) err := grpc.Invoke(ctx, "/types.PublicAPI/ContainerStop", in, out, c.cc, opts...) @@ -2682,7 +2713,7 @@ type PublicAPIServer interface { PodStart(context.Context, *PodStartRequest) (*PodStartResponse, error) // PodStop stops a pod PodStop(context.Context, *PodStopRequest) (*PodStopResponse, error) - // PodSignal sends a singal to all containers of specified pod + // PodSignal sends a signal to all containers of specified pod PodSignal(context.Context, *PodSignalRequest) (*PodSignalResponse, error) // PodPause pauses a pod PodPause(context.Context, *PodPauseRequest) (*PodPauseResponse, error) @@ -2709,7 +2740,8 @@ type PublicAPIServer interface { // ContainerRename renames a container ContainerRename(context.Context, *ContainerRenameRequest) (*ContainerRenameResponse, error) // TODO: ContainerCommit commits the changes of the specified container - // TODO: ContainerSignal sends a singla to specified container + // ContainerSignal sends a signal to specified container + ContainerSignal(context.Context, *ContainerSignalRequest) (*ContainerSignalResponse, error) // TODO: ContainerLabels updates labels of the specified container // ContainerStop stops the specified container ContainerStop(context.Context, *ContainerStopRequest) (*ContainerStopResponse, error) @@ -2986,6 +3018,18 @@ func _PublicAPI_ContainerRename_Handler(srv interface{}, ctx context.Context, de return out, nil } +func _PublicAPI_ContainerSignal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { + in := new(ContainerSignalRequest) + if err := dec(in); err != nil { + return nil, err + } + out, err := srv.(PublicAPIServer).ContainerSignal(ctx, in) + if err != nil { + return nil, err + } + return out, nil +} + func _PublicAPI_ContainerStop_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error) (interface{}, error) { in := new(ContainerStopRequest) if err := dec(in); err != nil { @@ -3300,6 +3344,10 @@ var _PublicAPI_serviceDesc = grpc.ServiceDesc{ MethodName: "ContainerRename", Handler: _PublicAPI_ContainerRename_Handler, }, + { + MethodName: "ContainerSignal", + Handler: _PublicAPI_ContainerSignal_Handler, + }, { MethodName: "ContainerStop", Handler: _PublicAPI_ContainerStop_Handler, diff --git a/types/types.proto b/types/types.proto index 345d7030..330081f3 100644 --- a/types/types.proto +++ b/types/types.proto @@ -758,6 +758,14 @@ message PingResponse { string hyperdStats = 1; } +message ContainerSignalRequest { + string podID = 1; + string containerID = 2; + int64 signal = 3; +} + +message ContainerSignalResponse{} + // PublicAPI defines the public APIs which are handled over TCP sockets. service PublicAPI { // PodList gets a list of pods @@ -772,7 +780,7 @@ service PublicAPI { rpc PodStart(PodStartRequest) returns (PodStartResponse) {} // PodStop stops a pod rpc PodStop(PodStopRequest) returns (PodStopResponse) {} - // PodSignal sends a singal to all containers of specified pod + // PodSignal sends a signal to all containers of specified pod rpc PodSignal(PodSignalRequest) returns (PodSignalResponse) {} // PodPause pauses a pod rpc PodPause(PodPauseRequest) returns (PodPauseResponse) {} @@ -805,7 +813,8 @@ service PublicAPI { // ContainerRename renames a container rpc ContainerRename(ContainerRenameRequest) returns (ContainerRenameResponse) {} // TODO: ContainerCommit commits the changes of the specified container - // TODO: ContainerSignal sends a singla to specified container + // ContainerSignal sends a signal to specified container + rpc ContainerSignal(ContainerSignalRequest) returns (ContainerSignalResponse) {} // TODO: ContainerLabels updates labels of the specified container // ContainerStop stops the specified container rpc ContainerStop(ContainerStopRequest) returns (ContainerStopResponse) {}