feat: add idempotent route checks and container network routes
continuous-integration/drone/push Build is passing

- Make AddRouteInContainer idempotent by checking existing routes and handling "File exists" errors
- Add loop in firewall reconciler to add routes for containers to reach other networks
- Update iptables checks to include port for better rule distinction
This commit is contained in:
gyurix
2026-06-16 09:42:47 +02:00
parent 903bc1a7da
commit 77f80dea1b
3 changed files with 52 additions and 6 deletions
+23 -1
View File
@@ -215,13 +215,30 @@ func (c *Client) GetContainerPID(ctx context.Context, containerName string) (int
return cont.State.Pid, nil
}
// AddRouteInContainer adds a route inside a container's network namespace using nsenter
// AddRouteInContainer adds a route inside a container's network namespace using nsenter.
// Idempotent: checks if route already exists before adding.
func (c *Client) AddRouteInContainer(ctx context.Context, containerName, network, gateway string) error {
pid, err := c.GetContainerPID(ctx, containerName)
if err != nil {
return fmt.Errorf("failed to get PID for container %s: %w", containerName, err)
}
// First check if the route already exists
checkArgs := []string{
"-t", fmt.Sprintf("%d", pid),
"-n", "--",
"ip", "route", "show", network,
}
checkCmd := exec.Command("nsenter", checkArgs...)
checkOutput, _ := checkCmd.CombinedOutput()
checkStr := strings.TrimSpace(string(checkOutput))
// If the route exists and points to the correct gateway, skip
if checkStr != "" && strings.Contains(checkStr, gateway) {
logger.Debug("DOCKER: route %s via %s already exists in container %q, skipping", network, gateway, containerName)
return nil
}
logger.Info("DOCKER: adding route in container %q (PID=%d): %s via %s", containerName, pid, network, gateway)
args := []string{
"-t", fmt.Sprintf("%d", pid),
@@ -232,6 +249,11 @@ func (c *Client) AddRouteInContainer(ctx context.Context, containerName, network
cmd := exec.Command("nsenter", args...)
output, err := cmd.CombinedOutput()
if err != nil {
// "File exists" means route already exists (race condition)
if strings.Contains(string(output), "File exists") {
logger.Debug("DOCKER: route %s via %s already exists in container %q (File exists), skipping", network, gateway, containerName)
return nil
}
return fmt.Errorf("failed to add route in container %s: %w\noutput: %s", containerName, err, string(output))
}
logger.Info("DOCKER: route added in container %q: %s via %s", containerName, network, gateway)