provisioning-catalog/lib/gateway-tcp.sh

86 lines
3.3 KiB
Bash

#!/bin/bash
# Shared primitives for TCP Gateway listener and TCPRoute lifecycle.
#
# Source from component *-lib.sh scripts. Requires _kubectl to be defined
# in the calling context (standard in all catalog component libs).
#
# Functions:
# _lib_gateway_patch_tcp <gw_name> <gw_ns> <listener_name> <port>
# _lib_gateway_remove_tcp <gw_name> <gw_ns> <listener_name>
# _lib_upsert_tcproute <route_name> <route_ns> <gw_name> <gw_ns> <section_name> <svc_name> <port>
# _lib_delete_tcproute <route_name> <route_ns>
# Upsert a TCP listener on a Gateway. Idempotent.
_lib_gateway_patch_tcp() {
local gw_name="$1" gw_ns="$2" listener_name="$3" port="$4"
# kubectl does the lookup server-side (jsonpath filter by name) — the node
# receives only the matched name, so no JSON parser is needed here.
local exists=""
[ -n "$(_kubectl get gateway "$gw_name" -n "$gw_ns" \
-o "jsonpath={.spec.listeners[?(@.name=='${listener_name}')].name}" 2>/dev/null)" ] \
&& exists="yes"
if [ "${exists:-no}" = "yes" ]; then
echo " [skip] gateway listener ${listener_name} (TCP:${port}) already exists"
return 0
fi
local patch
patch=$(printf '[{"op":"add","path":"/spec/listeners/-","value":{"name":"%s","port":%s,"protocol":"TCP","allowedRoutes":{"namespaces":{"from":"All"}}}}]' \
"$listener_name" "$port")
_kubectl patch gateway "$gw_name" -n "$gw_ns" --type=json -p "$patch"
echo " [ok] gateway ${gw_name}: TCP listener ${listener_name} added on port ${port}"
}
# Remove a TCP listener from a Gateway by name. No-op if absent.
_lib_gateway_remove_tcp() {
local gw_name="$1" gw_ns="$2" listener_name="$3"
# Find the listener's array index for the JSON-patch path. kubectl streams the
# names in order (jsonpath range); bash counts to the match — no JSON parser.
local idx="" _i=0 _n
while IFS= read -r _n; do
[ "$_n" = "$listener_name" ] && { idx="$_i"; break; }
_i=$((_i + 1))
done < <(_kubectl get gateway "$gw_name" -n "$gw_ns" \
-o 'jsonpath={range .spec.listeners[*]}{.name}{"\n"}{end}' 2>/dev/null)
[ -z "$idx" ] && { echo " [skip] gateway listener ${listener_name} not found"; return 0; }
_kubectl patch gateway "$gw_name" -n "$gw_ns" --type=json \
-p "[{\"op\":\"remove\",\"path\":\"/spec/listeners/${idx}\"}]"
echo " [ok] gateway ${gw_name}: TCP listener ${listener_name} removed"
}
# Create or replace a TCPRoute routing a Gateway TCP listener to a ClusterIP Service.
_lib_upsert_tcproute() {
local route_name="$1" route_ns="$2" gw_name="$3" gw_ns="$4" section_name="$5" svc_name="$6" port="$7"
_kubectl apply -f - <<ROUTE
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: ${route_name}
namespace: ${route_ns}
labels:
app.kubernetes.io/managed-by: provisioning
spec:
parentRefs:
- name: ${gw_name}
namespace: ${gw_ns}
sectionName: ${section_name}
rules:
- backendRefs:
- name: ${svc_name}
port: ${port}
ROUTE
echo " [ok] TCPRoute ${route_ns}/${route_name}${svc_name}:${port} via ${gw_name}/${section_name}"
}
# Delete a TCPRoute. No-op if absent.
_lib_delete_tcproute() {
local route_name="$1" route_ns="$2"
_kubectl delete tcproute/"${route_name}" --namespace "${route_ns}" --ignore-not-found
echo " [ok] TCPRoute ${route_ns}/${route_name} deleted (if existed)"
}