#!/usr/bin/env bash # Regression test: ArgoCD repo-server must be able to write to /var/run/argocd when # the manifest uses hostPath-backed volumes (common on k3d nodes). set -euo pipefail SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) KNOE_HOME=$(cd "$SCRIPT_DIR/../.." && pwd) MANIFEST="$KNOE_HOME/k8s/argocd/install.yaml" python3 - "$MANIFEST" <<'PY' import sys # NOTE: Avoid a dependency on PyYAML; validate via text scanning and block extraction. import re path = sys.argv[1] text = open(path, "r", encoding="utf-8").read() docs = [] buf = [] for line in text.splitlines(True): if line.strip() == "---": docs.append("".join(buf)) buf = [] continue buf.append(line) docs.append("".join(buf)) def is_target(doc: str) -> bool: return ( re.search(r"(?m)^kind:\s*Deployment\s*$", doc) is not None and re.search(r"(?m)^\s*name:\s*argocd-repo-server\s*$", doc) is not None ) targets = [d for d in docs if is_target(d)] assert len(targets) == 1, f"expected exactly 1 argocd-repo-server deployment doc, got {len(targets)}" doc = targets[0] def extract_block_after_key(text: str, key: str) -> tuple[int, str]: m = re.search(rf"(?m)^(?P\s*){re.escape(key)}:\s*$", text) assert m, f"missing key '{key}:'" base_indent = len(m.group("indent")) lines = text[m.end() :].splitlines(True) out = [] for ln in lines: if not ln.strip(): out.append(ln) continue ind = len(ln) - len(ln.lstrip(" ")) # Block ends when we return to a sibling key (same indent, not a list item) or higher. if ind < base_indent: break if ind == base_indent and not ln.lstrip().startswith("-"): break out.append(ln) return base_indent, "".join(out) def split_list_items(block: str, item_indent: int) -> list[str]: items: list[list[str]] = [] current: list[str] = [] for ln in block.splitlines(True): if not ln.strip(): if current: current.append(ln) continue ind = len(ln) - len(ln.lstrip(" ")) if ind == item_indent and ln.lstrip().startswith("-"): if current: items.append(current) current = [ln] else: if current: current.append(ln) if current: items.append(current) return ["".join(i) for i in items] def find_list_item_with_name(items: list[str], name: str) -> str: for it in items: if re.search(rf"(?m)^\s*name:\s*{re.escape(name)}\s*$", it): return it raise AssertionError(f"missing initContainer '{name}'") ic_indent, ic_block = extract_block_after_key(doc, "initContainers") ic_items = split_list_items(ic_block, ic_indent) init_perm = find_list_item_with_name(ic_items, "init-permissions") copyutil = find_list_item_with_name(ic_items, "copyutil") assert re.search(r"(?m)^\s*runAsUser:\s*0\s*$", init_perm), "init-permissions must run as root (runAsUser: 0)" assert "chown" in init_perm, "init-permissions should attempt chown when possible" assert "chown failed" in init_perm, "init-permissions must tolerate chown failures" assert "chmod 0777" in init_perm, "init-permissions must apply permissive chmod when chown is not allowed" def list_item_has_mount(container_item: str, vol_name: str, mount_path: str) -> bool: vm_indent, vm_block = extract_block_after_key(container_item, "volumeMounts") vm_items = split_list_items(vm_block, vm_indent) for it in vm_items: if re.search(rf"(?m)^\s*name:\s*{re.escape(vol_name)}\s*$", it) and re.search( rf"(?m)^\s*(?:-\s*)?mountPath:\s*{re.escape(mount_path)}\s*$", it ): return True return False required = [ ("var-files", "/var/run/argocd"), ("tmp", "/tmp"), ("helm-working-dir", "/helm-working-dir"), ("plugins", "/home/argocd/cmp-server/plugins"), ("gpg-keyring", "/app/config/gpg/keys"), ] missing = [(n, p) for (n, p) in required if not list_item_has_mount(init_perm, n, p)] assert not missing, f"init-permissions missing required mounts (name, mountPath): {missing}" assert list_item_has_mount(copyutil, "var-files", "/var/run/argocd"), "copyutil must mount var-files at /var/run/argocd" assert "/var/run/argocd/argocd" in copyutil, "copyutil must copy argocd binary into /var/run/argocd" print("OK") PY echo "SUCCESS"