Skip to content

Commit e548195

Browse files
authored
Fix bug where one workload name is a prefix substring of another (#1234)
My recent change to use names as IDs included a function which uses the Docker API to search for the matching workload container by name. The Docker API uses prefix searching. If you have two workloads, and one workload is a prefix substring of the other, searching for the shorter name will match both and return an error (an error case I ironically assumed would never happen...) This changes the code to explicitly filter down the list using the exact name in the case where more than one container is returned by Docker. I have validated this by reproducing the scenario that was provided when the bug was reported.
1 parent d59e595 commit e548195

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

pkg/container/docker/client.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"io"
1111
"os"
1212
"path/filepath"
13+
"slices"
1314
"strconv"
1415
"strings"
1516
"time"
@@ -1528,14 +1529,29 @@ func (c *Client) inspectContainerByName(ctx context.Context, workloadName string
15281529
return empty, NewContainerError(err, "", fmt.Sprintf("failed to list containers: %v", err))
15291530
}
15301531

1531-
// ASSUMPTION: There should either be no containers found, or exactly one.
15321532
if len(containers) == 0 {
15331533
return empty, NewContainerError(runtime.ErrWorkloadNotFound, workloadName, "no containers found")
15341534
}
1535-
// This should never happen (I hope).
1535+
// Docker does a prefix match on the name. If we find multiple containers,
1536+
// we need to filter down to the exact name requested.
1537+
var containerID string
15361538
if len(containers) > 1 {
1537-
return empty, NewContainerError(ErrMultipleContainersFound, workloadName, "multiple containers found with the same name")
1539+
// The name in the API has a leading slash, so we need to search for that.
1540+
prefixedName := "/" + workloadName
1541+
// The name in the API response is a list of names, so we need to check
1542+
// if the prefixed name is in the list.
1543+
// The extra names are used for docker network functionality which is
1544+
// not relevant for us.
1545+
idx := slices.IndexFunc(containers, func(c container.Summary) bool {
1546+
return slices.Contains(c.Names, prefixedName)
1547+
})
1548+
if idx == -1 {
1549+
return empty, NewContainerError(runtime.ErrWorkloadNotFound, workloadName, "no containers found with the exact name")
1550+
}
1551+
containerID = containers[idx].ID
1552+
} else {
1553+
containerID = containers[0].ID
15381554
}
15391555

1540-
return c.client.ContainerInspect(ctx, containers[0].ID)
1556+
return c.client.ContainerInspect(ctx, containerID)
15411557
}

0 commit comments

Comments
 (0)