Matches the chart-side replacement in devops-infra-helm-charts. Three
Applications now where there was one, since victoria-metrics-single
bundles no scraper or exporter the way the Prometheus chart did.
Sync order matters here specifically: victoria-metrics-single needs to
exist before vmagent's remote_write target resolves, though ArgoCD sync
failures are naturally retried so this only affects how quickly it
converges, not whether it does.
Verified with `helm template` against generic-argo-apps-chart and this
values file: 11 Applications render, the three new ones present and
correctly formed, nothing left pointing at the removed prometheus
chartDir.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wajog7nELA3i8JWTjxYGHF
Points at the chart and values just added to devops-infra-helm-charts.
nameOverride pinned to "prometheus" so the Helm release name matches
what the chart's server Service naming depends on
("<release-name>-server") — see that repo's commit for the full
reasoning, since this file is the one place that decision has to be
made correctly for toolshed's already-seeded PROMETHEUS_URL to resolve.
Needs the usual two syncs to actually deploy: this values file only
takes effect once incubator-infra-k8s-admin-prd-ase1 is synced (which
creates/updates the child "prometheus" Application object), and that
child Application then needs its own sync to actually create anything
in the cluster.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wajog7nELA3i8JWTjxYGHF
Environment variables are delivered through a Secret so values never appear
in the pod spec, but the ClusterRole was never given the resource — so every
deploy with configuration failed on a forbidden error, minutes after the
change looked fine.
Granted without list or watch. Kubernetes RBAC cannot scope a ClusterRole to
a namespace pattern, so this necessarily covers every namespace; withholding
list at least stops deployer enumerating the cluster's secrets, leaving only
access by a name it already knows. That narrows the blast radius rather than
removing it, and is called out in the manifest.
The proper fix, once there are tenants who are not the operator, is a
RoleBinding created per app namespace. That requires deployer to be able to
create RoleBindings, which is its own escalation path and wants deciding
deliberately rather than being slipped in here.
Scoped to the resource kinds toolshed creates for an app — not
cluster-admin, not a wildcard. This is the one credential in the system
whose compromise means the cluster, so what it can do should fit on one
screen.
Here rather than in toolshed's chart because these are cluster-scoped and
that Application runs in the webapp project, which permits only Namespace.
Widening webapp would have given every demo app in it the ability to create
cluster-wide RBAC.
A dedicated Jenkins user with an API token, not the admin account. Needs
Job/Create as well as Build and Read, because builder creates an app's job
on first deploy — which is what guarantees the SCM polling trigger exists
and so that a webhook can ever find it (issue #30).
Only api gets the private half. The gateway is given the public half in
plain Helm values, and that asymmetry is the point: the gateway
terminates traffic for every deployed app, so holding only a verification
key means compromising it cannot forge a session for anyone.
The two halves must be installed together — a private key here that does
not match the public key in the gateway's values means every session api
issues is rejected and every app redirects to login forever.
One Vault path (secret/toolshed/postgres) into two namespaces: the server
needs the credential to initialise, api needs it to connect. Kept in one
file because it is one credential with two consumers — split, they drift,
and drift surfaces as an authentication error that looks nothing like a
config mistake.
The api-side Secret also carries a composed libpq URL, so host, port and
database name live in one place instead of across several environment
variables that can disagree.
Postgres gets its own namespace rather than living inside toolshed, so it
is addressed over cluster DNS like any other platform component and
outlives whatever consumes it.
No longer needed now that anonymous pull works — pairs with
devops-helm-charts#efc2c4f dropping the corresponding pullSecret
reference from demo-go-app's values. app-of-secretstores has automated
prune, so this deletion applies on its own on next sync.
Both needed for the registry hostname switch to
harbor.192.168.1.7.nip.io (devops-lib#3ffa2d8):
- harbor-robot-dockerconfig's auths key was hardcoded to
harbor-core.harbor.svc.cluster.local — docker matches stored
credentials by exact registry hostname, so this had to move with
the image reference or push would go back to unauthorized.
- New demo-go-app-image-pull-secret, in the demo-go-app namespace
(imagePullSecrets must be same-namespace as the pod), for the
Deployment's own pull — separate from harbor-robot-dockerconfig,
which only ever lived in the jenkins namespace for the build pod's
push. Same underlying robot account/Vault path.
extra-manifests/priorityclass-high-priority.yaml: cluster-side
PriorityClass backing the app chart's hardcoded priorityClassName.
secretstores/argocd-jenkins-ci-token.yaml: ExternalSecret for the
scoped ArgoCD account devops-lib's syncArgoApp stage authenticates
with.
secretstores/harbor-robot-dockerconfig.yaml: ExternalSecret building a
dockerconfigjson from the Harbor robot account for image pulls.