From 03a09c3788fcb15904ac19edea9a910e39204426 Mon Sep 17 00:00:00 2001 From: Giovanni Ferri Date: Sat, 8 Aug 2026 15:26:56 +0100 Subject: [PATCH] fix(oci): tag reserved public IPs so oci-free-tier-monitor doesn't race a failover MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CreateReservedPublicIP never set FreeformTags. oci-free-tier-monitor's orphan-IP cleanup only checks lifecycle_state == AVAILABLE, which a managed IP briefly reads during this controller's own detach/reattach on node failover — the monitor's scheduled scan could delete a live Service's VIP mid-reassignment. Tag every IP pivot creates with pivot.oci.io/managed: "true"; the monitor already skips anything carrying that tag regardless of lifecycle_state (syscode-labs/oci-free-tier-monitor, already fixed there). --- internal/oci/client.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/oci/client.go b/internal/oci/client.go index e2e3331..3ad0c9b 100644 --- a/internal/oci/client.go +++ b/internal/oci/client.go @@ -139,6 +139,14 @@ func (c *Client) CreateReservedPublicIP(ctx context.Context, privateIPOCID, disp Lifetime: core.CreatePublicIpDetailsLifetimeReserved, DisplayName: common.String(displayName), PrivateIpId: common.String(privateIPOCID), + // oci-free-tier-monitor's orphan-IP cleanup skips anything + // carrying this tag, regardless of lifecycle_state. Without it, + // the monitor's scheduled scan can race this controller's own + // detach/reattach during a failover — the IP briefly reads + // AVAILABLE mid-reassignment — and delete a live Service's VIP. + FreeformTags: map[string]string{ + "pivot.oci.io/managed": "true", + }, }, }) if err != nil {