Fix prole.cfg portability: preserve HOME tokens, block KUBECONTEXT pollution, keep CNPG Clusters section

- _sanitize_sections_for_cfg(): wrap _expand_shell_path() with _cfgify_home_path() so
  paths are stored as dollar-HOME/... instead of /home/user/... (Mac to myrddin breakage)
- _write_cfg(): pop KUBECONTEXT from globals_to_save so Mac k3d context never persists
- _write_cfg(): add CNPG Clusters to sections list so user-authored registry survives write-back
- milestone._get_script_env(): _GLOBAL_CFG_PROPAGATION_BLOCK excludes KUBECONTEXT, HOME,
  USER from Global config propagation -- stops knoe.dev.prole.org injected into kubectl calls
- milestone._get_script_env(): env.pop KUBECONTEXT after k3s KUBECONFIG detection so
  kubectl uses kubeconfig current-context (default) on k3s, not a stale Mac context name
- conf/service/prole.cfg: remove stale KUBECONTEXT = knoe.dev.prole.org from Global

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
chrisfu 2026-04-11 16:15:59 -07:00
parent 6318d232f0
commit 2eb6ae0626
3 changed files with 18 additions and 2 deletions

View File

@ -110,7 +110,6 @@ GITEA_NODE_SELECTOR = gandalf.prole.org
K3S_SERVER = https://myrddin.prole.org:6443 K3S_SERVER = https://myrddin.prole.org:6443
K3S_TOKEN = ${PROLE_SECRET:v1:gnQjvO_dhM7qkU_g:kFb7E6IQ40RM64JfsrJWBPzkJsMaLXNpNPxfho6t8w5KAeWCAyrw2bMsQtJ8n7cPc_SLWh_zX53Sa1pvEOclmd79e-c_Qff0gZleba1PzzfkjsYRfVlpzQ34gdAHrNHQG2mKnpkcyrNFZ0j6J-w4c3m_m6bTN1cV1KQvMQ==} K3S_TOKEN = ${PROLE_SECRET:v1:gnQjvO_dhM7qkU_g:kFb7E6IQ40RM64JfsrJWBPzkJsMaLXNpNPxfho6t8w5KAeWCAyrw2bMsQtJ8n7cPc_SLWh_zX53Sa1pvEOclmd79e-c_Qff0gZleba1PzzfkjsYRfVlpzQ34gdAHrNHQG2mKnpkcyrNFZ0j6J-w4c3m_m6bTN1cV1KQvMQ==}
KNOE_DB_USER = root KNOE_DB_USER = root
KUBECONTEXT = knoe.dev.prole.org
OPTIONAL_WORKLOADS_MIN_READY_SCHEDULABLE_NODES = 2 OPTIONAL_WORKLOADS_MIN_READY_SCHEDULABLE_NODES = 2
PROLE_K3S_SERVER = https://myrddin.prole.org:6443 PROLE_K3S_SERVER = https://myrddin.prole.org:6443
PROLE_K3S_TOKEN = ${PROLE_SECRET:v1:vCWJZS-Sd3PspQvq:vvRx07ahtfy0r5l8VlvOvDjz2N-Ejstk1ilhBhTiQwmgaxF4RLsDjzZb9rHLjuagjnujJ2jv7F_7s8IHXA6a1baxyn58zHFctXn3AJWPDEVGpEu-iUQDuc5bDOMEVmC73wJ3Ormxs7ihhkWSrbyjYpeRfQUjYesGvJTJ1Q==} PROLE_K3S_TOKEN = ${PROLE_SECRET:v1:vCWJZS-Sd3PspQvq:vvRx07ahtfy0r5l8VlvOvDjz2N-Ejstk1ilhBhTiQwmgaxF4RLsDjzZb9rHLjuagjnujJ2jv7F_7s8IHXA6a1baxyn58zHFctXn3AJWPDEVGpEu-iUQDuc5bDOMEVmC73wJ3Ormxs7ihhkWSrbyjYpeRfQUjYesGvJTJ1Q==}

View File

