feat(docker, firewall): Add stateful network connection check and optimize NAT rules
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This adds an IsConnected method to verify if a container is already connected to a network with the expected IP, preventing redundant operations. In reconcileIPs, it skips reconnections if the state is correct. In applyNATRule, MASQUERADE is now applied in the same namespace as DNAT (container or host) for consistent and accurate rule application.
This commit is contained in:
@@ -31,6 +31,7 @@ type DockerAPI interface {
|
||||
GetContainerPID(ctx context.Context, containerName string) (int, error)
|
||||
AddRouteInContainer(ctx context.Context, containerName, network, gateway string) error
|
||||
FindContainerName(ctx context.Context, name, selector string) (string, error)
|
||||
IsConnected(ctx context.Context, containerName, networkName, expectedIP string) bool
|
||||
}
|
||||
|
||||
// Client wraps the Docker SDK client
|
||||
@@ -308,4 +309,42 @@ func (c *Client) FindContainerName(ctx context.Context, name, selector string) (
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no running container found matching name=%q selector=%q", name, selector)
|
||||
}
|
||||
}
|
||||
|
||||
// IsConnected checks if a container is already connected to a network with the expected IP.
|
||||
// Returns true if the connection already exists with the correct IP (stateful check).
|
||||
func (c *Client) IsConnected(ctx context.Context, containerName, networkName, expectedIP string) bool {
|
||||
logger.Debug("DOCKER: checking if container %q is connected to %q with IP %s", containerName, networkName, expectedIP)
|
||||
|
||||
containers, err := c.cli.ContainerList(ctx, container.ListOptions{
|
||||
Filters: filters.NewArgs(
|
||||
filters.Arg("name", "^/?"+regexp.QuoteMeta(containerName)+"$"),
|
||||
filters.Arg("status", "running"),
|
||||
),
|
||||
})
|
||||
if err != nil || len(containers) == 0 {
|
||||
logger.Debug("DOCKER: container %q not found or error: %v", containerName, err)
|
||||
return false
|
||||
}
|
||||
|
||||
// Check the network settings for the expected IP
|
||||
inspect, err := c.cli.ContainerInspect(ctx, containerName)
|
||||
if err != nil {
|
||||
logger.Debug("DOCKER: inspect failed for %q: %v", containerName, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if inspect.NetworkSettings != nil && inspect.NetworkSettings.Networks != nil {
|
||||
if netSettings, ok := inspect.NetworkSettings.Networks[networkName]; ok {
|
||||
currentIP := netSettings.IPAddress
|
||||
logger.Debug("DOCKER: container %q on network %q has IP=%s (expected=%s)", containerName, networkName, currentIP, expectedIP)
|
||||
if currentIP == expectedIP {
|
||||
logger.Debug("DOCKER: container %q already correctly connected to %q with IP %s", containerName, networkName, expectedIP)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.Debug("DOCKER: container %q not yet correctly connected to %q", containerName, networkName)
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user