provisioning-catalog/components/private_ingress/cluster/vars.nu

159 lines
5.1 KiB
Text

#!/usr/bin/env nu
# Derived variables for private_ingress bundle rendering.
# Reads the component JSON, outputs Tera context vars as JSON.
def slug_from_host [host: string]: nothing -> string {
$host | str replace --all "." "-"
}
def resolve_cluster_ip [upstream: string, cp_host: string]: nothing -> string {
# upstream is a K8s FQDN: <svc>.<ns>.svc.<domain> — extract svc+ns and resolve ClusterIP via SSH
let parts = ($upstream | split row ".")
if ($parts | length) < 2 { return $upstream }
let svc = ($parts | first)
let ns = ($parts | get 1)
let r = (do { ^ssh $cp_host $"kubectl get svc ($svc) -n ($ns) -o jsonpath='{.spec.clusterIP}'" } | complete)
if $r.exit_code != 0 or ($r.stdout | is-empty) {
error make { msg: $"Could not resolve ClusterIP for ($svc).($ns): ($r.stderr | str trim)" }
}
$r.stdout | str trim | str replace "'" "" | str replace "'" ""
}
def sozu_cluster_block [route: record, cp_host: string]: nothing -> string {
let slug = (slug_from_host $route.host)
let cert_path = $"/etc/sozu/tls/($route.host)/tls.crt"
let key_path = $"/etc/sozu/tls/($route.host)/tls.key"
let clusterip = (resolve_cluster_ip $route.upstream $cp_host)
[
$"[clusters.($slug)]",
"protocol = \"http\"",
"",
$"[[clusters.($slug).frontends]]",
"address = \"0.0.0.0:8443\"",
$"hostname = \"($route.host)\"",
$"certificate = \"($cert_path)\"",
$"certificate_chain = \"($cert_path)\"",
$"key = \"($key_path)\"",
"",
$"[[clusters.($slug).backends]]",
$"backend_id = \"($slug)-0\"",
$"address = \"($clusterip):($route.port)\"",
] | str join "\n"
}
def secret_volume_entry [route: record]: nothing -> string {
let slug = (slug_from_host $route.host)
let secret_name = $"private-ingress-tls-($slug)"
[
$"- name: tls-($slug)",
" secret:",
$" secretName: ($secret_name)",
" items:",
" - key: tls.crt",
" path: tls.crt",
" - key: tls.key",
" path: tls.key",
] | str join "\n"
}
def secret_mount_entry [route: record]: nothing -> string {
let slug = (slug_from_host $route.host)
[
$"- name: tls-($slug)",
$" mountPath: /etc/sozu/tls/($route.host)",
" readOnly: true",
] | str join "\n"
}
def certificate_entry [route: record, cluster_issuer: string, namespace: string]: nothing -> string {
let slug = (slug_from_host $route.host)
let secret_name = $"private-ingress-tls-($slug)"
$"---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ($secret_name)
namespace: ($namespace)
labels:
app.kubernetes.io/name: private-ingress
app.kubernetes.io/managed-by: provisioning
spec:
secretName: ($secret_name)
duration: 2160h
renewBefore: 720h
dnsNames:
- ($route.host)
issuerRef:
name: ($cluster_issuer)
kind: ClusterIssuer
group: cert-manager.io"
}
def main [component_json: string]: nothing -> nothing {
let d = ($component_json | from json)
let ns = ($d.namespace? | default "ingress-private")
let name = ($d.name? | default "private-ingress")
let image = ($d.image? | default "ghcr.io/sozu-proxy/sozu:1.0.3")
let cluster_issuer = ($d.cluster_issuer? | default "letsencrypt-prod-librecloud")
let routes = ($d.routes? | default [])
let private_lb_ip = ($d.private_lb_ip? | default "")
let cp_host = ($d.cp_host? | default "libre-wuji-cp-0")
let cluster_blocks = (
$routes
| each { |r| sozu_cluster_block $r $cp_host }
| str join "\n\n"
)
let sozu_config = [
"[config]",
"log_level = \"info\"",
"log_target = \"stdout\"",
"worker_count = 2",
"command_socket = \"/var/run/sozu/sozu.sock\"",
"",
"[[listeners]]",
"protocol = \"https\"",
"address = \"0.0.0.0:8443\"",
"",
# HTTP listener removed — sozu v2 answer_301 requires a file path, not URL template.
# Port 80 on the LB Service remains open (connections get TCP reset) until
# a proper redirect file/mechanism is configured.
"",
$cluster_blocks,
] | str join "\n"
let tls_volumes = (
$routes
| each { |r| secret_volume_entry $r }
| str join "\n"
)
let tls_mounts = (
$routes
| each { |r| secret_mount_entry $r }
| str join "\n"
)
let certificates_yaml = (
$routes
| each { |r| certificate_entry $r $cluster_issuer $ns }
| str join "\n"
)
{
sozu_config: $sozu_config,
tls_volumes: $tls_volumes,
tls_mounts: $tls_mounts,
certificates_yaml: $certificates_yaml,
private_lb_ip: $private_lb_ip,
namespace: $ns,
name: $name,
image: $image,
cluster_issuer: $cluster_issuer,
}
| to json --raw
| print
}