@ -786,7 +786,9 @@ class KnoeInstaller:
if _is_prole_secret(v) or _is_openbao_ref(v): if _is_prole_secret(v) or _is_openbao_ref(v):
continue continue
try: try:
section[k] = self._expand_shell_path(v, env=env_map) section[k] = self._cfgify_home_path(
self._expand_shell_path(v, env=env_map)
)
except Exception: except Exception:
section[k] = v section[k] = v
if "Kerberos Authentication" in sanitized: if "Kerberos Authentication" in sanitized:
@ -4514,6 +4516,7 @@ class KnoeConsoleInstaller(KnoeInstaller):
globals_to_save["DEPLOYMENT_TARGET"] = target_label globals_to_save["DEPLOYMENT_TARGET"] = target_label
globals_to_save.pop("NAMESPACE", None) globals_to_save.pop("NAMESPACE", None)
globals_to_save.pop("CNPG_CLUSTER_NAME", None) globals_to_save.pop("CNPG_CLUSTER_NAME", None)
globals_to_save.pop("KUBECONTEXT", None) # machine-specific; always runtime-detected
globals_to_save.setdefault("ARGOCD_NAMESPACE", self._argocd_namespace()) globals_to_save.setdefault("ARGOCD_NAMESPACE", self._argocd_namespace())
globals_to_save.setdefault("REGISTRY_NAMESPACE", self._registry_namespace()) globals_to_save.setdefault("REGISTRY_NAMESPACE", self._registry_namespace())
# Preserve Supabase placement vars from cfg — never let pipeline state overwrite them # Preserve Supabase placement vars from cfg — never let pipeline state overwrite them
@ -4597,6 +4600,7 @@ class KnoeConsoleInstaller(KnoeInstaller):
"Ollama", "Ollama",
"Optional Features", "Optional Features",
"GitOps", "GitOps",
"CNPG Clusters",
"Database Creation", "Database Creation",
"Initialize Cluster", "Initialize Cluster",
"Docker Build", "Docker Build",

View File

@ -142,8 +142,17 @@ class Milestone(ABC):
# (CNPG, monitoring, etc.) can access values declared in prole.cfg. # (CNPG, monitoring, etc.) can access values declared in prole.cfg.
# This mirrors what prole_cfg.sh does for shell subprocesses. # This mirrors what prole_cfg.sh does for shell subprocesses.
# We only set keys that are not already in env (env vars win over config). # We only set keys that are not already in env (env vars win over config).
# Machine-specific / runtime-detected values are excluded — they must
# never be sourced from a potentially stale config written on a different host.
_GLOBAL_CFG_PROPAGATION_BLOCK = frozenset({
"KUBECONTEXT", # runtime-detected: k3s="default", k8s=explicit context
"HOME", # OS-provided; never a config value
"USER", # OS-provided; never a config value
})
_global_cfg = (state.config_data.get("Global") or {}) _global_cfg = (state.config_data.get("Global") or {})
for _cfg_key, _cfg_val in _global_cfg.items(): for _cfg_key, _cfg_val in _global_cfg.items():
if _cfg_key in _GLOBAL_CFG_PROPAGATION_BLOCK:
continue
if _cfg_val is not None and str(_cfg_key) and _cfg_key not in env: if _cfg_val is not None and str(_cfg_key) and _cfg_key not in env:
env[_cfg_key] = str(_cfg_val) env[_cfg_key] = str(_cfg_val)
@ -159,6 +168,10 @@ class Milestone(ABC):
if _kc.exists(): if _kc.exists():
env["KUBECONFIG"] = str(_kc) env["KUBECONFIG"] = str(_kc)
break break
# k3s kubeconfig's current-context is authoritative (typically "default").
# Clear any stale KUBECONTEXT written from a different machine's config so
# kubectl uses KUBECONFIG without a --context override.
env.pop("KUBECONTEXT", None)
elif mode == "k3d": elif mode == "k3d":
# Ensure k3d dev clusters have a resolvable KUBECONFIG. # Ensure k3d dev clusters have a resolvable KUBECONFIG.
# The cluster may already be running from a previous session; # The cluster may already be running from a previous session;