add ListContainers and RemoveContainer methods to Docker service

This commit is contained in:
Pavel Sviderski
2024-12-04 12:15:55 +10:00
parent 386e4e25f3
commit 16120b80ba
5 changed files with 446 additions and 60 deletions
+51 -14
View File
@@ -4,8 +4,8 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/jsonmessage"
@@ -90,13 +90,60 @@ func (c *Client) CreateContainer(
func (c *Client) StartContainer(ctx context.Context, id string, opts container.StartOptions) error {
optsBytes, err := json.Marshal(opts)
if err != nil {
return fmt.Errorf("marshal start options: %w", err)
return fmt.Errorf("marshal options: %w", err)
}
_, err = c.grpcClient.StartContainer(ctx, &pb.StartContainerRequest{
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
}
func (c *Client) ListContainers(ctx context.Context, opts container.ListOptions) ([]types.Container, error) {
optsBytes, err := json.Marshal(opts)
if err != nil {
return nil, fmt.Errorf("marshal options: %w", err)
}
resp, err := c.grpcClient.ListContainers(ctx, &pb.ListContainersRequest{Options: optsBytes})
if err != nil {
return nil, err
}
var containers []types.Container
if err = json.Unmarshal(resp.Containers, &containers); err != nil {
return nil, fmt.Errorf("unmarshal containers: %w", err)
}
return containers, nil
}
// RemoveContainer stops (kills after grace period) and removes a container with the given ID.
func (c *Client) RemoveContainer(ctx context.Context, id string, opts container.RemoveOptions) error {
optsBytes, err := json.Marshal(opts)
if err != nil {
return fmt.Errorf("marshal options: %w", err)
}
_, err = c.grpcClient.RemoveContainer(ctx, &pb.RemoveContainerRequest{
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
}
@@ -105,18 +152,8 @@ type PullImageMessage struct {
Err error
}
func (c *Client) PullImage(
ctx context.Context, image string, opts image.PullOptions,
) (<-chan PullImageMessage, error) {
optsBytes, err := json.Marshal(opts)
if err != nil {
return nil, fmt.Errorf("marshal pull options: %w", err)
}
stream, err := c.grpcClient.PullImage(ctx, &pb.PullImageRequest{
Image: image,
Options: optsBytes,
})
func (c *Client) PullImage(ctx context.Context, image string) (<-chan PullImageMessage, error) {
stream, err := c.grpcClient.PullImage(ctx, &pb.PullImageRequest{Image: image})
if err != nil {
return nil, err
}
+42 -2
View File
@@ -70,7 +70,7 @@ func (s *Server) StartContainer(ctx context.Context, req *pb.StartContainerReque
var opts container.StartOptions
if len(req.Options) > 0 {
if err := json.Unmarshal(req.Options, &opts); err != nil {
return nil, status.Errorf(codes.InvalidArgument, "unmarshal start options: %v", err)
return nil, status.Errorf(codes.InvalidArgument, "unmarshal options: %v", err)
}
}
@@ -81,13 +81,53 @@ func (s *Server) StartContainer(ctx context.Context, req *pb.StartContainerReque
return &emptypb.Empty{}, nil
}
func (s *Server) ListContainers(ctx context.Context, req *pb.ListContainersRequest) (*pb.ListContainersResponse, error) {
var opts container.ListOptions
if len(req.Options) > 0 {
if err := json.Unmarshal(req.Options, &opts); err != nil {
return nil, status.Errorf(codes.InvalidArgument, "unmarshal options: %v", err)
}
}
containers, err := s.client.ContainerList(ctx, opts)
if err != nil {
return nil, status.Errorf(codes.Internal, "list container: %v", err)
}
containersBytes, err := json.Marshal(containers)
if err != nil {
return nil, status.Errorf(codes.Internal, "marshal containers: %v", err)
}
return &pb.ListContainersResponse{
Containers: containersBytes,
}, nil
}
// RemoveContainer stops (kills after grace period) and removes a container with the given ID.
func (s *Server) RemoveContainer(ctx context.Context, req *pb.RemoveContainerRequest) (*emptypb.Empty, error) {
var opts container.RemoveOptions
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.ContainerRemove(ctx, req.Id, opts); err != nil {
return nil, status.Errorf(codes.Internal, "remove container: %v", err)
}
return &emptypb.Empty{}, nil
}
func (s *Server) PullImage(req *pb.PullImageRequest, stream grpc.ServerStreamingServer[pb.JSONMessage]) error {
ctx := stream.Context()
// TODO: replace with another JSON serializable type (PullOptions.PrivilegeFunc is not serializable).
var opts image.PullOptions
if len(req.Options) > 0 {
if err := json.Unmarshal(req.Options, &opts); err != nil {
return status.Errorf(codes.InvalidArgument, "unmarshal pull options: %v", err)
return status.Errorf(codes.InvalidArgument, "unmarshal options: %v", err)
}
}