# One target per ctrl/ script; the subcommand is an argument, not a second # target: `make estate show`, not `make estate-show`. The logic lives in the # scripts, never here. # # Config layers, weakest first: ctrl/versions.env < ctrl/env.d/.env < # ctrl/.env < the environment. So `make estate plan TARGET=gcp` beats all. # # Every target defaults to its READ-ONLY verb, and the verbs that change a live # estate are not reachable by a bare word. Rationale: README.md. ESTATE := $(or $(shell sed -n 's/^ESTATE=//p' ctrl/.env 2>/dev/null),$(shell ls estate/*.json 2>/dev/null | head -1 | xargs -r basename | sed 's/\.json$$//')) TARGET := $(or $(shell sed -n 's/^TARGET=//p' ctrl/.env 2>/dev/null),aws) .PHONY: help check selftest estate services vpn dns certs host ports registry docs help: ## list targets @grep -hE '^[a-z][a-z-]*:.*?##' $(MAKEFILE_LIST) | sed 's/:.*##/\t/' | expand -t16 # ── preflight ────────────────────────────────────────────────────────────── check: ## is this estate coherent? reports, never fixes bash ctrl/check.sh selftest: ## does berth still do what it says? exits 1 if not bash ctrl/selftest.sh ports: ## port map [show|verify] (default show) bash ctrl/ports.sh $(or $(ARGS),show) # ── the estate ───────────────────────────────────────────────────────────── estate: ## the estate [show|list|plan|apply|destroy] (default show) bash ctrl/estate.sh $(or $(ARGS),show) services: ## gateway routes [list|render |deploy] (default list) bash ctrl/services.sh $(or $(ARGS),list) # ── the network ──────────────────────────────────────────────────────────── vpn: ## overlays [list|show |check|render|keygen] (default list) bash ctrl/vpn.sh $(or $(ARGS),list) # ── names and trust ──────────────────────────────────────────────────────── dns: ## DNS records [list|add|add-wildcard|remove] (default list) bash ctrl/dns.sh $(or $(ARGS),list) certs: ## TLS [status|verify|renew|push] (default status) bash ctrl/certs.sh $(or $(ARGS),status) # ── the box ──────────────────────────────────────────────────────────────── host: ## the remote box [status|ports|services] (default status) bash ctrl/host.sh $(or $(ARGS),status) registry: ## the image registry [status] (default status) bash ctrl/registry.sh $(or $(ARGS),status) # ── docs ─────────────────────────────────────────────────────────────────── docs: ## documentation [serve|graphs] (default serve) bash ctrl/docs.sh $(or $(ARGS),serve) # ── swallowing the argument words — MUST BE LAST IN THIS FILE ────────────── # # Words after the target are arguments, but make reads each as a goal, so each # gets a no-op rule. This block must come AFTER the real targets: when an # argument names one (`make host ports`, `make vpn check`), the last definition # wins, and it has to be the no-op. With it first, make ran both scripts. # # Make's "overriding recipe" warning is the swallow working as intended. ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) ifneq ($(ARGS),) $(eval $(ARGS):;@:) # .PHONY too: some of those words name real directories (ctrl, estate, render), # and make treats an existing directory as already built. .PHONY: $(ARGS) endif