diff --git a/spinifex/network/external/igw.go b/spinifex/network/external/igw.go index 73bcfec7b..99b470db0 100644 --- a/spinifex/network/external/igw.go +++ b/spinifex/network/external/igw.go @@ -445,14 +445,26 @@ func (m *igwManager) ensureSubnetEgressAtPriority(ctx context.Context, vpcID, su if nexthop == "" { return fmt.Errorf("%s: no gateway nexthop available for %s (IGW not attached?)", opName, vpcID) } - return m.routes.AddSubnetEgress(ctx, vpcID, policy.SubnetEgressSpec{ + if err := m.routes.AddSubnetEgress(ctx, vpcID, policy.SubnetEgressSpec{ SubnetID: subnetID, Prefix: prefix, Nexthop: nexthop, OutputPort: topology.GatewayRouterPort(vpcID), Priority: priority, ExcludeCIDRs: m.rerouteExcludeCIDRs(ctx, vpcID), - }) + }); err != nil { + return err + } + // The priority-1100 drop gate is installed while a subnet is routeless and + // outranks both reroutes (IGW 1000, NATGW 900), so a gate left in place once + // a route lands black-holes the subnet's egress before it reaches routing or + // SNAT. Clear it now that this prefix has a reroute. Idempotent and + // prefix-scoped: gates only exist for the default route, so a specific-prefix + // reroute is a no-op and leaves the default gate intact. + if err := m.RemoveSubnetEgressDrop(ctx, vpcID, subnetID, prefix); err != nil { + return fmt.Errorf("%s: clear drop gate for %s: %w", opName, subnetID, err) + } + return nil } // EnsureSystemInstanceEgress installs a /32 reroute above the drop gate plus a plain