feat(new-service): render __DOMAIN__ from INGRESS_DOMAIN; HTTPS URLs and health checks
Plan 11 step 7. INGRESS_DOMAIN=lab.holtlabs.xyz; health checks pin the host to INGRESS_IP on 443 and verify the wildcard cert. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
b133a0d120
commit
2a6971df03
4 changed files with 22 additions and 17 deletions
15
README.md
15
README.md
|
|
@ -37,11 +37,11 @@ new-service NAME --kind backend|frontend [--with postgres,redis] [--api BACKEND]
|
||||||
| 2 | generate public repo from `service-template-express` / `service-template-react` | repo exists |
|
| 2 | generate public repo from `service-template-express` / `service-template-react` | repo exists |
|
||||||
| 3 | set Actions secrets `REGISTRY_USER`, `REGISTRY_TOKEN`, `GITOPS_TOKEN` | never (PUT is idempotent) |
|
| 3 | set Actions secrets `REGISTRY_USER`, `REGISTRY_TOKEN`, `GITOPS_TOKEN` | never (PUT is idempotent) |
|
||||||
| 4 | create namespace + Secret `unleash-client-token` (copied from `unleash/unleash-init-tokens`) | they exist |
|
| 4 | create namespace + Secret `unleash-client-token` (copied from `unleash/unleash-init-tokens`) | they exist |
|
||||||
| 5 | render gitops `templates/<kind>` (+ `postgres`, `redis`) → `manifests/NAME`, `kustomize build` lint, commit, push | dir exists |
|
| 5 | render gitops `templates/<kind>` (+ `postgres`, `redis`; `__APP__`, `__API__`, `__DOMAIN__`) → `manifests/NAME`, `kustomize build` lint, commit, push | dir exists |
|
||||||
| 6 | clone repo to `$CODE_DIR/NAME`, push empty commit `chore: kick ci` | CI already deployed, or a kick is running/succeeded |
|
| 6 | clone repo to `$CODE_DIR/NAME`, push empty commit `chore: kick ci` | CI already deployed, or a kick is running/succeeded |
|
||||||
| 7 | wait for CI's `gitops-bump` to replace `newTag: latest` (fails fast if the CI run fails) | tag already bumped |
|
| 7 | wait for CI's `gitops-bump` to replace `newTag: latest` (fails fast if the CI run fails) | tag already bumped |
|
||||||
| 8 | write `apps/NAME.yaml`, commit, push, refresh ArgoCD `root` | file exists |
|
| 8 | write `apps/NAME.yaml`, commit, push, refresh ArgoCD `root` | file exists |
|
||||||
| 9 | `--wait`: ArgoCD app `Synced/Healthy`, then `/readyz` (backend) or `/healthz` + `/api/readyz` (frontend) → 200 | no `--wait` |
|
| 9 | `--wait`: ArgoCD app `Synced/Healthy`, then `https://NAME.$INGRESS_DOMAIN/readyz` (backend) or `/healthz` + `/api/readyz` (frontend) → 200 | no `--wait` |
|
||||||
|
|
||||||
Then it prints the service, ArgoCD, Kibana (pre-filtered on `service:"NAME"`)
|
Then it prints the service, ArgoCD, Kibana (pre-filtered on `service:"NAME"`)
|
||||||
and Unleash URLs, and the elapsed time.
|
and Unleash URLs, and the elapsed time.
|
||||||
|
|
@ -91,6 +91,11 @@ call (secret values redacted), git push and kubectl change instead of doing it.
|
||||||
registry push token (same user).
|
registry push token (same user).
|
||||||
- Git pushes use the admin token through an inline credential helper; it is
|
- Git pushes use the admin token through an inline credential helper; it is
|
||||||
never written into a remote URL or `argv`.
|
never written into a remote URL or `argv`.
|
||||||
- Platform UIs: ArgoCD, Kibana and Unleash at `argocd.` / `kibana.` /
|
- Platform UIs: ArgoCD, Kibana and Unleash at `https://argocd.` / `kibana.` /
|
||||||
`unleash.192.168.1.83.nip.io`. Credentials and conventions: homelab
|
`unleash.lab.holtlabs.xyz` (`INGRESS_DOMAIN`). Credentials and conventions:
|
||||||
`PLATFORM.md`.
|
homelab `PLATFORM.md`.
|
||||||
|
- `INGRESS_DOMAIN` (`lab.holtlabs.xyz`) fills `__DOMAIN__` in the gitops
|
||||||
|
templates, so services get `https://NAME.$INGRESS_DOMAIN/`. The wildcard
|
||||||
|
DNS record and the wildcard certificate are cluster-level (Plan 11); a new
|
||||||
|
service creates no DNS record and requests no certificate. Health checks
|
||||||
|
pin the host to `INGRESS_IP` with `curl --resolve` but still verify TLS.
|
||||||
|
|
|
||||||
|
|
@ -171,13 +171,13 @@ render_manifests() {
|
||||||
for f in "${extra[@]}"; do add+=" - $f\n"; done
|
for f in "${extra[@]}"; do add+=" - $f\n"; done
|
||||||
sed -i "s|^ # Added by the render recipe.*$|${add%\\n}|" "$out/kustomization.yaml"
|
sed -i "s|^ # Added by the render recipe.*$|${add%\\n}|" "$out/kustomization.yaml"
|
||||||
sed -i '/^$/d' "$out/kustomization.yaml"
|
sed -i '/^$/d' "$out/kustomization.yaml"
|
||||||
sed -i "s/__APP__/$NAME/g" "$out"/*.yaml
|
sed -i "s/__APP__/$NAME/g; s/__DOMAIN__/$INGRESS_DOMAIN/g" "$out"/*.yaml
|
||||||
else
|
else
|
||||||
if [[ -z $API_APP ]]; then
|
if [[ -z $API_APP ]]; then
|
||||||
rm "$out/ingress-api.yaml" "$out/middleware.yaml"
|
rm "$out/ingress-api.yaml" "$out/middleware.yaml"
|
||||||
sed -i '/ingress-api.yaml$/d; /middleware.yaml$/d; /# \/api -> backend/d' "$out/kustomization.yaml"
|
sed -i '/ingress-api.yaml$/d; /middleware.yaml$/d; /# \/api -> backend/d' "$out/kustomization.yaml"
|
||||||
fi
|
fi
|
||||||
sed -i "s/__APP__/$NAME/g; s/__API__/$API_APP/g" "$out"/*.yaml
|
sed -i "s/__APP__/$NAME/g; s/__API__/$API_APP/g; s/__DOMAIN__/$INGRESS_DOMAIN/g" "$out"/*.yaml
|
||||||
fi
|
fi
|
||||||
! grep -rn '__[A-Z]*__' "$out" || die "unrendered placeholder left in manifests"
|
! grep -rn '__[A-Z]*__' "$out" || die "unrendered placeholder left in manifests"
|
||||||
kustomize_build "$out" >/dev/null || die "kustomize build of rendered manifests failed"
|
kustomize_build "$out" >/dev/null || die "kustomize build of rendered manifests failed"
|
||||||
|
|
@ -291,14 +291,14 @@ if ((WAIT)) && ! is_dry; then
|
||||||
local p
|
local p
|
||||||
for p in "$@"; do
|
for p in "$@"; do
|
||||||
[[ $(curl -s -o /dev/null -w '%{http_code}' --max-time 5 \
|
[[ $(curl -s -o /dev/null -w '%{http_code}' --max-time 5 \
|
||||||
--resolve "$HOST:80:$INGRESS_IP" "http://$HOST$p") == 200 ]] || return 1
|
--resolve "$HOST:443:$INGRESS_IP" "https://$HOST$p") == 200 ]] || return 1
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
paths=("$HEALTH_PATH")
|
paths=("$HEALTH_PATH")
|
||||||
[[ -n $API_APP ]] && paths+=(/api/readyz)
|
[[ -n $API_APP ]] && paths+=(/api/readyz)
|
||||||
wait_until 180 5 "http://$HOST${paths[*]} -> 200" http_ok "${paths[@]}"
|
wait_until 180 5 "https://$HOST${paths[*]} -> 200" http_ok "${paths[@]}"
|
||||||
for p in "${paths[@]}"; do
|
for p in "${paths[@]}"; do
|
||||||
printf ' GET %s -> %s\n' "$p" "$(curl -s --max-time 5 --resolve "$HOST:80:$INGRESS_IP" "http://$HOST$p")" >&2
|
printf ' GET %s -> %s\n' "$p" "$(curl -s --max-time 5 --resolve "$HOST:443:$INGRESS_IP" "https://$HOST$p")" >&2
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -223,11 +223,11 @@ print_urls() {
|
||||||
kql=$(jq -rn --arg s "$name" '"service:\"\($s)\"" | @uri')
|
kql=$(jq -rn --arg s "$name" '"service:\"\($s)\"" | @uri')
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
|
||||||
service : http://$host/
|
service : https://$host/
|
||||||
health : http://$host/$([[ $kind == backend ]] && echo readyz || echo healthz)
|
health : https://$host/$([[ $kind == backend ]] && echo readyz || echo healthz)
|
||||||
repo : $FORGEJO_URL/$FORGEJO_OWNER/$name
|
repo : $FORGEJO_URL/$FORGEJO_OWNER/$name
|
||||||
argocd : http://argocd.$INGRESS_DOMAIN/applications/argocd/$name
|
argocd : https://argocd.$INGRESS_DOMAIN/applications/argocd/$name
|
||||||
kibana : http://kibana.$INGRESS_DOMAIN/app/discover#/?_g=(time:(from:now-1h,to:now))&_a=(query:(language:kuery,query:'$kql'))
|
kibana : https://kibana.$INGRESS_DOMAIN/app/discover#/?_g=(time:(from:now-1h,to:now))&_a=(query:(language:kuery,query:'$kql'))
|
||||||
unleash : http://unleash.$INGRESS_DOMAIN/projects/default
|
unleash : https://unleash.$INGRESS_DOMAIN/projects/default
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,5 +12,5 @@ GITOPS_DIR=$HOME/Code/forgejo.local/nholtware/gitops # clean clone of
|
||||||
CODE_DIR=$HOME/Code/forgejo.local/nholtware # new service repos are cloned here
|
CODE_DIR=$HOME/Code/forgejo.local/nholtware # new service repos are cloned here
|
||||||
KUBECONFIG=$HOME/.kube/homelab.yaml
|
KUBECONFIG=$HOME/.kube/homelab.yaml
|
||||||
|
|
||||||
INGRESS_DOMAIN=192.168.1.83.nip.io # services at <name>.$INGRESS_DOMAIN
|
INGRESS_DOMAIN=lab.holtlabs.xyz # services at https://<name>.$INGRESS_DOMAIN (renders __DOMAIN__)
|
||||||
INGRESS_IP=192.168.1.83 # health checks use curl --resolve, no DNS needed
|
INGRESS_IP=192.168.1.83 # health checks use curl --resolve, no DNS needed (TLS still verified)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue