package main # Gateway API resources require several fields to be set explicitly even though # the Gateway API controller defaults them. ArgoCD diffs desired vs live by # string comparison, so any field the controller defaults that is absent from # the git manifest causes a permanent OutOfSync. # # Affected resources: # HTTPRoute / TLSRoute — parentRefs and backendRefs (see PR #162, #165) # Gateway — listeners[*].tls.certificateRefs (see PR #153) _route_kinds := {"HTTPRoute", "TLSRoute"} # ---- parentRefs: group must be "gateway.networking.k8s.io" ---- deny contains msg if { _route_kinds[input.kind] ref := input.spec.parentRefs[i] object.get(ref, "group", null) != "gateway.networking.k8s.io" msg := sprintf( "%s %s/%s parentRefs[%d]: add 'group: gateway.networking.k8s.io' — controller defaults this field, causing ArgoCD OutOfSync when omitted", [input.kind, input.metadata.namespace, input.metadata.name, i], ) } # ---- parentRefs: kind must be "Gateway" ---- deny contains msg if { _route_kinds[input.kind] ref := input.spec.parentRefs[i] object.get(ref, "kind", null) != "Gateway" msg := sprintf( "%s %s/%s parentRefs[%d]: add 'kind: Gateway' — controller defaults this field, causing ArgoCD OutOfSync when omitted", [input.kind, input.metadata.namespace, input.metadata.name, i], ) } # ---- backendRefs: group must be present (may be empty string "") ---- deny contains msg if { _route_kinds[input.kind] rule := input.spec.rules[ri] ref := rule.backendRefs[bi] not _has_key(ref, "group") msg := sprintf( "%s %s/%s rules[%d].backendRefs[%d]: add 'group: \"\"' — controller defaults this field, causing ArgoCD OutOfSync when omitted", [input.kind, input.metadata.namespace, input.metadata.name, ri, bi], ) } # ---- backendRefs: kind must be "Service" ---- deny contains msg if { _route_kinds[input.kind] rule := input.spec.rules[ri] ref := rule.backendRefs[bi] object.get(ref, "kind", null) != "Service" msg := sprintf( "%s %s/%s rules[%d].backendRefs[%d]: add 'kind: Service' — controller defaults this field, causing ArgoCD OutOfSync when omitted", [input.kind, input.metadata.namespace, input.metadata.name, ri, bi], ) } # ---- backendRefs: weight must be present ---- deny contains msg if { _route_kinds[input.kind] rule := input.spec.rules[ri] ref := rule.backendRefs[bi] not _has_key(ref, "weight") msg := sprintf( "%s %s/%s rules[%d].backendRefs[%d]: add 'weight: 1' — controller defaults this field, causing ArgoCD OutOfSync when omitted", [input.kind, input.metadata.namespace, input.metadata.name, ri, bi], ) } # ---- Gateway certificateRefs: group must be present (may be empty string "") ---- deny contains msg if { input.kind == "Gateway" listener := input.spec.listeners[li] ref := listener.tls.certificateRefs[ci] not _has_key(ref, "group") msg := sprintf( "Gateway %s/%s listeners[%d].tls.certificateRefs[%d]: add 'group: \"\"' — admission webhook defaults this field, causing ArgoCD OutOfSync when omitted", [input.metadata.namespace, input.metadata.name, li, ci], ) } # ---- Helper: key presence check (works for null, "", and any defined value) ---- _has_key(obj, key) if { _ = obj[key] }