feat(apps): onboard pihole via renderer + --no-image-automation flag (WS-APPS golden path)

First app onboarded through catalog/render.py -> apps/. Added --no-image-automation so apps
deploy before the Flux image controllers exist (L1 goldens keep the default, unchanged).
KNOWN GAP surfaced: exposed apps get default-deny (ingress: []) with no gateway-ingress allow,
so the HTTPRoute path is blocked — renderer/WS-NET follow-up to allow Cilium gateway ingress
to services with an exposure/HTTPRoute.
This commit is contained in:
jakman85 committed 2026-08-24 23:27:22 -05:00
1 parent 34e4b191f1
commit e843db2601
3 files changed
+203 -8

No files matched your search

+20 -8
View File
@@ -580,8 +580,14 @@ def r_virtualmachine(s: dict) -> dict:
# =============================================================================
# Top-level render + emit
# =============================================================================
def render(sd: dict) -> list:
"""Return an ordered list of (header_comment, resource_dict) for a ServiceDefinition."""
def render(sd: dict, image_automation: bool = True) -> list:
"""Return an ordered list of (header_comment, resource_dict) for a ServiceDefinition.
image_automation=False omits the Flux ImageRepository/ImagePolicy CRs — used when
onboarding apps before the Flux image-reflector/-automation controllers are installed
(their CRDs would otherwise be missing and the apps Kustomization would fail). The L1
render goldens use the default (True), so their expected output is unchanged.
"""
s = apply_defaults(sd)
if s["kind"] not in ("container", "vm"):
raise ValueError(f"unknown kind: {s['kind']!r}")
@@ -620,8 +626,9 @@ def render(sd: dict) -> list:
if pr:
docs.append(("PrometheusRule SLI alerts (R-OBS-01)", pr))
for res in r_image_automation(s):
docs.append((f"Flux {res['kind']} (R-UPD)", res))
if image_automation:
for res in r_image_automation(s):
docs.append((f"Flux {res['kind']} (R-UPD)", res))
return docs
@@ -645,8 +652,8 @@ def load_sd(path: Path) -> dict:
return yaml.safe_load(fh)
def render_file(path: Path) -> str:
return emit(render(load_sd(path)))
def render_file(path: Path, image_automation: bool = True) -> str:
return emit(render(load_sd(path), image_automation=image_automation))
# =============================================================================
@@ -745,16 +752,21 @@ def main(argv=None) -> int:
ap.add_argument("--all", metavar="DIR", help="Render every *.yaml ServiceDefinition in DIR")
ap.add_argument("-o", "--out-dir", help="With --all: write <name>.yaml files into this dir")
ap.add_argument("--selftest", action="store_true", help="Run the built-in self-test")
ap.add_argument("--no-image-automation", action="store_true",
help="Omit Flux ImageRepository/ImagePolicy CRs (for onboarding before the "
"image-reflector/-automation controllers are installed)")
args = ap.parse_args(argv)
if args.selftest:
return _selftest()
image_automation = not args.no_image_automation
if args.all:
src = Path(args.all)
files = sorted(p for p in src.glob("*.yaml") if p.name != "render.py")
for f in files:
text = render_file(f)
text = render_file(f, image_automation=image_automation)
if args.out_dir:
outdir = Path(args.out_dir)
outdir.mkdir(parents=True, exist_ok=True)
@@ -766,7 +778,7 @@ def main(argv=None) -> int:
if not args.input:
ap.error("provide a ServiceDefinition file, --all DIR, or --selftest")
sys.stdout.write(render_file(Path(args.input)))
sys.stdout.write(render_file(Path(args.input), image_automation=image_automation))
return 0