diff --git a/internal/cli/client/container.go b/internal/cli/client/container.go index 57ea0c2b..8e1ac7fd 100644 --- a/internal/cli/client/container.go +++ b/internal/cli/client/container.go @@ -219,39 +219,102 @@ func toPullProgressEvent(jm jsonmessage.JSONMessage) *progress.Event { } } -// StartContainer starts the specified container within the service. -func (cli *Client) StartContainer(ctx context.Context, serviceID, containerID string) error { +// InspectContainer returns the information about the specified container within the service. +func (cli *Client) InspectContainer(ctx context.Context, serviceID, containerID string) (api.MachineContainer, error) { + var ctr api.MachineContainer + svc, err := cli.InspectService(ctx, serviceID) if err != nil { - return fmt.Errorf("inspect service: %w", err) + return ctr, fmt.Errorf("inspect service: %w", err) } - var ctr api.Container - var machineID string for _, c := range svc.Containers { if c.Container.ID == containerID || c.Container.Names[0] == containerID { - ctr = c.Container - machineID = c.MachineID + ctr = c } } - if ctr.ID == "" { - return ErrNotFound + if ctr.MachineID == "" { + return ctr, ErrNotFound } - machine, err := cli.InspectMachine(ctx, machineID) + return ctr, nil +} + +// StartContainer starts the specified container within the service. +func (cli *Client) StartContainer(ctx context.Context, serviceID, containerID string) error { + ctr, err := cli.InspectContainer(ctx, serviceID, containerID) if err != nil { - return fmt.Errorf("inspect machine '%s': %w", machineID, err) + return err + } + + machine, err := cli.InspectMachine(ctx, ctr.MachineID) + if err != nil { + return fmt.Errorf("inspect machine '%s': %w", ctr.MachineID, err) } ctx = proxyToMachine(ctx, machine.Machine) pw := progress.ContextWriter(ctx) - eventID := fmt.Sprintf("Container %s on %s", ctr.Names[0], machine.Machine.Name) + eventID := fmt.Sprintf("Container %s on %s", ctr.Container.Names[0], machine.Machine.Name) pw.Event(progress.StartingEvent(eventID)) - if err = cli.Docker.StartContainer(ctx, ctr.ID, container.StartOptions{}); err != nil { + if err = cli.Docker.StartContainer(ctx, ctr.Container.ID, container.StartOptions{}); err != nil { return err } pw.Event(progress.StartedEvent(eventID)) return nil } + +// StopContainer stops the specified container within the service. +func (cli *Client) StopContainer( + ctx context.Context, serviceID, containerID string, opts container.StopOptions, +) error { + ctr, err := cli.InspectContainer(ctx, serviceID, containerID) + if err != nil { + return err + } + + machine, err := cli.InspectMachine(ctx, ctr.MachineID) + if err != nil { + return fmt.Errorf("inspect machine '%s': %w", ctr.MachineID, err) + } + ctx = proxyToMachine(ctx, machine.Machine) + + pw := progress.ContextWriter(ctx) + eventID := fmt.Sprintf("Container %s on %s", ctr.Container.Names[0], machine.Machine.Name) + + pw.Event(progress.StoppingEvent(eventID)) + if err = cli.Docker.StopContainer(ctx, ctr.Container.ID, opts); err != nil { + return err + } + pw.Event(progress.StoppedEvent(eventID)) + + return nil +} + +// RemoveContainer removes the specified container within the service. +func (cli *Client) RemoveContainer( + ctx context.Context, serviceID, containerID string, opts container.RemoveOptions, +) error { + ctr, err := cli.InspectContainer(ctx, serviceID, containerID) + if err != nil { + return err + } + + machine, err := cli.InspectMachine(ctx, ctr.MachineID) + if err != nil { + return fmt.Errorf("inspect machine '%s': %w", ctr.MachineID, err) + } + ctx = proxyToMachine(ctx, machine.Machine) + + pw := progress.ContextWriter(ctx) + eventID := fmt.Sprintf("Container %s on %s", ctr.Container.Names[0], machine.Machine.Name) + + pw.Event(progress.RemovingEvent(eventID)) + if err = cli.Docker.RemoveContainer(ctx, ctr.Container.ID, opts); err != nil { + return err + } + pw.Event(progress.RemovedEvent(eventID)) + + return nil +} diff --git a/internal/cli/client/service.go b/internal/cli/client/service.go index fa7e31fa..3532bba8 100644 --- a/internal/cli/client/service.go +++ b/internal/cli/client/service.go @@ -8,7 +8,6 @@ import ( "github.com/docker/compose/v2/pkg/progress" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" - dockerclient "github.com/docker/docker/client" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" @@ -388,18 +387,15 @@ func (cli *Client) RemoveService(ctx context.Context, id string) error { go func() { defer wg.Done() - machineIP, ok := machineManagementIPByID[mc.MachineID] - if !ok { - errCh <- fmt.Errorf("machine not found by ID: %s", mc.MachineID) + err := cli.StopContainer(ctx, svc.ID, mc.Container.ID, container.StopOptions{}) + if err != nil { + errCh <- fmt.Errorf("stop container '%s': %w", mc.Container.ID, err) return } - removeCtx := metadata.NewOutgoingContext(ctx, metadata.Pairs("machines", machineIP)) - // TODO: gracefully stop the container before removing it without force. - err := cli.Docker.RemoveContainer(removeCtx, mc.Container.ID, container.RemoveOptions{Force: true}) - if err != nil { - if !dockerclient.IsErrNotFound(err) { - errCh <- fmt.Errorf("remove container '%s': %w", mc.Container.ID, err) - } + + err = cli.RemoveContainer(ctx, svc.ID, mc.Container.ID, container.RemoveOptions{}) + if err != nil && !errors.Is(err, ErrNotFound) { + errCh <- fmt.Errorf("remove container '%s': %w", mc.Container.ID, err) } }() } diff --git a/internal/machine/api/pb/docker.pb.go b/internal/machine/api/pb/docker.pb.go index 2d433760..203908a1 100644 --- a/internal/machine/api/pb/docker.pb.go +++ b/internal/machine/api/pb/docker.pb.go @@ -303,6 +303,62 @@ func (x *StartContainerRequest) GetOptions() []byte { return nil } +type StopContainerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // JSON serialized container.StopOptions. + Options []byte `protobuf:"bytes,2,opt,name=options,proto3" json:"options,omitempty"` +} + +func (x *StopContainerRequest) Reset() { + *x = StopContainerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StopContainerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StopContainerRequest) ProtoMessage() {} + +func (x *StopContainerRequest) ProtoReflect() protoreflect.Message { + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StopContainerRequest.ProtoReflect.Descriptor instead. +func (*StopContainerRequest) Descriptor() ([]byte, []int) { + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{5} +} + +func (x *StopContainerRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *StopContainerRequest) GetOptions() []byte { + if x != nil { + return x.Options + } + return nil +} + type ListContainersRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -315,7 +371,7 @@ type ListContainersRequest struct { func (x *ListContainersRequest) Reset() { *x = ListContainersRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[5] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -328,7 +384,7 @@ func (x *ListContainersRequest) String() string { func (*ListContainersRequest) ProtoMessage() {} func (x *ListContainersRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[5] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -341,7 +397,7 @@ func (x *ListContainersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListContainersRequest.ProtoReflect.Descriptor instead. func (*ListContainersRequest) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{5} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{6} } func (x *ListContainersRequest) GetOptions() []byte { @@ -363,7 +419,7 @@ type ListContainersResponse struct { func (x *ListContainersResponse) Reset() { *x = ListContainersResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[6] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -376,7 +432,7 @@ func (x *ListContainersResponse) String() string { func (*ListContainersResponse) ProtoMessage() {} func (x *ListContainersResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[6] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -389,7 +445,7 @@ func (x *ListContainersResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListContainersResponse.ProtoReflect.Descriptor instead. func (*ListContainersResponse) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{6} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{7} } func (x *ListContainersResponse) GetMessages() []*MachineContainers { @@ -412,7 +468,7 @@ type MachineContainers struct { func (x *MachineContainers) Reset() { *x = MachineContainers{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[7] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -425,7 +481,7 @@ func (x *MachineContainers) String() string { func (*MachineContainers) ProtoMessage() {} func (x *MachineContainers) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[7] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -438,7 +494,7 @@ func (x *MachineContainers) ProtoReflect() protoreflect.Message { // Deprecated: Use MachineContainers.ProtoReflect.Descriptor instead. func (*MachineContainers) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{7} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{8} } func (x *MachineContainers) GetMetadata() *Metadata { @@ -468,7 +524,7 @@ type RemoveContainerRequest struct { func (x *RemoveContainerRequest) Reset() { *x = RemoveContainerRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[8] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -481,7 +537,7 @@ func (x *RemoveContainerRequest) String() string { func (*RemoveContainerRequest) ProtoMessage() {} func (x *RemoveContainerRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[8] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -494,7 +550,7 @@ func (x *RemoveContainerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RemoveContainerRequest.ProtoReflect.Descriptor instead. func (*RemoveContainerRequest) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{8} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{9} } func (x *RemoveContainerRequest) GetId() string { @@ -524,7 +580,7 @@ type PullImageRequest struct { func (x *PullImageRequest) Reset() { *x = PullImageRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[9] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -537,7 +593,7 @@ func (x *PullImageRequest) String() string { func (*PullImageRequest) ProtoMessage() {} func (x *PullImageRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[9] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -550,7 +606,7 @@ func (x *PullImageRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PullImageRequest.ProtoReflect.Descriptor instead. func (*PullImageRequest) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{9} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{10} } func (x *PullImageRequest) GetImage() string { @@ -579,7 +635,7 @@ type JSONMessage struct { func (x *JSONMessage) Reset() { *x = JSONMessage{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[10] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -592,7 +648,7 @@ func (x *JSONMessage) String() string { func (*JSONMessage) ProtoMessage() {} func (x *JSONMessage) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[10] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -605,7 +661,7 @@ func (x *JSONMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use JSONMessage.ProtoReflect.Descriptor instead. func (*JSONMessage) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{10} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{11} } func (x *JSONMessage) GetMessage() []byte { @@ -649,64 +705,72 @@ var file_internal_machine_api_pb_docker_proto_rawDesc = []byte{ 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x31, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x4c, 0x0a, 0x16, 0x4c, 0x69, 0x73, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, 0x63, 0x68, - 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x08, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x5e, 0x0a, 0x11, 0x4d, 0x61, 0x63, 0x68, 0x69, - 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x29, 0x0a, 0x08, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x22, 0x42, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x42, 0x0a, 0x10, 0x50, - 0x75, 0x6c, 0x6c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x14, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, - 0x27, 0x0a, 0x0b, 0x4a, 0x53, 0x4f, 0x4e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0xb8, 0x03, 0x0a, 0x06, 0x44, 0x6f, 0x63, - 0x6b, 0x65, 0x72, 0x12, 0x4c, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x4f, 0x0a, 0x10, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, - 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, - 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x6d, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x40, 0x0a, 0x14, 0x53, 0x74, 0x6f, 0x70, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, + 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x31, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x4c, 0x0a, 0x16, 0x4c, + 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x61, + 0x63, 0x68, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, + 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x22, 0x5e, 0x0a, 0x11, 0x4d, 0x61, 0x63, + 0x68, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x29, + 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, + 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x22, 0x42, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x36, 0x0a, 0x09, 0x50, - 0x75, 0x6c, 0x6c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, - 0x75, 0x6c, 0x6c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x30, 0x01, 0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x70, 0x73, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x6b, 0x69, 0x2f, 0x75, 0x6e, 0x63, - 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6d, 0x61, - 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x42, 0x0a, + 0x10, 0x50, 0x75, 0x6c, 0x6c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x22, 0x27, 0x0a, 0x0b, 0x4a, 0x53, 0x4f, 0x4e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0xfc, 0x03, 0x0a, 0x06, 0x44, + 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x12, 0x4c, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x10, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, + 0x73, 0x70, 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x49, 0x6e, 0x73, 0x70, + 0x65, 0x63, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x43, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0d, 0x53, 0x74, + 0x6f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x19, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, + 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, + 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x0f, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x36, 0x0a, 0x09, 0x50, 0x75, 0x6c, 0x6c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x15, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x50, 0x75, 0x6c, 0x6c, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x30, 0x01, 0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x73, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, + 0x6b, 0x69, 0x2f, 0x75, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -721,39 +785,42 @@ func file_internal_machine_api_pb_docker_proto_rawDescGZIP() []byte { return file_internal_machine_api_pb_docker_proto_rawDescData } -var file_internal_machine_api_pb_docker_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_internal_machine_api_pb_docker_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_internal_machine_api_pb_docker_proto_goTypes = []any{ (*CreateContainerRequest)(nil), // 0: api.CreateContainerRequest (*CreateContainerResponse)(nil), // 1: api.CreateContainerResponse (*InspectContainerRequest)(nil), // 2: api.InspectContainerRequest (*InspectContainerResponse)(nil), // 3: api.InspectContainerResponse (*StartContainerRequest)(nil), // 4: api.StartContainerRequest - (*ListContainersRequest)(nil), // 5: api.ListContainersRequest - (*ListContainersResponse)(nil), // 6: api.ListContainersResponse - (*MachineContainers)(nil), // 7: api.MachineContainers - (*RemoveContainerRequest)(nil), // 8: api.RemoveContainerRequest - (*PullImageRequest)(nil), // 9: api.PullImageRequest - (*JSONMessage)(nil), // 10: api.JSONMessage - (*Metadata)(nil), // 11: api.Metadata - (*emptypb.Empty)(nil), // 12: google.protobuf.Empty + (*StopContainerRequest)(nil), // 5: api.StopContainerRequest + (*ListContainersRequest)(nil), // 6: api.ListContainersRequest + (*ListContainersResponse)(nil), // 7: api.ListContainersResponse + (*MachineContainers)(nil), // 8: api.MachineContainers + (*RemoveContainerRequest)(nil), // 9: api.RemoveContainerRequest + (*PullImageRequest)(nil), // 10: api.PullImageRequest + (*JSONMessage)(nil), // 11: api.JSONMessage + (*Metadata)(nil), // 12: api.Metadata + (*emptypb.Empty)(nil), // 13: google.protobuf.Empty } var file_internal_machine_api_pb_docker_proto_depIdxs = []int32{ - 7, // 0: api.ListContainersResponse.messages:type_name -> api.MachineContainers - 11, // 1: api.MachineContainers.metadata:type_name -> api.Metadata + 8, // 0: api.ListContainersResponse.messages:type_name -> api.MachineContainers + 12, // 1: api.MachineContainers.metadata:type_name -> api.Metadata 0, // 2: api.Docker.CreateContainer:input_type -> api.CreateContainerRequest 2, // 3: api.Docker.InspectContainer:input_type -> api.InspectContainerRequest 4, // 4: api.Docker.StartContainer:input_type -> api.StartContainerRequest - 5, // 5: api.Docker.ListContainers:input_type -> api.ListContainersRequest - 8, // 6: api.Docker.RemoveContainer:input_type -> api.RemoveContainerRequest - 9, // 7: api.Docker.PullImage:input_type -> api.PullImageRequest - 1, // 8: api.Docker.CreateContainer:output_type -> api.CreateContainerResponse - 3, // 9: api.Docker.InspectContainer:output_type -> api.InspectContainerResponse - 12, // 10: api.Docker.StartContainer:output_type -> google.protobuf.Empty - 6, // 11: api.Docker.ListContainers:output_type -> api.ListContainersResponse - 12, // 12: api.Docker.RemoveContainer:output_type -> google.protobuf.Empty - 10, // 13: api.Docker.PullImage:output_type -> api.JSONMessage - 8, // [8:14] is the sub-list for method output_type - 2, // [2:8] is the sub-list for method input_type + 5, // 5: api.Docker.StopContainer:input_type -> api.StopContainerRequest + 6, // 6: api.Docker.ListContainers:input_type -> api.ListContainersRequest + 9, // 7: api.Docker.RemoveContainer:input_type -> api.RemoveContainerRequest + 10, // 8: api.Docker.PullImage:input_type -> api.PullImageRequest + 1, // 9: api.Docker.CreateContainer:output_type -> api.CreateContainerResponse + 3, // 10: api.Docker.InspectContainer:output_type -> api.InspectContainerResponse + 13, // 11: api.Docker.StartContainer:output_type -> google.protobuf.Empty + 13, // 12: api.Docker.StopContainer:output_type -> google.protobuf.Empty + 7, // 13: api.Docker.ListContainers:output_type -> api.ListContainersResponse + 13, // 14: api.Docker.RemoveContainer:output_type -> google.protobuf.Empty + 11, // 15: api.Docker.PullImage:output_type -> api.JSONMessage + 9, // [9:16] is the sub-list for method output_type + 2, // [2:9] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension type_name 2, // [2:2] is the sub-list for extension extendee 0, // [0:2] is the sub-list for field type_name @@ -827,7 +894,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[5].Exporter = func(v any, i int) any { - switch v := v.(*ListContainersRequest); i { + switch v := v.(*StopContainerRequest); i { case 0: return &v.state case 1: @@ -839,7 +906,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[6].Exporter = func(v any, i int) any { - switch v := v.(*ListContainersResponse); i { + switch v := v.(*ListContainersRequest); i { case 0: return &v.state case 1: @@ -851,7 +918,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[7].Exporter = func(v any, i int) any { - switch v := v.(*MachineContainers); i { + switch v := v.(*ListContainersResponse); i { case 0: return &v.state case 1: @@ -863,7 +930,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[8].Exporter = func(v any, i int) any { - switch v := v.(*RemoveContainerRequest); i { + switch v := v.(*MachineContainers); i { case 0: return &v.state case 1: @@ -875,7 +942,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[9].Exporter = func(v any, i int) any { - switch v := v.(*PullImageRequest); i { + switch v := v.(*RemoveContainerRequest); i { case 0: return &v.state case 1: @@ -887,6 +954,18 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[10].Exporter = func(v any, i int) any { + switch v := v.(*PullImageRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_internal_machine_api_pb_docker_proto_msgTypes[11].Exporter = func(v any, i int) any { switch v := v.(*JSONMessage); i { case 0: return &v.state @@ -905,7 +984,7 @@ func file_internal_machine_api_pb_docker_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_internal_machine_api_pb_docker_proto_rawDesc, NumEnums: 0, - NumMessages: 11, + NumMessages: 12, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/machine/api/pb/docker.proto b/internal/machine/api/pb/docker.proto index 259bf19c..81b58c33 100644 --- a/internal/machine/api/pb/docker.proto +++ b/internal/machine/api/pb/docker.proto @@ -11,6 +11,7 @@ service Docker { rpc CreateContainer(CreateContainerRequest) returns (CreateContainerResponse); rpc InspectContainer(InspectContainerRequest) returns (InspectContainerResponse); rpc StartContainer(StartContainerRequest) returns (google.protobuf.Empty); + rpc StopContainer(StopContainerRequest) returns (google.protobuf.Empty); rpc ListContainers(ListContainersRequest) returns (ListContainersResponse); rpc RemoveContainer(RemoveContainerRequest) returns (google.protobuf.Empty); rpc PullImage(PullImageRequest) returns (stream JSONMessage); @@ -48,6 +49,12 @@ message StartContainerRequest { bytes options = 2; } +message StopContainerRequest { + string id = 1; + // JSON serialized container.StopOptions. + bytes options = 2; +} + message ListContainersRequest { // JSON serialized container.ListOptions. bytes options = 1; diff --git a/internal/machine/api/pb/docker_grpc.pb.go b/internal/machine/api/pb/docker_grpc.pb.go index 6d2df48e..5715be6a 100644 --- a/internal/machine/api/pb/docker_grpc.pb.go +++ b/internal/machine/api/pb/docker_grpc.pb.go @@ -23,6 +23,7 @@ const ( Docker_CreateContainer_FullMethodName = "/api.Docker/CreateContainer" Docker_InspectContainer_FullMethodName = "/api.Docker/InspectContainer" Docker_StartContainer_FullMethodName = "/api.Docker/StartContainer" + Docker_StopContainer_FullMethodName = "/api.Docker/StopContainer" Docker_ListContainers_FullMethodName = "/api.Docker/ListContainers" Docker_RemoveContainer_FullMethodName = "/api.Docker/RemoveContainer" Docker_PullImage_FullMethodName = "/api.Docker/PullImage" @@ -35,6 +36,7 @@ type DockerClient interface { CreateContainer(ctx context.Context, in *CreateContainerRequest, opts ...grpc.CallOption) (*CreateContainerResponse, error) InspectContainer(ctx context.Context, in *InspectContainerRequest, opts ...grpc.CallOption) (*InspectContainerResponse, error) StartContainer(ctx context.Context, in *StartContainerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + StopContainer(ctx context.Context, in *StopContainerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) ListContainers(ctx context.Context, in *ListContainersRequest, opts ...grpc.CallOption) (*ListContainersResponse, error) RemoveContainer(ctx context.Context, in *RemoveContainerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) PullImage(ctx context.Context, in *PullImageRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[JSONMessage], error) @@ -78,6 +80,16 @@ func (c *dockerClient) StartContainer(ctx context.Context, in *StartContainerReq return out, nil } +func (c *dockerClient) StopContainer(ctx context.Context, in *StopContainerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, Docker_StopContainer_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *dockerClient) ListContainers(ctx context.Context, in *ListContainersRequest, opts ...grpc.CallOption) (*ListContainersResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ListContainersResponse) @@ -124,6 +136,7 @@ type DockerServer interface { CreateContainer(context.Context, *CreateContainerRequest) (*CreateContainerResponse, error) InspectContainer(context.Context, *InspectContainerRequest) (*InspectContainerResponse, error) StartContainer(context.Context, *StartContainerRequest) (*emptypb.Empty, error) + StopContainer(context.Context, *StopContainerRequest) (*emptypb.Empty, error) ListContainers(context.Context, *ListContainersRequest) (*ListContainersResponse, error) RemoveContainer(context.Context, *RemoveContainerRequest) (*emptypb.Empty, error) PullImage(*PullImageRequest, grpc.ServerStreamingServer[JSONMessage]) error @@ -146,6 +159,9 @@ func (UnimplementedDockerServer) InspectContainer(context.Context, *InspectConta func (UnimplementedDockerServer) StartContainer(context.Context, *StartContainerRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method StartContainer not implemented") } +func (UnimplementedDockerServer) StopContainer(context.Context, *StopContainerRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method StopContainer not implemented") +} func (UnimplementedDockerServer) ListContainers(context.Context, *ListContainersRequest) (*ListContainersResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListContainers not implemented") } @@ -230,6 +246,24 @@ func _Docker_StartContainer_Handler(srv interface{}, ctx context.Context, dec fu return interceptor(ctx, in, info, handler) } +func _Docker_StopContainer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(StopContainerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DockerServer).StopContainer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Docker_StopContainer_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DockerServer).StopContainer(ctx, req.(*StopContainerRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Docker_ListContainers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListContainersRequest) if err := dec(in); err != nil { @@ -296,6 +330,10 @@ var Docker_ServiceDesc = grpc.ServiceDesc{ MethodName: "StartContainer", Handler: _Docker_StartContainer_Handler, }, + { + MethodName: "StopContainer", + Handler: _Docker_StopContainer_Handler, + }, { MethodName: "ListContainers", Handler: _Docker_ListContainers_Handler, diff --git a/internal/machine/docker/client.go b/internal/machine/docker/client.go index 46c40c05..6f0be8e0 100644 --- a/internal/machine/docker/client.go +++ b/internal/machine/docker/client.go @@ -127,6 +127,27 @@ func (c *Client) StartContainer(ctx context.Context, id string, opts container.S return err } +// StopContainer stops a container with the given ID and options. +func (c *Client) StopContainer(ctx context.Context, id string, opts container.StopOptions) error { + optsBytes, err := json.Marshal(opts) + if err != nil { + return fmt.Errorf("marshal options: %w", err) + } + + _, err = c.grpcClient.StopContainer(ctx, &pb.StopContainerRequest{ + Id: id, + Options: optsBytes, + }) + if err != nil { + if s, ok := status.FromError(err); ok { + if s.Code() == codes.NotFound { + return errdefs.NotFound(err) + } + } + } + return err +} + type MachineContainers struct { Metadata *pb.Metadata Containers []types.Container diff --git a/internal/machine/docker/server.go b/internal/machine/docker/server.go index 3a13999d..917c7c68 100644 --- a/internal/machine/docker/server.go +++ b/internal/machine/docker/server.go @@ -53,9 +53,9 @@ func (s *Server) CreateContainer(ctx context.Context, req *pb.CreateContainerReq resp, err := s.client.ContainerCreate(ctx, &config, &hostConfig, &networkConfig, &platform, req.Name) if err != nil { if client.IsErrNotFound(err) { - return nil, status.Errorf(codes.NotFound, "create container: %v", err) + return nil, status.Errorf(codes.NotFound, err.Error()) } - return nil, status.Errorf(codes.Internal, "create container: %v", err) + return nil, status.Errorf(codes.Internal, err.Error()) } respBytes, err := json.Marshal(resp) @@ -71,9 +71,9 @@ func (s *Server) InspectContainer(ctx context.Context, req *pb.InspectContainerR resp, err := s.client.ContainerInspect(ctx, req.Id) if err != nil { if client.IsErrNotFound(err) { - return nil, status.Errorf(codes.NotFound, "inspect container: %v", err) + return nil, status.Errorf(codes.NotFound, err.Error()) } - return nil, status.Errorf(codes.Internal, "inspect container: %v", err) + return nil, status.Errorf(codes.Internal, err.Error()) } respBytes, err := json.Marshal(resp) @@ -95,9 +95,28 @@ func (s *Server) StartContainer(ctx context.Context, req *pb.StartContainerReque if err := s.client.ContainerStart(ctx, req.Id, opts); err != nil { if client.IsErrNotFound(err) { - return nil, status.Errorf(codes.NotFound, "start container: %v", err) + return nil, status.Errorf(codes.NotFound, err.Error()) } - return nil, status.Errorf(codes.Internal, "start container: %v", err) + return nil, status.Errorf(codes.Internal, err.Error()) + } + + return &emptypb.Empty{}, nil +} + +// StopContainer stops a container with the given ID and options. +func (s *Server) StopContainer(ctx context.Context, req *pb.StopContainerRequest) (*emptypb.Empty, error) { + var opts container.StopOptions + if len(req.Options) > 0 { + if err := json.Unmarshal(req.Options, &opts); err != nil { + return nil, status.Errorf(codes.InvalidArgument, "unmarshal options: %v", err) + } + } + + if err := s.client.ContainerStop(ctx, req.Id, opts); err != nil { + if client.IsErrNotFound(err) { + return nil, status.Errorf(codes.NotFound, err.Error()) + } + return nil, status.Errorf(codes.Internal, err.Error()) } return &emptypb.Empty{}, nil @@ -127,7 +146,7 @@ func (s *Server) ListContainers(ctx context.Context, req *pb.ListContainersReque containers, err := s.client.ContainerList(ctx, opts) if err != nil { - return nil, status.Errorf(codes.Internal, "list container: %v", err) + return nil, status.Errorf(codes.Internal, err.Error()) } containersBytes, err := json.Marshal(containers) @@ -155,9 +174,9 @@ func (s *Server) RemoveContainer(ctx context.Context, req *pb.RemoveContainerReq if err := s.client.ContainerRemove(ctx, req.Id, opts); err != nil { if client.IsErrNotFound(err) { - return nil, status.Errorf(codes.NotFound, "remove container: %v", err) + return nil, status.Errorf(codes.NotFound, err.Error()) } - return nil, status.Errorf(codes.Internal, "remove container: %v", err) + return nil, status.Errorf(codes.Internal, err.Error()) } return &emptypb.Empty{}, nil @@ -176,7 +195,7 @@ func (s *Server) PullImage(req *pb.PullImageRequest, stream grpc.ServerStreaming respBody, err := s.client.ImagePull(ctx, req.Image, opts) if err != nil { - return status.Errorf(codes.Internal, "pull image: %v", err) + return status.Errorf(codes.Internal, err.Error()) } defer respBody.Close() @@ -207,7 +226,7 @@ func (s *Server) PullImage(req *pb.PullImageRequest, stream grpc.ServerStreaming case err = <-errCh: return err case <-ctx.Done(): - return status.Errorf(codes.Canceled, "pull image: %v", ctx.Err()) + return status.Errorf(codes.Canceled, ctx.Err().Error()) } } } diff --git a/test/e2e/service_test.go b/test/e2e/service_test.go index 22a5ab4b..1f0e3913 100644 --- a/test/e2e/service_test.go +++ b/test/e2e/service_test.go @@ -2,6 +2,8 @@ package e2e import ( "context" + "errors" + "github.com/docker/docker/api/types/container" dockerclient "github.com/docker/docker/client" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -24,12 +26,11 @@ func TestService(t *testing.T) { t.Run("container lifecycle", func(t *testing.T) { t.Parallel() - svcName := "busybox-container-lifecycle" + svcName := "pause-container-lifecycle" spec := api.ServiceSpec{ Name: svcName, Container: api.ContainerSpec{ - Command: []string{"sleep", "infinity"}, - Image: "busybox:latest", + Image: "portainer/pause:latest", }, } machineID := c.Machines[0].Name @@ -38,8 +39,25 @@ func TestService(t *testing.T) { require.NoError(t, err) assert.NotEmpty(t, ctr.ID) + t.Cleanup(func() { + err := cli.RemoveContainer(ctx, svcName, ctr.ID, container.RemoveOptions{Force: true}) + if !errors.Is(err, client.ErrNotFound) { + require.NoError(t, err) + } + }) + err = cli.StartContainer(ctx, svcName, ctr.ID) require.NoError(t, err) + + timeout := 1 + err = cli.StopContainer(ctx, svcName, ctr.ID, container.StopOptions{Timeout: &timeout}) + require.NoError(t, err) + + err = cli.RemoveContainer(ctx, svcName, ctr.ID, container.RemoveOptions{}) + require.NoError(t, err) + + err = cli.RemoveContainer(ctx, svcName, ctr.ID, container.RemoveOptions{}) + require.ErrorIs(t, err, client.ErrNotFound) }) } @@ -56,7 +74,7 @@ func TestRunService(t *testing.T) { t.Run("1 replica", func(t *testing.T) { t.Parallel() - name := "busybox-1-replica" + name := "pause-1-replica" t.Cleanup(func() { err := cli.RemoveService(ctx, name) if !dockerclient.IsErrNotFound(err) { @@ -71,8 +89,7 @@ func TestRunService(t *testing.T) { Name: name, Mode: api.ServiceModeReplicated, Container: api.ContainerSpec{ - Command: []string{"sleep", "infinity"}, - Image: "busybox:latest", + Image: "portainer/pause:latest", }, }) require.NoError(t, err) @@ -108,7 +125,7 @@ func TestRunService(t *testing.T) { t.Run("1 replica with ports", func(t *testing.T) { t.Parallel() - name := "busybox-1-replica-ports" + name := "pause-1-replica-ports" t.Cleanup(func() { err := cli.RemoveService(ctx, name) if !dockerclient.IsErrNotFound(err) { @@ -123,8 +140,7 @@ func TestRunService(t *testing.T) { Name: name, Mode: api.ServiceModeReplicated, Container: api.ContainerSpec{ - Command: []string{"sleep", "infinity"}, - Image: "busybox:latest", + Image: "portainer/pause:latest", }, Ports: []api.PortSpec{ { @@ -163,7 +179,7 @@ func TestRunService(t *testing.T) { t.Run("global mode", func(t *testing.T) { t.Parallel() - name := "busybox-global" + name := "pause-global" t.Cleanup(func() { err := cli.RemoveService(ctx, name) if !dockerclient.IsErrNotFound(err) { @@ -178,8 +194,7 @@ func TestRunService(t *testing.T) { Name: name, Mode: api.ServiceModeGlobal, Container: api.ContainerSpec{ - Command: []string{"sleep", "infinity"}, - Image: "busybox:latest", + Image: "portainer/pause:latest", }, }) require.NoError(t, err)