From a477db6b1610f03c8fc963975a9fcc7b1512304f Mon Sep 17 00:00:00 2001 From: Pavel Sviderski Date: Tue, 11 Feb 2025 15:59:36 +1000 Subject: [PATCH] refactor: client CreateContainer and StartContainer methods --- internal/cli/client/client.go | 17 +- internal/cli/client/cluster.go | 15 + internal/cli/client/container.go | 243 +++++++++++++++ internal/cli/client/service.go | 235 +-------------- internal/machine/api/pb/docker.pb.go | 351 +++++++++++++++------- internal/machine/api/pb/docker.proto | 10 + internal/machine/api/pb/docker_grpc.pb.go | 48 ++- internal/machine/docker/client.go | 20 ++ internal/machine/docker/server.go | 18 ++ test/e2e/service_test.go | 18 +- 10 files changed, 624 insertions(+), 351 deletions(-) create mode 100644 internal/cli/client/container.go diff --git a/internal/cli/client/client.go b/internal/cli/client/client.go index 8540f41b..dba89f9e 100644 --- a/internal/cli/client/client.go +++ b/internal/cli/client/client.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/docker/cli/cli/streams" "google.golang.org/grpc" + "google.golang.org/grpc/metadata" "os" "uncloud/internal/machine/api/pb" "uncloud/internal/machine/docker" @@ -20,12 +21,11 @@ type Client struct { pb.MachineClient pb.ClusterClient - *DockerClient + // Docker is a namespaced client for the Docker service to distinguish Uncloud-specific service container operations + // from generic Docker operations. + Docker *docker.Client } -// DockerClient is a type alias for the Docker client to embed it in Client with a more specific name. -type DockerClient = docker.Client - // Connector is an interface for establishing a connection to the machine API. type Connector interface { Connect(ctx context.Context) (*grpc.ClientConn, error) @@ -46,7 +46,7 @@ func New(ctx context.Context, connector Connector) (*Client, error) { c.MachineClient = pb.NewMachineClient(c.conn) c.ClusterClient = pb.NewClusterClient(c.conn) - c.DockerClient = docker.NewClient(c.conn) + c.Docker = docker.NewClient(c.conn) return c, nil } @@ -58,3 +58,10 @@ func (cli *Client) Close() error { func (cli *Client) progressOut() *streams.Out { return streams.NewOut(os.Stdout) } + +// proxyToMachine returns a new context that proxies gRPC requests to the specified machine. +func proxyToMachine(ctx context.Context, machine *pb.MachineInfo) context.Context { + machineIP, _ := machine.Network.ManagementIp.ToAddr() + md := metadata.Pairs("machines", machineIP.String()) + return metadata.NewOutgoingContext(ctx, md) +} diff --git a/internal/cli/client/cluster.go b/internal/cli/client/cluster.go index 5219364a..e76d6855 100644 --- a/internal/cli/client/cluster.go +++ b/internal/cli/client/cluster.go @@ -6,6 +6,21 @@ import ( "uncloud/internal/machine/api/pb" ) +func (cli *Client) InspectMachine(ctx context.Context, id string) (*pb.MachineMember, error) { + machines, err := cli.ListMachines(ctx) + if err != nil { + return nil, err + } + + for _, m := range machines { + if m.Machine.Id == id || m.Machine.Name == id { + return m, nil + } + } + + return nil, ErrNotFound +} + func (cli *Client) ListMachines(ctx context.Context) ([]*pb.MachineMember, error) { resp, err := cli.ClusterClient.ListMachines(ctx, &emptypb.Empty{}) if err != nil { diff --git a/internal/cli/client/container.go b/internal/cli/client/container.go new file mode 100644 index 00000000..2eda8e53 --- /dev/null +++ b/internal/cli/client/container.go @@ -0,0 +1,243 @@ +package client + +import ( + "context" + "errors" + "fmt" + "github.com/docker/compose/v2/pkg/progress" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/network" + dockerclient "github.com/docker/docker/client" + "github.com/docker/docker/pkg/jsonmessage" + "github.com/docker/go-connections/nat" + "strconv" + "strings" + "uncloud/internal/api" + machinedocker "uncloud/internal/machine/docker" + "uncloud/internal/secret" +) + +func (cli *Client) CreateContainer( + ctx context.Context, serviceID string, spec api.ServiceSpec, machineID string, +) (container.CreateResponse, error) { + var resp container.CreateResponse + + machine, err := cli.InspectMachine(ctx, machineID) + if err != nil { + return resp, fmt.Errorf("inspect machine '%s': %w", machineID, err) + } + + suffix, err := secret.RandomAlphaNumeric(4) + if err != nil { + return resp, fmt.Errorf("generate random suffix: %w", err) + } + containerName := fmt.Sprintf("%s-%s", spec.Name, suffix) + + config := &container.Config{ + Cmd: spec.Container.Command, + Image: spec.Container.Image, + Labels: map[string]string{ + api.LabelServiceID: serviceID, + api.LabelServiceName: spec.Name, + api.LabelManaged: "", + }, + } + if spec.Mode == api.ServiceModeGlobal { + config.Labels[api.LabelServiceMode] = api.ServiceModeGlobal + } + + if len(spec.Ports) > 0 { + encodedPorts := make([]string, len(spec.Ports)) + for i, p := range spec.Ports { + encodedPorts[i], err = p.String() + if err != nil { + return resp, fmt.Errorf("encode service port spec: %w", err) + } + } + + config.Labels[api.LabelServicePorts] = strings.Join(encodedPorts, ",") + } + + portBindings := make(nat.PortMap) + for _, p := range spec.Ports { + if p.Mode != api.PortModeHost { + continue + } + port := nat.Port(fmt.Sprintf("%d/%s", p.ContainerPort, p.Protocol)) + portBindings[port] = []nat.PortBinding{ + { + HostPort: strconv.Itoa(int(p.PublishedPort)), + }, + } + if p.HostIP.IsValid() { + portBindings[port][0].HostIP = p.HostIP.String() + } + } + hostConfig := &container.HostConfig{ + Binds: spec.Container.Volumes, + Init: spec.Container.Init, + PortBindings: portBindings, + } + netConfig := &network.NetworkingConfig{ + EndpointsConfig: map[string]*network.EndpointSettings{ + machinedocker.NetworkName: {}, + }, + } + + // Proxy Docker gRPC requests to the selected machine. + ctx = proxyToMachine(ctx, machine.Machine) + + pw := progress.ContextWriter(ctx) + eventID := fmt.Sprintf("Container %s on %s", containerName, machine.Machine.Name) + + pw.Event(progress.CreatingEvent(eventID)) + resp, err = cli.Docker.CreateContainer(ctx, config, hostConfig, netConfig, nil, containerName) + if err != nil { + if !dockerclient.IsErrNotFound(err) { + return resp, err + } + + // Pull the missing image and create the container again. + if err = cli.pullImageWithProgress(ctx, config.Image, machine.Machine.Name, eventID); err != nil { + return resp, err + } + if resp, err = cli.Docker.CreateContainer(ctx, config, hostConfig, netConfig, nil, containerName); err != nil { + return resp, err + } + } + pw.Event(progress.CreatedEvent(eventID)) + + return resp, nil +} + +func (cli *Client) pullImageWithProgress(ctx context.Context, image, machineName, parentEventID string) error { + pw := progress.ContextWriter(ctx) + eventID := fmt.Sprintf("Image %s on %s", image, machineName) + pw.Event(progress.Event{ + ID: eventID, + ParentID: parentEventID, + Status: progress.Working, + StatusText: "Pulling", + }) + + pullCh, err := cli.Docker.PullImage(ctx, image) + if err != nil { + pw.Event(progress.Event{ + ID: eventID, + ParentID: parentEventID, + Text: "Error", + Status: progress.Error, + StatusText: errors.Unwrap(err).Error(), + }) + return fmt.Errorf("pull image: %w", err) + } + + // Wait for pull to complete by reading all progress messages and converting them to events. + for msg := range pullCh { + if msg.Err != nil { + err = msg.Err + } else { + if msg.Message.Error != nil { + err = errors.New(msg.Message.Error.Message) + } + } + if err != nil { + pw.Event(progress.Event{ + ID: eventID, + ParentID: parentEventID, + Text: "Error", + Status: progress.Error, + StatusText: errors.Unwrap(err).Error(), + }) + return fmt.Errorf("pull image: %w", err) + } + + // TODO: add like in compose: --quiet-pull Pull without printing progress information + e := toPullProgressEvent(msg.Message) + if e != nil { + e.ID = fmt.Sprintf("%s on %s", e.ID, machineName) + e.ParentID = eventID + // Grand children events are not printed by the tty progress writer but they are still required + // to calculate the progress line of their parent. + pw.Event(*e) + } + } + pw.Event(progress.Event{ + ID: eventID, + ParentID: parentEventID, + Status: progress.Done, + StatusText: "Pulled", + }) + + return nil +} + +// toPullProgressEvent converts a JSON progress message from the Docker API to a progress event. +// It's based on toPullProgressEvent from Docker Compose. +func toPullProgressEvent(jm jsonmessage.JSONMessage) *progress.Event { + if jm.ID == "" || jm.Progress == nil { + return nil + } + + var ( + total int64 + percent int + current int64 + ) + text := jm.Progress.String() + stat := progress.Working + + switch jm.Status { + case "Preparing", "Waiting", "Pulling fs layer": + percent = 0 + case "Downloading", "Extracting", "Verifying Checksum": + current = jm.Progress.Current + total = jm.Progress.Total + if jm.Progress.Total > 0 { + percent = int(jm.Progress.Current * 100 / jm.Progress.Total) + } + case "Download complete", "Already exists", "Pull complete": + stat = progress.Done + percent = 100 + } + + if strings.Contains(jm.Status, "Image is up to date") || + strings.Contains(jm.Status, "Downloaded newer image") { + stat = progress.Done + percent = 100 + } + + return &progress.Event{ + ID: jm.ID, + Current: current, + Total: total, + Percent: percent, + Text: jm.Status, + Status: stat, + StatusText: text, + } +} + +func (cli *Client) StartContainer(ctx context.Context, id string, machineID string) error { + machine, err := cli.InspectMachine(ctx, machineID) + if err != nil { + return fmt.Errorf("inspect machine '%s': %w", machineID, err) + } + ctx = proxyToMachine(ctx, machine.Machine) + + ctr, err := cli.Docker.InspectContainer(ctx, id) + if err != nil { + return err + } + + pw := progress.ContextWriter(ctx) + eventID := fmt.Sprintf("Container %s on %s", ctr.Name, machine.Machine.Name) + + pw.Event(progress.StartingEvent(eventID)) + if err = cli.Docker.StartContainer(ctx, ctr.ID, container.StartOptions{}); err != nil { + return err + } + pw.Event(progress.StartedEvent(eventID)) + + return nil +} diff --git a/internal/cli/client/service.go b/internal/cli/client/service.go index 295c5f29..d9cdd5a7 100644 --- a/internal/cli/client/service.go +++ b/internal/cli/client/service.go @@ -8,20 +8,15 @@ import ( "github.com/docker/compose/v2/pkg/progress" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/network" dockerclient "github.com/docker/docker/client" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/go-connections/nat" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" "slices" - "strconv" "strings" "sync" "uncloud/internal/api" "uncloud/internal/machine/api/pb" - machinedocker "uncloud/internal/machine/docker" "uncloud/internal/secret" ) @@ -36,35 +31,6 @@ type MachineContainerID struct { ContainerID string } -type Service struct { - ID string - Name string -} - -// NewService creates a new Service object with the specified name that can be used to run service containers. -// It doesn't create anything in the cluster yet. -func (cli *Client) NewService(ctx context.Context, name string) (*Service, error) { - // Optimistically check if a service with the specified name already exists. - // TODO: introduce a distributed lock to hold for all service related operations. - _, err := cli.InspectService(ctx, name) - if err == nil { - return nil, fmt.Errorf("service with name '%s' already exists", name) - } - if !errors.Is(err, ErrNotFound) { - return nil, fmt.Errorf("inspect service: %w", err) - } - - id, err := secret.NewID() - if err != nil { - return nil, fmt.Errorf("generate service ID: %w", err) - } - - return &Service{ - ID: id, - Name: name, - }, nil -} - func (cli *Client) RunService(ctx context.Context, spec api.ServiceSpec) (RunServiceResponse, error) { var resp RunServiceResponse @@ -243,207 +209,18 @@ func (cli *Client) runGlobalService(ctx context.Context, id string, spec api.Ser func (cli *Client) runContainer( ctx context.Context, serviceID string, spec api.ServiceSpec, machine *pb.MachineInfo, ) (container.CreateResponse, error) { - var resp container.CreateResponse - - // Proxy Docker gRPC requests to the selected machine. - machineIP, _ := machine.Network.ManagementIp.ToAddr() - md := metadata.Pairs("machines", machineIP.String()) - ctx = metadata.NewOutgoingContext(ctx, md) - - suffix, err := secret.RandomAlphaNumeric(4) + resp, err := cli.CreateContainer(ctx, serviceID, spec, machine.Name) if err != nil { - return resp, fmt.Errorf("generate random suffix: %w", err) - } - containerName := fmt.Sprintf("%s-%s", spec.Name, suffix) - - config := &container.Config{ - Cmd: spec.Container.Command, - Image: spec.Container.Image, - Labels: map[string]string{ - api.LabelServiceID: serviceID, - api.LabelServiceName: spec.Name, - api.LabelManaged: "", - }, - } - if spec.Mode == api.ServiceModeGlobal { - config.Labels[api.LabelServiceMode] = api.ServiceModeGlobal + return resp, fmt.Errorf("create container: %w", err) } - if len(spec.Ports) > 0 { - encodedPorts := make([]string, len(spec.Ports)) - for i, p := range spec.Ports { - encodedPorts[i], err = p.String() - if err != nil { - return resp, fmt.Errorf("encode service port spec: %w", err) - } - } - - config.Labels[api.LabelServicePorts] = strings.Join(encodedPorts, ",") - } - - portBindings := make(nat.PortMap) - for _, p := range spec.Ports { - if p.Mode != api.PortModeHost { - continue - } - port := nat.Port(fmt.Sprintf("%d/%s", p.ContainerPort, p.Protocol)) - portBindings[port] = []nat.PortBinding{ - { - HostPort: strconv.Itoa(int(p.PublishedPort)), - }, - } - if p.HostIP.IsValid() { - portBindings[port][0].HostIP = p.HostIP.String() - } - } - hostConfig := &container.HostConfig{ - Binds: spec.Container.Volumes, - Init: spec.Container.Init, - PortBindings: portBindings, - } - netConfig := &network.NetworkingConfig{ - EndpointsConfig: map[string]*network.EndpointSettings{ - machinedocker.NetworkName: {}, - }, - } - - pw := progress.ContextWriter(ctx) - eventID := fmt.Sprintf("Container %s on %s", containerName, machine.Name) - - pw.Event(progress.CreatingEvent(eventID)) - resp, err = cli.CreateContainer(ctx, config, hostConfig, netConfig, nil, containerName) - if err != nil { - if !dockerclient.IsErrNotFound(err) { - return resp, fmt.Errorf("create container: %w", err) - } - - // Pull the missing image and create the container again. - if err = cli.pullImageWithProgress(ctx, config.Image, machine.Name, eventID); err != nil { - return resp, err - } - if resp, err = cli.CreateContainer(ctx, config, hostConfig, netConfig, nil, containerName); err != nil { - return resp, fmt.Errorf("create container: %w", err) - } - } - pw.Event(progress.CreatedEvent(eventID)) - - pw.Event(progress.StartingEvent(eventID)) - if err = cli.StartContainer(ctx, resp.ID, container.StartOptions{}); err != nil { + if err = cli.StartContainer(ctx, resp.ID, machine.Name); err != nil { return resp, fmt.Errorf("start container: %w", err) } - pw.Event(progress.StartedEvent(eventID)) return resp, nil } -func (cli *Client) pullImageWithProgress(ctx context.Context, image, machineName, parentEventID string) error { - pw := progress.ContextWriter(ctx) - eventID := fmt.Sprintf("Image %s on %s", image, machineName) - pw.Event(progress.Event{ - ID: eventID, - ParentID: parentEventID, - Status: progress.Working, - StatusText: "Pulling", - }) - - pullCh, err := cli.PullImage(ctx, image) - if err != nil { - pw.Event(progress.Event{ - ID: eventID, - ParentID: parentEventID, - Text: "Error", - Status: progress.Error, - StatusText: errors.Unwrap(err).Error(), - }) - return fmt.Errorf("pull image: %w", err) - } - - // Wait for pull to complete by reading all progress messages and converting them to events. - for msg := range pullCh { - if msg.Err != nil { - err = msg.Err - } else { - if msg.Message.Error != nil { - err = errors.New(msg.Message.Error.Message) - } - } - if err != nil { - pw.Event(progress.Event{ - ID: eventID, - ParentID: parentEventID, - Text: "Error", - Status: progress.Error, - StatusText: errors.Unwrap(err).Error(), - }) - return fmt.Errorf("pull image: %w", err) - } - - // TODO: add like in compose: --quiet-pull Pull without printing progress information - e := toPullProgressEvent(msg.Message) - if e != nil { - e.ID = fmt.Sprintf("%s on %s", e.ID, machineName) - e.ParentID = eventID - // Grand children events are not printed by the tty progress writer but they are still required - // to calculate the progress line of their parent. - pw.Event(*e) - } - } - pw.Event(progress.Event{ - ID: eventID, - ParentID: parentEventID, - Status: progress.Done, - StatusText: "Pulled", - }) - - return nil -} - -// toPullProgressEvent converts a JSON progress message from the Docker API to a progress event. -// It's based on toPullProgressEvent from Docker Compose. -func toPullProgressEvent(jm jsonmessage.JSONMessage) *progress.Event { - if jm.ID == "" || jm.Progress == nil { - return nil - } - - var ( - total int64 - percent int - current int64 - ) - text := jm.Progress.String() - stat := progress.Working - - switch jm.Status { - case "Preparing", "Waiting", "Pulling fs layer": - percent = 0 - case "Downloading", "Extracting", "Verifying Checksum": - current = jm.Progress.Current - total = jm.Progress.Total - if jm.Progress.Total > 0 { - percent = int(jm.Progress.Current * 100 / jm.Progress.Total) - } - case "Download complete", "Already exists", "Pull complete": - stat = progress.Done - percent = 100 - } - - if strings.Contains(jm.Status, "Image is up to date") || - strings.Contains(jm.Status, "Downloaded newer image") { - stat = progress.Done - percent = 100 - } - - return &progress.Event{ - ID: jm.ID, - Current: current, - Total: total, - Percent: percent, - Text: jm.Status, - Status: stat, - StatusText: text, - } -} - // InspectService returns detailed information about a service and its containers. // The id parameter can be either a service ID or name. func (cli *Client) InspectService(ctx context.Context, id string) (api.Service, error) { @@ -476,7 +253,7 @@ func (cli *Client) InspectService(ctx context.Context, id string) (api.Service, filters.Arg("label", api.LabelManaged), ), } - machineContainers, err := cli.ListContainers(listCtx, opts) + machineContainers, err := cli.Docker.ListContainers(listCtx, opts) if err != nil { return svc, fmt.Errorf("list containers: %w", err) } @@ -618,7 +395,7 @@ func (cli *Client) RemoveService(ctx context.Context, id string) error { } removeCtx := metadata.NewOutgoingContext(ctx, metadata.Pairs("machines", machineIP)) // TODO: gracefully stop the container before removing it without force. - err := cli.RemoveContainer(removeCtx, mc.Container.ID, container.RemoveOptions{Force: true}) + 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) @@ -665,7 +442,7 @@ func (cli *Client) ListServices(ctx context.Context) ([]api.Service, error) { filters.Arg("label", api.LabelManaged), ), } - machineContainers, err := cli.ListContainers(listCtx, opts) + machineContainers, err := cli.Docker.ListContainers(listCtx, opts) if err != nil { return nil, fmt.Errorf("list containers: %w", err) } diff --git a/internal/machine/api/pb/docker.pb.go b/internal/machine/api/pb/docker.pb.go index 0cfe4c53..2d433760 100644 --- a/internal/machine/api/pb/docker.pb.go +++ b/internal/machine/api/pb/docker.pb.go @@ -152,6 +152,101 @@ func (x *CreateContainerResponse) GetResponse() []byte { return nil } +type InspectContainerRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *InspectContainerRequest) Reset() { + *x = InspectContainerRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InspectContainerRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InspectContainerRequest) ProtoMessage() {} + +func (x *InspectContainerRequest) ProtoReflect() protoreflect.Message { + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[2] + 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 InspectContainerRequest.ProtoReflect.Descriptor instead. +func (*InspectContainerRequest) Descriptor() ([]byte, []int) { + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{2} +} + +func (x *InspectContainerRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type InspectContainerResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // JSON serialized container.InspectResponse. + Response []byte `protobuf:"bytes,1,opt,name=response,proto3" json:"response,omitempty"` +} + +func (x *InspectContainerResponse) Reset() { + *x = InspectContainerResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InspectContainerResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InspectContainerResponse) ProtoMessage() {} + +func (x *InspectContainerResponse) ProtoReflect() protoreflect.Message { + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[3] + 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 InspectContainerResponse.ProtoReflect.Descriptor instead. +func (*InspectContainerResponse) Descriptor() ([]byte, []int) { + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{3} +} + +func (x *InspectContainerResponse) GetResponse() []byte { + if x != nil { + return x.Response + } + return nil +} + type StartContainerRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -165,7 +260,7 @@ type StartContainerRequest struct { func (x *StartContainerRequest) Reset() { *x = StartContainerRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[2] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -178,7 +273,7 @@ func (x *StartContainerRequest) String() string { func (*StartContainerRequest) ProtoMessage() {} func (x *StartContainerRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[2] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -191,7 +286,7 @@ func (x *StartContainerRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StartContainerRequest.ProtoReflect.Descriptor instead. func (*StartContainerRequest) Descriptor() ([]byte, []int) { - return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{2} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{4} } func (x *StartContainerRequest) GetId() string { @@ -220,7 +315,7 @@ type ListContainersRequest struct { func (x *ListContainersRequest) Reset() { *x = ListContainersRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[3] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -233,7 +328,7 @@ func (x *ListContainersRequest) String() string { func (*ListContainersRequest) ProtoMessage() {} func (x *ListContainersRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[3] + 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 { @@ -246,7 +341,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{3} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{5} } func (x *ListContainersRequest) GetOptions() []byte { @@ -268,7 +363,7 @@ type ListContainersResponse struct { func (x *ListContainersResponse) Reset() { *x = ListContainersResponse{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[4] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -281,7 +376,7 @@ func (x *ListContainersResponse) String() string { func (*ListContainersResponse) ProtoMessage() {} func (x *ListContainersResponse) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[4] + 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 { @@ -294,7 +389,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{4} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{6} } func (x *ListContainersResponse) GetMessages() []*MachineContainers { @@ -317,7 +412,7 @@ type MachineContainers struct { func (x *MachineContainers) Reset() { *x = MachineContainers{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[5] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -330,7 +425,7 @@ func (x *MachineContainers) String() string { func (*MachineContainers) ProtoMessage() {} func (x *MachineContainers) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[5] + 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 { @@ -343,7 +438,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{5} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{7} } func (x *MachineContainers) GetMetadata() *Metadata { @@ -373,7 +468,7 @@ type RemoveContainerRequest struct { func (x *RemoveContainerRequest) Reset() { *x = RemoveContainerRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[6] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -386,7 +481,7 @@ func (x *RemoveContainerRequest) String() string { func (*RemoveContainerRequest) ProtoMessage() {} func (x *RemoveContainerRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[6] + 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 { @@ -399,7 +494,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{6} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{8} } func (x *RemoveContainerRequest) GetId() string { @@ -429,7 +524,7 @@ type PullImageRequest struct { func (x *PullImageRequest) Reset() { *x = PullImageRequest{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[7] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -442,7 +537,7 @@ func (x *PullImageRequest) String() string { func (*PullImageRequest) ProtoMessage() {} func (x *PullImageRequest) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[7] + 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 { @@ -455,7 +550,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{7} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{9} } func (x *PullImageRequest) GetImage() string { @@ -484,7 +579,7 @@ type JSONMessage struct { func (x *JSONMessage) Reset() { *x = JSONMessage{} if protoimpl.UnsafeEnabled { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[8] + mi := &file_internal_machine_api_pb_docker_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -497,7 +592,7 @@ func (x *JSONMessage) String() string { func (*JSONMessage) ProtoMessage() {} func (x *JSONMessage) ProtoReflect() protoreflect.Message { - mi := &file_internal_machine_api_pb_docker_proto_msgTypes[8] + 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 { @@ -510,7 +605,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{8} + return file_internal_machine_api_pb_docker_proto_rawDescGZIP(), []int{10} } func (x *JSONMessage) GetMessage() []byte { @@ -544,62 +639,74 @@ var file_internal_machine_api_pb_docker_proto_rawDesc = []byte{ 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x41, 0x0a, 0x15, 0x53, 0x74, 0x61, 0x72, 0x74, 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, 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, 0xe7, 0x02, 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, + 0x22, 0x29, 0x0a, 0x17, 0x49, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x74, 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, 0x22, 0x36, 0x0a, 0x18, 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, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x41, 0x0a, 0x15, 0x53, 0x74, 0x61, 0x72, 0x74, 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, 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, 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, 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, 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, + 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 ( @@ -614,35 +721,39 @@ 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, 9) +var file_internal_machine_api_pb_docker_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_internal_machine_api_pb_docker_proto_goTypes = []any{ - (*CreateContainerRequest)(nil), // 0: api.CreateContainerRequest - (*CreateContainerResponse)(nil), // 1: api.CreateContainerResponse - (*StartContainerRequest)(nil), // 2: api.StartContainerRequest - (*ListContainersRequest)(nil), // 3: api.ListContainersRequest - (*ListContainersResponse)(nil), // 4: api.ListContainersResponse - (*MachineContainers)(nil), // 5: api.MachineContainers - (*RemoveContainerRequest)(nil), // 6: api.RemoveContainerRequest - (*PullImageRequest)(nil), // 7: api.PullImageRequest - (*JSONMessage)(nil), // 8: api.JSONMessage - (*Metadata)(nil), // 9: api.Metadata - (*emptypb.Empty)(nil), // 10: google.protobuf.Empty + (*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 } var file_internal_machine_api_pb_docker_proto_depIdxs = []int32{ - 5, // 0: api.ListContainersResponse.messages:type_name -> api.MachineContainers - 9, // 1: api.MachineContainers.metadata:type_name -> api.Metadata + 7, // 0: api.ListContainersResponse.messages:type_name -> api.MachineContainers + 11, // 1: api.MachineContainers.metadata:type_name -> api.Metadata 0, // 2: api.Docker.CreateContainer:input_type -> api.CreateContainerRequest - 2, // 3: api.Docker.StartContainer:input_type -> api.StartContainerRequest - 3, // 4: api.Docker.ListContainers:input_type -> api.ListContainersRequest - 6, // 5: api.Docker.RemoveContainer:input_type -> api.RemoveContainerRequest - 7, // 6: api.Docker.PullImage:input_type -> api.PullImageRequest - 1, // 7: api.Docker.CreateContainer:output_type -> api.CreateContainerResponse - 10, // 8: api.Docker.StartContainer:output_type -> google.protobuf.Empty - 4, // 9: api.Docker.ListContainers:output_type -> api.ListContainersResponse - 10, // 10: api.Docker.RemoveContainer:output_type -> google.protobuf.Empty - 8, // 11: api.Docker.PullImage:output_type -> api.JSONMessage - 7, // [7:12] is the sub-list for method output_type - 2, // [2:7] is the sub-list for method input_type + 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 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 @@ -680,7 +791,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[2].Exporter = func(v any, i int) any { - switch v := v.(*StartContainerRequest); i { + switch v := v.(*InspectContainerRequest); i { case 0: return &v.state case 1: @@ -692,7 +803,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[3].Exporter = func(v any, i int) any { - switch v := v.(*ListContainersRequest); i { + switch v := v.(*InspectContainerResponse); i { case 0: return &v.state case 1: @@ -704,7 +815,7 @@ func file_internal_machine_api_pb_docker_proto_init() { } } file_internal_machine_api_pb_docker_proto_msgTypes[4].Exporter = func(v any, i int) any { - switch v := v.(*ListContainersResponse); i { + switch v := v.(*StartContainerRequest); i { case 0: return &v.state case 1: @@ -716,7 +827,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.(*MachineContainers); i { + switch v := v.(*ListContainersRequest); i { case 0: return &v.state case 1: @@ -728,7 +839,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.(*RemoveContainerRequest); i { + switch v := v.(*ListContainersResponse); i { case 0: return &v.state case 1: @@ -740,7 +851,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.(*PullImageRequest); i { + switch v := v.(*MachineContainers); i { case 0: return &v.state case 1: @@ -752,6 +863,30 @@ 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 { + 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[9].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[10].Exporter = func(v any, i int) any { switch v := v.(*JSONMessage); i { case 0: return &v.state @@ -770,7 +905,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: 9, + NumMessages: 11, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/machine/api/pb/docker.proto b/internal/machine/api/pb/docker.proto index d88c6c86..259bf19c 100644 --- a/internal/machine/api/pb/docker.proto +++ b/internal/machine/api/pb/docker.proto @@ -9,6 +9,7 @@ import "internal/machine/api/pb/common.proto"; service Docker { rpc CreateContainer(CreateContainerRequest) returns (CreateContainerResponse); + rpc InspectContainer(InspectContainerRequest) returns (InspectContainerResponse); rpc StartContainer(StartContainerRequest) returns (google.protobuf.Empty); rpc ListContainers(ListContainersRequest) returns (ListContainersResponse); rpc RemoveContainer(RemoveContainerRequest) returns (google.protobuf.Empty); @@ -32,6 +33,15 @@ message CreateContainerResponse { bytes response = 1; } +message InspectContainerRequest { + string id = 1; +} + +message InspectContainerResponse { + // JSON serialized container.InspectResponse. + bytes response = 1; +} + message StartContainerRequest { string id = 1; // JSON serialized container.StartOptions. diff --git a/internal/machine/api/pb/docker_grpc.pb.go b/internal/machine/api/pb/docker_grpc.pb.go index d1cc1c5a..6d2df48e 100644 --- a/internal/machine/api/pb/docker_grpc.pb.go +++ b/internal/machine/api/pb/docker_grpc.pb.go @@ -20,11 +20,12 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - Docker_CreateContainer_FullMethodName = "/api.Docker/CreateContainer" - Docker_StartContainer_FullMethodName = "/api.Docker/StartContainer" - Docker_ListContainers_FullMethodName = "/api.Docker/ListContainers" - Docker_RemoveContainer_FullMethodName = "/api.Docker/RemoveContainer" - Docker_PullImage_FullMethodName = "/api.Docker/PullImage" + Docker_CreateContainer_FullMethodName = "/api.Docker/CreateContainer" + Docker_InspectContainer_FullMethodName = "/api.Docker/InspectContainer" + Docker_StartContainer_FullMethodName = "/api.Docker/StartContainer" + Docker_ListContainers_FullMethodName = "/api.Docker/ListContainers" + Docker_RemoveContainer_FullMethodName = "/api.Docker/RemoveContainer" + Docker_PullImage_FullMethodName = "/api.Docker/PullImage" ) // DockerClient is the client API for Docker service. @@ -32,6 +33,7 @@ const ( // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 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) ListContainers(ctx context.Context, in *ListContainersRequest, opts ...grpc.CallOption) (*ListContainersResponse, error) RemoveContainer(ctx context.Context, in *RemoveContainerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) @@ -56,6 +58,16 @@ func (c *dockerClient) CreateContainer(ctx context.Context, in *CreateContainerR return out, nil } +func (c *dockerClient) InspectContainer(ctx context.Context, in *InspectContainerRequest, opts ...grpc.CallOption) (*InspectContainerResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(InspectContainerResponse) + err := c.cc.Invoke(ctx, Docker_InspectContainer_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *dockerClient) StartContainer(ctx context.Context, in *StartContainerRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(emptypb.Empty) @@ -110,6 +122,7 @@ type Docker_PullImageClient = grpc.ServerStreamingClient[JSONMessage] // for forward compatibility. type DockerServer interface { CreateContainer(context.Context, *CreateContainerRequest) (*CreateContainerResponse, error) + InspectContainer(context.Context, *InspectContainerRequest) (*InspectContainerResponse, error) StartContainer(context.Context, *StartContainerRequest) (*emptypb.Empty, error) ListContainers(context.Context, *ListContainersRequest) (*ListContainersResponse, error) RemoveContainer(context.Context, *RemoveContainerRequest) (*emptypb.Empty, error) @@ -127,6 +140,9 @@ type UnimplementedDockerServer struct{} func (UnimplementedDockerServer) CreateContainer(context.Context, *CreateContainerRequest) (*CreateContainerResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateContainer not implemented") } +func (UnimplementedDockerServer) InspectContainer(context.Context, *InspectContainerRequest) (*InspectContainerResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method InspectContainer not implemented") +} func (UnimplementedDockerServer) StartContainer(context.Context, *StartContainerRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method StartContainer not implemented") } @@ -178,6 +194,24 @@ func _Docker_CreateContainer_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _Docker_InspectContainer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InspectContainerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DockerServer).InspectContainer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Docker_InspectContainer_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DockerServer).InspectContainer(ctx, req.(*InspectContainerRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Docker_StartContainer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(StartContainerRequest) if err := dec(in); err != nil { @@ -254,6 +288,10 @@ var Docker_ServiceDesc = grpc.ServiceDesc{ MethodName: "CreateContainer", Handler: _Docker_CreateContainer_Handler, }, + { + MethodName: "InspectContainer", + Handler: _Docker_InspectContainer_Handler, + }, { MethodName: "StartContainer", Handler: _Docker_StartContainer_Handler, diff --git a/internal/machine/docker/client.go b/internal/machine/docker/client.go index 8d60df46..46c40c05 100644 --- a/internal/machine/docker/client.go +++ b/internal/machine/docker/client.go @@ -86,6 +86,26 @@ func (c *Client) CreateContainer( return resp, nil } +// InspectContainer returns the container information for the given container ID. +func (c *Client) InspectContainer(ctx context.Context, id string) (types.ContainerJSON, error) { + var resp types.ContainerJSON + + grpcResp, err := c.grpcClient.InspectContainer(ctx, &pb.InspectContainerRequest{Id: id}) + if err != nil { + if s, ok := status.FromError(err); ok { + if s.Code() == codes.NotFound { + return resp, errdefs.NotFound(err) + } + } + return resp, err + } + + if err = json.Unmarshal(grpcResp.Response, &resp); err != nil { + return resp, fmt.Errorf("unmarshal gRPC response: %w", err) + } + return resp, nil +} + // StartContainer starts a container with the given ID and options. func (c *Client) StartContainer(ctx context.Context, id string, opts container.StartOptions) error { optsBytes, err := json.Marshal(opts) diff --git a/internal/machine/docker/server.go b/internal/machine/docker/server.go index 4cf4170b..3a13999d 100644 --- a/internal/machine/docker/server.go +++ b/internal/machine/docker/server.go @@ -66,6 +66,24 @@ func (s *Server) CreateContainer(ctx context.Context, req *pb.CreateContainerReq return &pb.CreateContainerResponse{Response: respBytes}, nil } +// InspectContainer returns the container information for the given container ID. +func (s *Server) InspectContainer(ctx context.Context, req *pb.InspectContainerRequest) (*pb.InspectContainerResponse, error) { + 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.Internal, "inspect container: %v", err) + } + + respBytes, err := json.Marshal(resp) + if err != nil { + return nil, status.Errorf(codes.Internal, "marshal response: %v", err) + } + + return &pb.InspectContainerResponse{Response: respBytes}, nil +} + // StartContainer starts a container with the given ID and options. func (s *Server) StartContainer(ctx context.Context, req *pb.StartContainerRequest) (*emptypb.Empty, error) { var opts container.StartOptions diff --git a/test/e2e/service_test.go b/test/e2e/service_test.go index 0b4802af..9d4e2461 100644 --- a/test/e2e/service_test.go +++ b/test/e2e/service_test.go @@ -25,11 +25,21 @@ func TestService(t *testing.T) { t.Parallel() name := "busybox-container-lifecycle" - svc, err := cli.NewService(ctx, name) - require.NoError(t, err) + spec := api.ServiceSpec{ + Name: name, + Container: api.ContainerSpec{ + Command: []string{"sleep", "infinity"}, + Image: "busybox:latest", + }, + } + machineID := c.Machines[0].Name - assert.NotEmpty(t, svc.ID) - assert.Equal(t, name, svc.Name) + ctr, err := cli.CreateContainer(ctx, name, spec, machineID) + require.NoError(t, err) + assert.NotEmpty(t, ctr.ID) + + err = cli.StartContainer(ctx, ctr.ID, machineID) + require.NoError(t, err) }) }