refactor(docker): switch container lookup to use filtered ContainerList
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
Replace ContainerInspect with ContainerList and name filters for exact and prefix matching. This improves efficiency and correctness by leveraging Docker's filtering capabilities, matching the old shell script's grep behavior more accurately. Add regexp import to properly escape container names in filters.
This commit is contained in:
+35
-20
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -203,25 +204,37 @@ func (c *Client) AddRouteInContainer(ctx context.Context, containerName, network
|
||||
}
|
||||
|
||||
// FindContainerName attempts to find a running container by name or selector.
|
||||
// First tries the exact name, then tries listing running containers whose name
|
||||
// starts with the selector prefix (or the name prefix), matching the old shell
|
||||
// script's grep $D"-" behavior.
|
||||
// First tries exact name match, then exact selector, then prefix matching
|
||||
// (matching the old shell script's grep $D"-" behavior).
|
||||
func (c *Client) FindContainerName(ctx context.Context, name, selector string) (string, error) {
|
||||
// First try the exact name
|
||||
cont, err := c.cli.ContainerInspect(ctx, name)
|
||||
if err == nil && cont.State != nil && cont.State.Running {
|
||||
return name, nil
|
||||
// Try exact name match using ContainerList with a name filter
|
||||
// Docker API name filter does an exact match by default
|
||||
containers, err := c.cli.ContainerList(ctx, container.ListOptions{
|
||||
Filters: filters.NewArgs(
|
||||
filters.Arg("name", "^/?"+regexp.QuoteMeta(name)+"$"),
|
||||
filters.Arg("status", "running"),
|
||||
),
|
||||
})
|
||||
if err == nil && len(containers) > 0 {
|
||||
cName := strings.TrimPrefix(containers[0].Names[0], "/")
|
||||
return cName, nil
|
||||
}
|
||||
|
||||
// Try exact selector
|
||||
// Try exact selector match
|
||||
if selector != "" && selector != name {
|
||||
cont, err := c.cli.ContainerInspect(ctx, selector)
|
||||
if err == nil && cont.State != nil && cont.State.Running {
|
||||
return selector, nil
|
||||
containers, err = c.cli.ContainerList(ctx, container.ListOptions{
|
||||
Filters: filters.NewArgs(
|
||||
filters.Arg("name", "^/?"+regexp.QuoteMeta(selector)+"$"),
|
||||
filters.Arg("status", "running"),
|
||||
),
|
||||
})
|
||||
if err == nil && len(containers) > 0 {
|
||||
cName := strings.TrimPrefix(containers[0].Names[0], "/")
|
||||
return cName, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Try prefix matching with selector (old shell script behavior: grep $D"-")
|
||||
// Try prefix matching on both name and selector (shell script behavior: grep $D"-")
|
||||
candidates := []string{name, selector}
|
||||
for _, candidate := range candidates {
|
||||
if candidate == "" {
|
||||
@@ -233,21 +246,23 @@ func (c *Client) FindContainerName(ctx context.Context, name, selector string) (
|
||||
prefix = candidate[:strings.Index(candidate, "-")]
|
||||
}
|
||||
|
||||
containers, err := c.cli.ContainerList(ctx, container.ListOptions{})
|
||||
containers, err = c.cli.ContainerList(ctx, container.ListOptions{
|
||||
Filters: filters.NewArgs(
|
||||
filters.Arg("name", prefix+"-"),
|
||||
filters.Arg("status", "running"),
|
||||
),
|
||||
})
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, container := range containers {
|
||||
// Remove leading / from container names
|
||||
for _, cName := range container.Names {
|
||||
for _, c := range containers {
|
||||
for _, cName := range c.Names {
|
||||
cName = strings.TrimPrefix(cName, "/")
|
||||
if strings.HasPrefix(cName, prefix+"-") && container.State == "running" {
|
||||
return cName, nil
|
||||
}
|
||||
return cName, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no running container found matching name=%q selector=%q", name, selector)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user