From f1a150821cf0f6903440cf480bcd50a618910e1f Mon Sep 17 00:00:00 2001 From: Pavel Sviderski Date: Sat, 22 Mar 2025 08:44:17 +1000 Subject: [PATCH] fix(compose): client.ImageInspect to handle broadcasted responses to multiple machines --- internal/machine/docker/client.go | 41 ++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/internal/machine/docker/client.go b/internal/machine/docker/client.go index fe4bf30e..66b1b31d 100644 --- a/internal/machine/docker/client.go +++ b/internal/machine/docker/client.go @@ -228,20 +228,43 @@ func (c *Client) PullImage(ctx context.Context, image string) (<-chan PullImageM return ch, nil } +type MachineImage struct { + Metadata *pb.Metadata + Image types.ImageInspect +} + // ImageInspect returns the image information for the given image ID. -func (c *Client) ImageInspect(ctx context.Context, id string) (types.ImageInspect, error) { - var resp types.ImageInspect - - grpcResp, err := c.grpcClient.InspectImage(ctx, &pb.InspectImageRequest{id: id}) +func (c *Client) ImageInspect(ctx context.Context, id string) ([]MachineImage, error) { + resp, err := c.grpcClient.InspectImage(ctx, &pb.InspectImageRequest{Id: id}) if err != nil { + // If the request was sent to only one machine, err is an actual error from the machine. if status.Convert(err).Code() == codes.NotFound { - return resp, errdefs.NotFound(err) + return nil, errdefs.NotFound(err) + } + return nil, err + } + + notFoundCount := 0 + for _, msg := range resp.Messages { + if msg.Metadata != nil && codes.Code(msg.Metadata.Status.Code) == codes.NotFound { + notFoundCount++ } - return resp, err } + if len(resp.Messages) == notFoundCount { + return nil, errdefs.NotFound(fmt.Errorf("image not found: %s", id)) + } + + images := make([]MachineImage, len(resp.Messages)) + for i, msg := range resp.Messages { + images[i].Metadata = msg.Metadata + if msg.Metadata != nil && msg.Metadata.Error != "" { + continue + } - if err = json.Unmarshal(grpcResp.Response, &resp); err != nil { - return resp, fmt.Errorf("unmarshal gRPC response: %w", err) + if err = json.Unmarshal(msg.Image, &images[i].Image); err != nil { + return nil, fmt.Errorf("unmarshal image: %w", err) + } } - return resp, nil + + return images, nil }