provisioning/schemas/lib/concerns_presets.ncl

194 lines
8.2 KiB
Text
Raw Normal View History

# Reusable ServiceConcerns presets for component defaults.
#
# Component contracts.ncl files declare `concerns | _concerns_lib.ServiceConcerns | optional`
# and their defaults.ncl files set `concerns | default = presets.<preset>` to give
# the component an honest declarative surface without repeating boilerplate.
#
# Presets cover the recurring archetypes in libre-wuji:
# - stateless : no TLS/DNS/data — most container runtimes,
# kernel modules, OS-level taskservs
# - infra_storage_managed : storage backends that handle their own
# backup outside per-component policies
# (Longhorn engine state via SystemBackupDef)
# - tls_endpoint_with_acme : public service with cert-manager TLS
# and ACME issuer config; backup decided
# at workspace level
# - observability_telemetry : Prometheus/Grafana/Loki/Vector — config
# in git, data either transient or already
# shipped to S3
# - infrastructure_glue : controllers/operators with no user data
# (cilium, hccm, csi, ops-controller)
let _pending_obs = {
kind = 'pending,
reason = "ObservabilityImpl iteration deferred — surface stub only",
backlog_ref = "OBS-001",
} in
let _pending_sec = {
kind = 'pending,
reason = "SecurityImpl iteration deferred — surface stub only",
backlog_ref = "SEC-001",
} in
{
presets = {
# ── Stateless service ────────────────────────────────────────────────
# Container runtimes (containerd, runc, crun, youki), OS modules,
# kernel-level taskservs. No persistent state, no network endpoints
# exposed at the component level.
stateless = {
tls = { kind = 'disabled, reason = "no TLS termination at this layer" },
dns = { kind = 'disabled, reason = "no DNS records owned by this component" },
certs = { kind = 'disabled, reason = "no ACME issuer required" },
backup = {
kind = 'disabled,
reason = "stateless: configuration in git, no runtime data to capture",
},
observability = _pending_obs,
security = _pending_sec,
},
# ── Storage backend with its own backup model ────────────────────────
# Longhorn (engine state in SystemBackupDef.longhorn_engine), local-path
# provisioner, Hetzner CSI, democratic CSI. Their data is captured by
# the system-level backup, not per-component.
infra_storage_managed = {
tls = { kind = 'disabled, reason = "internal cluster storage, no TLS endpoint" },
dns = { kind = 'disabled, reason = "no DNS records owned by this component" },
certs = { kind = 'disabled, reason = "no ACME issuer required" },
backup = {
kind = 'disabled,
reason = "engine state captured by SystemBackupDef.longhorn_engine (or equivalent system target)",
},
observability = _pending_obs,
security = _pending_sec,
},
# ── Public service with cert-manager TLS + ACME ──────────────────────
# docker-mailserver, odoo, zot, anything that terminates HTTPS or SMTPS
# via cert-manager. Tls/Dns/Certs concerns get populated from existing
# tls_secret/cluster_issuer/cert/dns_records fields. Backup decided at
# workspace level (concerns.backup overridden in infra/<workspace>/components/<x>.ncl).
tls_endpoint_with_acme = fun args =>
{
tls = {
kind = 'enabled,
tls_impl = {
secret_name = args.tls_secret,
issuer_ref = args.cluster_issuer,
hostnames = args.hostnames,
},
},
dns = {
kind = 'enabled,
dns_impl = {
internal = args.dns_internal,
zone = args.dns_zone,
},
},
certs = {
kind = 'enabled,
certs_impl = {
acme_server = args.acme_server,
email = args.acme_email,
secret_ref = args.cert_secret_ref,
provider = args.cert_provider,
},
},
backup = {
kind = 'pending,
reason = "BackupPolicy declared at workspace level",
backlog_ref = args.backup_backlog_ref,
},
observability = _pending_obs,
security = _pending_sec,
},
# ── Observability stack components (Prometheus/Grafana/Loki/Vector) ──
# No user data; configuration in git; metric/log data either transient
# (Prometheus WAL) or already shipped to S3 (Loki via boltdb-shipper).
observability_telemetry = {
tls = { kind = 'disabled, reason = "internal cluster service, ingress-level TLS handled separately" },
dns = { kind = 'disabled, reason = "no DNS records owned by this component" },
certs = { kind = 'disabled, reason = "no ACME issuer required" },
backup = {
kind = 'disabled,
reason = "config in git; runtime data either transient or shipped to S3 backend",
},
observability = {
kind = 'enabled,
observability_impl = {
metrics = { enabled = true, port = 9090, path = "/metrics" },
logs = { enabled = true, sink = 'loki },
traces = { enabled = false },
alerts = [],
},
},
security = _pending_sec,
},
# ── Infrastructure glue (controllers/operators) ──────────────────────
# cilium, hccm, hetzner-csi, ops-controller. State lives in K8s API,
# captured by SystemBackupDef.cluster_resources.
infrastructure_glue = {
tls = { kind = 'disabled, reason = "controller-level RBAC, not TLS endpoint" },
dns = { kind = 'disabled, reason = "no DNS records owned by this component" },
certs = { kind = 'disabled, reason = "no ACME issuer required" },
backup = {
kind = 'disabled,
reason = "state in K8s API captured by SystemBackupDef.cluster_resources",
},
observability = _pending_obs,
security = _pending_sec,
},
# ── DNS provider service (CoreDNS, external-dns) ─────────────────────
# Owns DNS records but typically not TLS endpoint of its own.
dns_provider = {
tls = { kind = 'disabled, reason = "DNS server, not TLS endpoint" },
dns = {
kind = 'enabled,
dns_impl = {
internal = [],
zone = "",
},
},
certs = { kind = 'disabled, reason = "no ACME issuer required" },
backup = {
kind = 'pending,
reason = "zone files captured by SystemBackupDef.external_dns",
backlog_ref = "BACKUP-DNS-001",
},
observability = _pending_obs,
security = _pending_sec,
},
# ── Database (PostgreSQL, MariaDB, SurrealDB) ─────────────────────────
# Backup with database scope + dump strategy. Decided at workspace level.
database = {
tls = { kind = 'disabled, reason = "internal cluster service, ingress-level TLS handled separately" },
dns = { kind = 'disabled, reason = "no public DNS records" },
certs = { kind = 'disabled, reason = "no ACME issuer required" },
backup = {
kind = 'pending,
reason = "BackupPolicy with database scope + dump_strategy declared at workspace level",
backlog_ref = "BACKUP-DB-001",
},
observability = _pending_obs,
security = _pending_sec,
},
},
# ── Helper for components that need to compose a custom ServiceConcerns
# from individual variants (rather than picking a preset wholesale).
builders = {
pending = fun reason backlog => {
kind = 'pending,
reason = reason,
backlog_ref = backlog,
},
disabled = fun reason => { kind = 'disabled, reason = reason },
},
}