Ticket: pal-e-services — var.services entry + Keycloak client
Ticket: pal-e-services — var.services entry + Keycloak client
Story:
Architecture:
Labels:
Blocks: Woodpecker pipeline (needs Harbor project + CI robot), k8s overlay (needs namespace + Keycloak client secret)
Blocked by: Streamlit spike ticket
story-westside-ops-spreadsheet-accessArchitecture:
arch-deployment-westside-ops (pal-e-services as the tenancy layer)Labels:
story:spreadsheet-access,arch:services-tf,type:infra,track:devops,scope:plannedBlocks: Woodpecker pipeline (needs Harbor project + CI robot), k8s overlay (needs namespace + Keycloak client secret)
Blocked by: Streamlit spike ticket
Purpose
Register westside-ops as a service in pal-e-services so terraform provisions: Harbor project, CI robot, pull robot, namespace, harbor-creds image pull secret, ArgoCD application pointing at the westside-ops repo's
k8s/ directory, and a Tailscale ingress (explicitly NOT a funnel). Also register a new Keycloak client westside-ops in the existing westside realm.Scope
- Edit
~/pal-e-services/terraform/k3s.tfvars(the GPG-decrypted or local copy — do not commit) - Add the service entry and Keycloak client below
- Run
tofu plan -var-file=k3s.tfvars -lock=falseand review for expected resources (Harbor project, 2 robots, namespace, secret, ArgoCD app, ingress, Keycloak client) - Run
tofu apply -var-file=k3s.tfvars -lock=falseperfeedback_tofu_lock_false - Capture the CI robot credentials via
tofu outputand hand them to the Woodpecker pipeline ticket - Capture the Keycloak client secret from the Keycloak admin console and hand it to the k8s overlay ticket (it will be SOPS-encrypted into
secrets.enc.yaml) - Add Marcus's Keycloak account to the new
westside-ops-userrole within the westside realm (manual step in Keycloak admin UI, or viamcp__pal-e-docsif Keycloak MCP exists)
Exact tfvars additions
Append to the
services map in k3s.tfvars:
Append to the
keycloak_clients map in k3s.tfvars:
Also needed: add
westside-ops-user to the roles list of the existing westside realm definition in tfvars (if realms are declared there), or create the role manually in the Keycloak admin console if realms are managed outside tfvars.Important: verify the funnel=false code path
Reading
pal-e-services/terraform/services.tf: the current funnel resource is conditional on each.value.funnel being true and applies the tailscale.com/funnel: "true" annotation. For westside-ops, we need tailscale.com/expose: "true" instead — the private variant.The current terraform module does not create an expose-style ingress when
funnel=false — it just skips the ingress entirely. That means one of:- Option A: westside-ops manages its own ingress inside
~/westside-ops/k8s/ingress.yamlwith thetailscale.com/exposeannotation (the k8s overlay ticket handles this).funnel=falsein tfvars just means "tofu doesn't create any ingress — the overlay does." This is the recommended path because it's consistent with howwestside-landing/westsidekingsandqueensalready manages its own ingress via its overlay. - Option B: Extend pal-e-services's services.tf to support a third mode (
expose). More invasive, defer as a separate ticket.
Go with Option A. The ingress resource lives in
~/westside-ops/k8s/ingress.yaml, declared in the k8s overlay ticket.Acceptance Criteria
- [ ]
tofu plan -var-file=k3s.tfvars -lock=falseshows expected new resources:harbor_project.service["westside-ops"],harbor_robot_account.service_ci["westside-ops"],harbor_robot_account.service_pull["westside-ops"],kubernetes_namespace_v1.service["westside-ops"],kubernetes_secret_v1.harbor_creds["westside-ops"],argocd_application.service["westside-ops"], and the new Keycloak client - [ ] Plan does NOT show
kubernetes_ingress_v1.service_funnel["westside-ops"](funnel=false so the funnel resource is skipped) - [ ]
tofu apply -var-file=k3s.tfvars -lock=falsesucceeds - [ ] CI robot credentials captured from
tofu output ci_robot_usernamesandtofu output -json ci_robot_passwords; handed to Woodpecker pipeline ticket - [ ] Keycloak client secret captured from the admin console; encrypted into the k8s overlay's
secrets.enc.yaml - [ ] Marcus's Keycloak account has the
westside-ops-userrole assigned - [ ] Namespace
westside-opsexists in the cluster (kubectl get ns westside-ops) - [ ] Harbor project
westside-opsexists (verified in Harbor UI) - [ ] ArgoCD application
westside-opsexists but isOutOfSync(expected — the k8s overlay ticket hasn't committed manifests yet)
Files touched
~/pal-e-services/terraform/k3s.tfvars(local, not committed)- Cluster state (Harbor project, 2 robots, namespace, harbor-creds secret, ArgoCD Application, Keycloak client, Keycloak role, Keycloak user→role assignment)
Rollback
Remove the
westside-ops entry from services and keycloak_clients in tfvars. Run tofu apply -var-file=k3s.tfvars -lock=false. Terraform destroys everything it created. ArgoCD pruning may race with namespace deletion — transient errors are harmless per SERVICE_ONBOARDING.md.Out of scope
- The
westside_ops_readerPostgres role — separate ticket - Application manifests (Deployment, Service, Ingress, Secrets) — k8s overlay ticket
- The Streamlit image build — Woodpecker pipeline ticket
Dependencies
Blocked by: Streamlit spike ticket. Can proceed in parallel with repo bootstrap and Postgres role.