Rebrand: Sentry -> Cairn OBS

Full rebrand across cosmetic branding, code identifiers, and
infrastructure/data-plane naming, using the supplied Cairn OBS logo
package. Cosmetic: favicon/logo swap (also closes a stale license-audit
finding -- the old favicon was SvelteKit's unreplaced scaffold logo),
new centered welcome landing page, larger/legible sidebar logo, page
titles, CLAUDE.md/README/docs prose.

Code identifiers: Go module path github.com/sentry/sentry ->
github.com/cairnobs/cairnobs across all 13 modules and ~91 files (protoc
regenerated); Rust crates sentry-agent/sentry-parser/sentry-search ->
cairnobs-*; CLI sentryctl -> cairnobsctl; Terraform provider fully
renamed (sentry_dashboard etc. -> cairnobs_dashboard, provider type,
env vars); every session/auth cookie name; agent config paths and
Windows service identity.

Deliberately preserved: the gRPC wire protocol's protobuf packages
(sentry.logs.v1, sentry.agent.v1) and their Go import directory
(proto/sentry/...) -- renaming the wire-level package would break every
currently-deployed agent binary (confirmed two real hosts, including
mail.inbuxa.com, are actively streaming through this exact contract)
until rebuilt and redeployed in lockstep with an ingest cutover. Only
the Go module path wrapping the generated code changes.

Infrastructure: every docker-compose container name (root and three
component-level compose files); the Helm chart (directory, Chart.yaml,
named-template helpers, all templates, values.yaml image repos);
Kubernetes Operator (CRD group sentry.io -> cairnobs.io, both CRD YAML
files, Go identifiers, RBAC markers); the coupled enterprise/tenantcrd
package. Caught and fixed real path-coupling bugs along the way: the
Helm chart's search/ingest volume mounts and the dev-only-credential
detection constant vs. docker-compose.yml's literal values had to move
together or a security warning would have silently stopped firing.

Data plane: Postgres database sentry_metadata -> cairnobs_metadata and
role sentry -> cairnobs; ClickHouse database sentry -> cairnobs; Kafka
topic sentry.logs.raw -> cairnobs.logs.raw and its consumer groups.
Source-level defaults, docker-compose.yml, and every migrate.sh/
provision script default updated together; already-applied migration
files left untouched per this repo's immutable-migration convention.

Verified at every layer: all 13 Go modules build/vet/test clean, both
Rust workspaces (agent, search) build/clippy/test clean, npm run check/
build clean, docker compose config validates on all four compose files.
Live-verified against a real docker stack multiple times through this
work, including a final fresh-volume run confirming the actual renamed
Postgres database/role, ClickHouse database, and Kafka topic all work
end to end with a real login and query, zero console errors.
This commit is contained in:
2026-08-21 20:53:32 -07:00
parent 9e21ea17bb
commit 13cf9a30cb
291 changed files with 1565 additions and 1441 deletions
+9 -9
View File
@@ -1,14 +1,14 @@
# deploy
Kubernetes deployment for Sentry, added in Phase 4 (`/deploy` was
Kubernetes deployment for Cairn OBS, added in Phase 4 (`/deploy` was
deliberately stubbed through Phase 3 -- see `/CLAUDE.md`'s Phase 3
non-goals). Two pieces:
- `operator/` -- a small Go controller-runtime Operator managing one CRD
(`Tenant`). See `operator/README.md`.
- `helm/sentry/` -- a Helm chart covering every `docker-compose.yml`
- `helm/cairnobs/` -- a Helm chart covering every `docker-compose.yml`
service, plus the operator and `Tenant` CRs when
`enterprise.enabled=true`. See `helm/sentry/README.md`.
`enterprise.enabled=true`. See `helm/cairnobs/README.md`.
## What "multi-tenant-aware" means here, precisely
@@ -29,7 +29,7 @@ add:
(`values.tenants`) alongside the rest of the stack, and swaps `api`'s
Deployment for `enterprise-api`'s whenever `enterprise.enabled` is
true, so which query binary actually serves traffic is no longer a
separately-forgettable decision (see `helm/sentry/README.md`'s "`api`
separately-forgettable decision (see `helm/cairnobs/README.md`'s "`api`
vs `enterprise-api`" section).
**Now unified, in a deliberately lightweight way**: `enterprise-api
@@ -65,7 +65,7 @@ gap, which was two *disconnected* sources of truth, not two actors).
`kubectl`/`helm` were installed without root (static binaries into
`~/.local/bin`), a real local cluster was created, every image this
chart references was built and loaded into it, and the full two-tenant
walkthrough (`helm/sentry/README.md`) was run end to end -- both tenants
walkthrough (`helm/cairnobs/README.md`) was run end to end -- both tenants
reached `Tenant.status.phase: Active` with real generated ClickHouse
credentials in their Secrets. See `/docs/phase-4-runbook.md` §7 for the
exact commands and the two real chart bugs this run found and fixed
@@ -88,16 +88,16 @@ true, kept as additional evidence, not superseded by the above):
`k8s.io/client-go`'s fake dynamic and typed clientsets -- real client
library, fake transport, same shape as `enterprise/internal/
searchclient`'s in-process gRPC tests. What this doesn't prove: that
`sentry.io/v1alpha1.Tenant`'s real CRD schema (a real apiserver's
`cairnobs.io/v1alpha1.Tenant`'s real CRD schema (a real apiserver's
OpenAPI validation) accepts exactly what this package writes -- the
`helm template`/kubeconform check below covers the schema shape, not
a live write against it.
- `deploy/operator/config/crd/sentry.io_tenants.yaml`: parsed with
- `deploy/operator/config/crd/cairnobs.io_tenants.yaml`: parsed with
`sigs.k8s.io/yaml` + strict-unmarshaled into the real
`k8s.io/apiextensions-apiserver` `CustomResourceDefinition` Go type --
catches YAML syntax errors and structural mistakes, not a live-cluster
admission check.
- `deploy/helm/sentry`: `helm lint` passes; `helm template` renders
- `deploy/helm/cairnobs`: `helm lint` passes; `helm template` renders
cleanly under both default values and a `enterprise.enabled: true` +
two-tenant override; the rendered output was checked with `kubeconform
-strict` against the real Kubernetes 1.31 OpenAPI schema for every
@@ -107,7 +107,7 @@ true, kept as additional evidence, not superseded by the above):
together on a live cluster (Job/StatefulSet startup ordering, PVC
provisioning, actual pod scheduling). Specifically confirmed by
parsing the rendered YAML (not just eyeballing it): exactly one
`Deployment`/`Service` named `sentry-api` renders in each mode, with
`Deployment`/`Service` named `cairnobs-api` renders in each mode, with
the `enterprise.enabled: true` render using the `enterprise-api` image
and the default render using plain `api`'s. Also confirmed for the
`tenantOperator.enabled: true` case: `enterprise-api` gets its own
@@ -1,7 +1,7 @@
apiVersion: v2
name: sentry
name: cairnobs
description: >-
Sentry: Kubernetes-native distributed log aggregation. Phase 4 adds
Cairn OBS: Kubernetes-native distributed log aggregation. Phase 4 adds
multi-tenant-aware deployment (per-tenant ClickHouse credential Secrets
via the tenant-operator, optional enterprise-auth) on top of the same
single-cluster topology Phases 0-3 ran under docker-compose -- see
@@ -1,4 +1,4 @@
# deploy/helm/sentry
# deploy/helm/cairnobs
A Helm chart covering every `docker-compose.yml` service (Redpanda,
ClickHouse, Postgres, ingest, search, alerting, web) plus, when
@@ -49,7 +49,7 @@ be reachable). This chart approximates that more loosely:
up yet.
- App Deployments get an `initContainer` that busy-waits for their
dependency's **TCP port**, not for a specific Job's completion (see
`templates/_helpers.tpl`'s `sentry.waitForTCP`) -- this covers "is
`templates/_helpers.tpl`'s `cairnobs.waitForTCP`) -- this covers "is
ClickHouse/Postgres/Redpanda up" but not "has the migration Job
actually finished."
- The gap that leaves (a pod starts before its migration has completed)
@@ -68,7 +68,7 @@ be reachable). This chart approximates that more loosely:
# here -- that's a helm template-only flag (install always installs
# crds/ by default); confirmed the hard way running this against a real
# kind cluster, see /docs/phase-4-runbook.md §7.
helm install sentry . \
helm install cairnobs . \
--set enterprise.enabled=true \
--set tenantOperator.enabled=true \
--set 'tenants[0].name=acme' --set 'tenants[0].displayName=Acme Corp' \
@@ -79,12 +79,12 @@ kubectl get tenants
# declarative request; nothing has actually provisioned ClickHouse for
# either yet (see below).
kubectl exec -it deploy/sentry-api -- /enterprise-api -provision-tenant=acme -display-name="Acme Corp"
kubectl exec -it deploy/sentry-api -- /enterprise-api -provision-tenant=globex -display-name="Globex Corporation"
kubectl exec -it deploy/cairnobs-api -- /enterprise-api -provision-tenant=acme -display-name="Acme Corp"
kubectl exec -it deploy/cairnobs-api -- /enterprise-api -provision-tenant=globex -display-name="Globex Corporation"
kubectl get tenants
# expect: both Active now.
kubectl get secret sentry-tenant-acme-clickhouse sentry-tenant-globex-clickhouse
kubectl get secret cairnobs-tenant-acme-clickhouse cairnobs-tenant-globex-clickhouse
```
Before any of this: `ingest` needs a real mTLS cert Secret
@@ -135,7 +135,7 @@ actually reachable from a browser before pointing real users at it.
```sh
helm lint .
helm template sentry . --include-crds > /tmp/rendered.yaml
helm template cairnobs . --include-crds > /tmp/rendered.yaml
```
See `/deploy/README.md`'s verification section for what was checked
@@ -7,9 +7,9 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: tenants.sentry.io
name: tenants.cairnobs.io
spec:
group: sentry.io
group: cairnobs.io
names:
kind: Tenant
listKind: TenantList
@@ -1,31 +1,31 @@
{{/*
Standard labels applied to every resource this chart renders.
*/}}
{{- define "sentry.labels" -}}
app.kubernetes.io/part-of: sentry
{{- define "cairnobs.labels" -}}
app.kubernetes.io/part-of: cairnobs
app.kubernetes.io/managed-by: {{ .Release.Service }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
{{- end -}}
{{/*
Per-component selector labels -- usage:
{{ include "sentry.selectorLabels" (list $ "api") }}
{{ include "cairnobs.selectorLabels" (list $ "api") }}
A plain string arg (the old shape this started with) can't reach
$.Release from inside the defined template -- `include`'s argument
becomes the template's entire root context, so a bare "api" string
leaves no way to get back to the chart root. A two-element list carries
both.
*/}}
{{- define "sentry.selectorLabels" -}}
{{- define "cairnobs.selectorLabels" -}}
{{- $root := index . 0 -}}
{{- $name := index . 1 -}}
app.kubernetes.io/name: sentry-{{ $name }}
app.kubernetes.io/name: cairnobs-{{ $name }}
app.kubernetes.io/instance: {{ $root.Release.Name }}
{{- end -}}
{{/*
An initContainer that busy-waits for a TCP host:port to accept
connections -- usage: {{ include "sentry.waitForTCP" (list "name-suffix" "host" "port") }}
connections -- usage: {{ include "cairnobs.waitForTCP" (list "name-suffix" "host" "port") }}
This approximates docker-compose.yml's `depends_on: condition:
service_healthy` (waits for the dependency's process to be reachable),
@@ -34,7 +34,7 @@ one-shot Job, like clickhouse-migrate, to have actually finished). That
second guarantee doesn't have a lightweight equivalent here without
giving every app pod's ServiceAccount RBAC to read Job status, which is
a lot of privilege for a startup-ordering nicety -- see
deploy/helm/sentry/README.md's "Startup ordering" section. The gap it
deploy/helm/cairnobs/README.md's "Startup ordering" section. The gap it
leaves (a pod starts before its migration Job has finished) is covered
by the app's own crash-and-restart-on-connect/schema failure: every Go
service here already os.Exit(1)s on a failed Postgres/ClickHouse ping at
@@ -42,7 +42,7 @@ startup (see e.g. api/cmd/api/main.go), so Kubernetes' restart policy
naturally retries until the schema is ready. Documented as a real,
accepted tradeoff, not implied to be a hard ordering guarantee.
*/}}
{{- define "sentry.waitForTCP" -}}
{{- define "cairnobs.waitForTCP" -}}
{{- $name := index . 0 -}}
{{- $host := index . 1 -}}
{{- $port := index . 2 -}}
@@ -3,22 +3,22 @@ kind: Deployment
metadata:
name: {{ .Release.Name }}-alerting
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "alerting") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "alerting") | nindent 4 }}
spec:
# See values.yaml's comment: replicas is not a real knob here yet.
replicas: {{ .Values.alerting.replicas }}
selector:
matchLabels:
{{- include "sentry.selectorLabels" (list $ "alerting") | nindent 6 }}
{{- include "cairnobs.selectorLabels" (list $ "alerting") | nindent 6 }}
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "alerting") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "alerting") | nindent 8 }}
spec:
initContainers:
{{- include "sentry.waitForTCP" (list "postgres" (printf "%s-postgres" .Release.Name) "5432") | nindent 8 }}
{{- include "sentry.waitForTCP" (list "api" (printf "%s-api" .Release.Name) "8080") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "postgres" (printf "%s-postgres" .Release.Name) "5432") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "api" (printf "%s-api" .Release.Name) "8080") | nindent 8 }}
containers:
- name: alerting
image: "{{ .Values.alerting.image.repository }}:{{ .Values.alerting.image.tag }}"
@@ -71,11 +71,11 @@ kind: Service
metadata:
name: {{ .Release.Name }}-alerting
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "alerting") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "alerting") | nindent 4 }}
spec:
selector:
{{- include "sentry.selectorLabels" (list $ "alerting") | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "alerting") | nindent 4 }}
ports:
- name: http
port: 8081
@@ -13,22 +13,22 @@ kind: Deployment
metadata:
name: {{ .Release.Name }}-api
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "api") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "api") | nindent 4 }}
spec:
replicas: {{ .Values.api.replicas }}
selector:
matchLabels:
{{- include "sentry.selectorLabels" (list $ "api") | nindent 6 }}
{{- include "cairnobs.selectorLabels" (list $ "api") | nindent 6 }}
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "api") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "api") | nindent 8 }}
spec:
initContainers:
{{- include "sentry.waitForTCP" (list "clickhouse" (printf "%s-clickhouse" .Release.Name) "9000") | nindent 8 }}
{{- include "sentry.waitForTCP" (list "postgres" (printf "%s-postgres" .Release.Name) "5432") | nindent 8 }}
{{- include "sentry.waitForTCP" (list "search" (printf "%s-search" .Release.Name) "50052") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "clickhouse" (printf "%s-clickhouse" .Release.Name) "9000") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "postgres" (printf "%s-postgres" .Release.Name) "5432") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "search" (printf "%s-search" .Release.Name) "50052") | nindent 8 }}
containers:
- name: api
image: "{{ .Values.api.image.repository }}:{{ .Values.api.image.tag }}"
@@ -75,11 +75,11 @@ kind: Service
metadata:
name: {{ .Release.Name }}-api
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "api") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "api") | nindent 4 }}
spec:
selector:
{{- include "sentry.selectorLabels" (list $ "api") | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "api") | nindent 4 }}
ports:
- name: http
port: 8080
@@ -3,18 +3,18 @@ kind: StatefulSet
metadata:
name: {{ .Release.Name }}-clickhouse
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "clickhouse") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "clickhouse") | nindent 4 }}
spec:
serviceName: {{ .Release.Name }}-clickhouse
replicas: 1
selector:
matchLabels:
{{- include "sentry.selectorLabels" (list $ "clickhouse") | nindent 6 }}
{{- include "cairnobs.selectorLabels" (list $ "clickhouse") | nindent 6 }}
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "clickhouse") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "clickhouse") | nindent 8 }}
spec:
containers:
- name: clickhouse
@@ -69,12 +69,12 @@ kind: Service
metadata:
name: {{ .Release.Name }}-clickhouse
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "clickhouse") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "clickhouse") | nindent 4 }}
spec:
clusterIP: None
selector:
{{- include "sentry.selectorLabels" (list $ "clickhouse") | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "clickhouse") | nindent 4 }}
ports:
- name: http
port: 8123
@@ -84,19 +84,19 @@ spec:
# One-shot: applies /storage/migrations/*.sql -- same image
# storage/Dockerfile builds for docker-compose.yml's clickhouse-migrate
# service. Plain Job, not a Helm hook -- see redpanda.yaml's comment and
# deploy/helm/sentry/README.md's "Startup ordering" section.
# deploy/helm/cairnobs/README.md's "Startup ordering" section.
apiVersion: batch/v1
kind: Job
metadata:
name: {{ .Release.Name }}-clickhouse-migrate
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
spec:
backoffLimit: 6
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "clickhouse-migrate") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "clickhouse-migrate") | nindent 8 }}
spec:
restartPolicy: OnFailure
containers:
@@ -25,19 +25,19 @@ kind: ServiceAccount
metadata:
name: {{ .Release.Name }}-enterprise-api
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ .Release.Name }}-enterprise-api
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
rules:
- apiGroups: ["sentry.io"]
- apiGroups: ["cairnobs.io"]
resources: ["tenants"]
verbs: ["get", "list", "create"]
- apiGroups: ["sentry.io"]
- apiGroups: ["cairnobs.io"]
resources: ["tenants/status"]
verbs: ["get", "update", "patch"]
- apiGroups: [""]
@@ -49,7 +49,7 @@ kind: RoleBinding
metadata:
name: {{ .Release.Name }}-enterprise-api
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
@@ -65,27 +65,27 @@ kind: Deployment
metadata:
name: {{ .Release.Name }}-api
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "api") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "api") | nindent 4 }}
app.kubernetes.io/component: enterprise-api
spec:
replicas: {{ .Values.api.replicas }}
selector:
matchLabels:
{{- include "sentry.selectorLabels" (list $ "api") | nindent 6 }}
{{- include "cairnobs.selectorLabels" (list $ "api") | nindent 6 }}
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "api") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "api") | nindent 8 }}
spec:
{{- if .Values.tenantOperator.enabled }}
serviceAccountName: {{ .Release.Name }}-enterprise-api
{{- end }}
initContainers:
{{- include "sentry.waitForTCP" (list "clickhouse" (printf "%s-clickhouse" .Release.Name) "9000") | nindent 8 }}
{{- include "sentry.waitForTCP" (list "postgres" (printf "%s-postgres" .Release.Name) "5432") | nindent 8 }}
{{- include "sentry.waitForTCP" (list "search" (printf "%s-search" .Release.Name) "50052") | nindent 8 }}
{{- include "sentry.waitForTCP" (list "enterprise-auth" (printf "%s-enterprise-auth" .Release.Name) "8082") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "clickhouse" (printf "%s-clickhouse" .Release.Name) "9000") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "postgres" (printf "%s-postgres" .Release.Name) "5432") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "search" (printf "%s-search" .Release.Name) "50052") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "enterprise-auth" (printf "%s-enterprise-auth" .Release.Name) "8082") | nindent 8 }}
containers:
- name: enterprise-api
image: "{{ .Values.enterprise.apiImage.repository }}:{{ .Values.enterprise.apiImage.tag }}"
@@ -161,11 +161,11 @@ kind: Service
metadata:
name: {{ .Release.Name }}-api
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "api") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "api") | nindent 4 }}
spec:
selector:
{{- include "sentry.selectorLabels" (list $ "api") | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "api") | nindent 4 }}
ports:
- name: http
port: 8080
@@ -4,20 +4,20 @@ kind: Deployment
metadata:
name: {{ .Release.Name }}-enterprise-auth
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "enterprise-auth") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "enterprise-auth") | nindent 4 }}
spec:
replicas: {{ .Values.enterprise.replicas }}
selector:
matchLabels:
{{- include "sentry.selectorLabels" (list $ "enterprise-auth") | nindent 6 }}
{{- include "cairnobs.selectorLabels" (list $ "enterprise-auth") | nindent 6 }}
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "enterprise-auth") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "enterprise-auth") | nindent 8 }}
spec:
initContainers:
{{- include "sentry.waitForTCP" (list "postgres" (printf "%s-postgres" .Release.Name) "5432") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "postgres" (printf "%s-postgres" .Release.Name) "5432") | nindent 8 }}
containers:
- name: enterprise-auth
image: "{{ .Values.enterprise.image.repository }}:{{ .Values.enterprise.image.tag }}"
@@ -76,11 +76,11 @@ kind: Service
metadata:
name: {{ .Release.Name }}-enterprise-auth
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "enterprise-auth") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "enterprise-auth") | nindent 4 }}
spec:
selector:
{{- include "sentry.selectorLabels" (list $ "enterprise-auth") | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "enterprise-auth") | nindent 4 }}
ports:
- name: http
port: 8082
@@ -13,22 +13,22 @@ kind: Deployment
metadata:
name: {{ .Release.Name }}-enterprise-ingest
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "enterprise-ingest") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "enterprise-ingest") | nindent 4 }}
spec:
replicas: {{ .Values.ingest.replicas }}
selector:
matchLabels:
{{- include "sentry.selectorLabels" (list $ "enterprise-ingest") | nindent 6 }}
{{- include "cairnobs.selectorLabels" (list $ "enterprise-ingest") | nindent 6 }}
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "enterprise-ingest") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "enterprise-ingest") | nindent 8 }}
spec:
initContainers:
{{- include "sentry.waitForTCP" (list "redpanda" (printf "%s-redpanda" .Release.Name) "9092") | nindent 8 }}
{{- include "sentry.waitForTCP" (list "clickhouse" (printf "%s-clickhouse" .Release.Name) "9000") | nindent 8 }}
{{- include "sentry.waitForTCP" (list "postgres" (printf "%s-postgres" .Release.Name) "5432") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "redpanda" (printf "%s-redpanda" .Release.Name) "9092") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "clickhouse" (printf "%s-clickhouse" .Release.Name) "9000") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "postgres" (printf "%s-postgres" .Release.Name) "5432") | nindent 8 }}
containers:
- name: enterprise-ingest
image: "{{ .Values.enterprise.ingestImage.repository }}:{{ .Values.enterprise.ingestImage.tag }}"
@@ -3,21 +3,21 @@ kind: Deployment
metadata:
name: {{ .Release.Name }}-ingest
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "ingest") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "ingest") | nindent 4 }}
spec:
replicas: {{ .Values.ingest.replicas }}
selector:
matchLabels:
{{- include "sentry.selectorLabels" (list $ "ingest") | nindent 6 }}
{{- include "cairnobs.selectorLabels" (list $ "ingest") | nindent 6 }}
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "ingest") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "ingest") | nindent 8 }}
spec:
initContainers:
{{- include "sentry.waitForTCP" (list "redpanda" (printf "%s-redpanda" .Release.Name) "9092") | nindent 8 }}
{{- include "sentry.waitForTCP" (list "clickhouse" (printf "%s-clickhouse" .Release.Name) "9000") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "redpanda" (printf "%s-redpanda" .Release.Name) "9092") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "clickhouse" (printf "%s-clickhouse" .Release.Name) "9000") | nindent 8 }}
containers:
- name: ingest
image: "{{ .Values.ingest.image.repository }}:{{ .Values.ingest.image.tag }}"
@@ -68,7 +68,7 @@ spec:
{{- if .Values.ingest.tlsSecretName }}
volumeMounts:
- name: tls
mountPath: /etc/sentry-ingest
mountPath: /etc/cairnobs-ingest
readOnly: true
{{- end }}
resources:
@@ -85,11 +85,11 @@ kind: Service
metadata:
name: {{ .Release.Name }}-ingest
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "ingest") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "ingest") | nindent 4 }}
spec:
selector:
{{- include "sentry.selectorLabels" (list $ "ingest") | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "ingest") | nindent 4 }}
ports:
- name: grpc
port: 4317
@@ -3,18 +3,18 @@ kind: StatefulSet
metadata:
name: {{ .Release.Name }}-postgres
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "postgres") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "postgres") | nindent 4 }}
spec:
serviceName: {{ .Release.Name }}-postgres
replicas: 1
selector:
matchLabels:
{{- include "sentry.selectorLabels" (list $ "postgres") | nindent 6 }}
{{- include "cairnobs.selectorLabels" (list $ "postgres") | nindent 6 }}
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "postgres") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "postgres") | nindent 8 }}
spec:
containers:
- name: postgres
@@ -57,12 +57,12 @@ kind: Service
metadata:
name: {{ .Release.Name }}-postgres
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "postgres") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "postgres") | nindent 4 }}
spec:
clusterIP: None
selector:
{{- include "sentry.selectorLabels" (list $ "postgres") | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "postgres") | nindent 4 }}
ports:
- name: postgres
port: 5432
@@ -76,13 +76,13 @@ kind: Job
metadata:
name: {{ .Release.Name }}-metadata-migrate
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
spec:
backoffLimit: 6
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "metadata-migrate") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "metadata-migrate") | nindent 8 }}
spec:
restartPolicy: OnFailure
containers:
@@ -3,18 +3,18 @@ kind: StatefulSet
metadata:
name: {{ .Release.Name }}-redpanda
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "redpanda") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "redpanda") | nindent 4 }}
spec:
serviceName: {{ .Release.Name }}-redpanda
replicas: 1
selector:
matchLabels:
{{- include "sentry.selectorLabels" (list $ "redpanda") | nindent 6 }}
{{- include "cairnobs.selectorLabels" (list $ "redpanda") | nindent 6 }}
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "redpanda") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "redpanda") | nindent 8 }}
spec:
containers:
- name: redpanda
@@ -60,12 +60,12 @@ kind: Service
metadata:
name: {{ .Release.Name }}-redpanda
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "redpanda") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "redpanda") | nindent 4 }}
spec:
clusterIP: None
selector:
{{- include "sentry.selectorLabels" (list $ "redpanda") | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "redpanda") | nindent 4 }}
ports:
- name: kafka
port: 9092
@@ -75,7 +75,7 @@ spec:
# One-shot: creates the sentry.logs.raw topic. Same image
# transport/Dockerfile builds for docker-compose.yml's redpanda-provision
# service. Deliberately a plain Job, not a Helm hook -- see
# deploy/helm/sentry/README.md's "Startup ordering" section for why
# deploy/helm/cairnobs/README.md's "Startup ordering" section for why
# (StatefulSets-as-hooks breaks helm upgrade/uninstall's ownership
# tracking of stateful resources). backoffLimit gives it room to retry
# until redpanda's StatefulSet is actually ready; ingest/search's own
@@ -86,13 +86,13 @@ kind: Job
metadata:
name: {{ .Release.Name }}-redpanda-provision
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
spec:
backoffLimit: 6
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "redpanda-provision") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "redpanda-provision") | nindent 8 }}
spec:
restartPolicy: OnFailure
containers:
@@ -3,8 +3,8 @@ kind: Deployment
metadata:
name: {{ .Release.Name }}-search
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "search") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "search") | nindent 4 }}
spec:
# See values.yaml's comment: replicas is not a real knob here yet.
replicas: {{ .Values.search.replicas }}
@@ -12,14 +12,14 @@ spec:
type: Recreate # single PVC below (ReadWriteOnce) -- avoid two pods racing to mount it during a rollout
selector:
matchLabels:
{{- include "sentry.selectorLabels" (list $ "search") | nindent 6 }}
{{- include "cairnobs.selectorLabels" (list $ "search") | nindent 6 }}
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "search") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "search") | nindent 8 }}
spec:
initContainers:
{{- include "sentry.waitForTCP" (list "redpanda" (printf "%s-redpanda" .Release.Name) "9092") | nindent 8 }}
{{- include "cairnobs.waitForTCP" (list "redpanda" (printf "%s-redpanda" .Release.Name) "9092") | nindent 8 }}
containers:
- name: search
image: "{{ .Values.search.image.repository }}:{{ .Values.search.image.tag }}"
@@ -36,7 +36,7 @@ spec:
containerPort: 50052
volumeMounts:
- name: index-data
mountPath: /var/lib/sentry-search
mountPath: /var/lib/cairnobs-search
resources:
{{- toYaml .Values.search.resources | nindent 12 }}
volumes:
@@ -49,7 +49,7 @@ kind: PersistentVolumeClaim
metadata:
name: {{ .Release.Name }}-search-index
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
spec:
accessModes: ["ReadWriteOnce"]
resources:
@@ -61,11 +61,11 @@ kind: Service
metadata:
name: {{ .Release.Name }}-search
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "search") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "search") | nindent 4 }}
spec:
selector:
{{- include "sentry.selectorLabels" (list $ "search") | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "search") | nindent 4 }}
ports:
- name: grpc
port: 50052
@@ -1,6 +1,6 @@
{{/*
Shared control-plane secrets -- the cluster-wide passwords
docker-compose.yml hardcodes as "sentry-dev-only"/etc (see its
docker-compose.yml hardcodes as "cairnobs-dev-only"/etc (see its
clickhouse/metadata-postgres/metadata-migrate comments) become real
generated-or-supplied Secrets here. Each follows the same pattern: a
values override wins if set, otherwise a value is generated once and
@@ -13,7 +13,7 @@ reconcileSecret). `lookup` returns nothing under `helm template`
(no live cluster) -- expected; see deploy/README.md's verification
section for what that means for this file specifically.
*/}}
{{- define "sentry.stableSecretValue" -}}
{{- define "cairnobs.stableSecretValue" -}}
{{- $ns := index . 0 -}}
{{- $name := index . 1 -}}
{{- $key := index . 2 -}}
@@ -33,7 +33,7 @@ kind: Secret
metadata:
name: {{ .Release.Name }}-clickhouse
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
type: Opaque
stringData:
# The official clickhouse-server image locks down *network* access
@@ -42,22 +42,22 @@ stringData:
# Not a substitute for task 2's per-tenant credentials (still unbuilt
# -- see deploy/operator's Tenant controller); this is the shared
# admin/migration credential only.
password: {{ include "sentry.stableSecretValue" (list .Release.Namespace (printf "%s-clickhouse" .Release.Name) "password" .Values.clickhouse.password) }}
password: {{ include "cairnobs.stableSecretValue" (list .Release.Namespace (printf "%s-clickhouse" .Release.Name) "password" .Values.clickhouse.password) }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ .Release.Name }}-postgres
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
type: Opaque
stringData:
password: {{ include "sentry.stableSecretValue" (list .Release.Namespace (printf "%s-postgres" .Release.Name) "password" .Values.postgres.password) }}
password: {{ include "cairnobs.stableSecretValue" (list .Release.Namespace (printf "%s-postgres" .Release.Name) "password" .Values.postgres.password) }}
# Restricted audit_writer Postgres role (Phase 4 task 4) -- INSERT+SELECT
# only, via its own pool, never the shared role above. See
# /docs/phase-4-isolation-design.md's audit-logging section and
# metadata/README.md.
auditWriterPassword: {{ include "sentry.stableSecretValue" (list .Release.Namespace (printf "%s-postgres" .Release.Name) "auditWriterPassword" .Values.postgres.auditWriterPassword) }}
auditWriterPassword: {{ include "cairnobs.stableSecretValue" (list .Release.Namespace (printf "%s-postgres" .Release.Name) "auditWriterPassword" .Values.postgres.auditWriterPassword) }}
{{- if .Values.enterprise.enabled }}
---
apiVersion: v1
@@ -65,7 +65,7 @@ kind: Secret
metadata:
name: {{ .Release.Name }}-enterprise-auth
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
type: Opaque
stringData:
# Must be >= 32 bytes -- see enterprise/internal/config.Load and
@@ -74,7 +74,7 @@ stringData:
# "don't rotate a live credential silently" reasoning as above,
# which is why it's kept stable via the lookup above rather than
# regenerated on every `helm upgrade`.
sessionSigningKey: {{ include "sentry.stableSecretValue" (list .Release.Namespace (printf "%s-enterprise-auth" .Release.Name) "sessionSigningKey" .Values.enterprise.sessionSigningKey) }}
sessionSigningKey: {{ include "cairnobs.stableSecretValue" (list .Release.Namespace (printf "%s-enterprise-auth" .Release.Name) "sessionSigningKey" .Values.enterprise.sessionSigningKey) }}
{{- if .Values.enterprise.oidc.clientSecret }}
oidcClientSecret: {{ .Values.enterprise.oidc.clientSecret | quote }}
{{- end }}
@@ -4,10 +4,10 @@ kind: ServiceAccount
metadata:
name: {{ .Release.Name }}-tenant-operator
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
---
# ClusterRole, not Role: Tenant is cluster-scoped-CRD-but-namespaced-object
# (see crds/sentry.io_tenants.yaml's scope: Namespaced), and this chart
# (see crds/cairnobs.io_tenants.yaml's scope: Namespaced), and this chart
# doesn't assume it's the only namespace the operator might one day watch
# -- narrowed to exactly the two resource types
# deploy/operator/internal/controller/tenant_controller.go's
@@ -22,12 +22,12 @@ kind: ClusterRole
metadata:
name: {{ .Release.Name }}-tenant-operator
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
rules:
- apiGroups: ["sentry.io"]
- apiGroups: ["cairnobs.io"]
resources: ["tenants"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["sentry.io"]
- apiGroups: ["cairnobs.io"]
resources: ["tenants/status"]
verbs: ["get", "update", "patch"]
---
@@ -36,7 +36,7 @@ kind: ClusterRoleBinding
metadata:
name: {{ .Release.Name }}-tenant-operator
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
@@ -51,8 +51,8 @@ kind: Deployment
metadata:
name: {{ .Release.Name }}-tenant-operator
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "tenant-operator") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "tenant-operator") | nindent 4 }}
spec:
# One replica -- see deploy/operator/cmd/tenant-operator/main.go's
# comment: no leader election yet, a second replica could
@@ -60,11 +60,11 @@ spec:
replicas: 1
selector:
matchLabels:
{{- include "sentry.selectorLabels" (list $ "tenant-operator") | nindent 6 }}
{{- include "cairnobs.selectorLabels" (list $ "tenant-operator") | nindent 6 }}
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "tenant-operator") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "tenant-operator") | nindent 8 }}
spec:
serviceAccountName: {{ .Release.Name }}-tenant-operator
containers:
@@ -1,12 +1,12 @@
{{- if .Values.enterprise.enabled }}
{{- range .Values.tenants }}
---
apiVersion: sentry.io/v1alpha1
apiVersion: cairnobs.io/v1alpha1
kind: Tenant
metadata:
name: {{ .name }}
labels:
{{- include "sentry.labels" $ | nindent 4 }}
{{- include "cairnobs.labels" $ | nindent 4 }}
spec:
displayName: {{ .displayName | default .name | quote }}
suspended: {{ .suspended | default false }}
@@ -3,17 +3,17 @@ kind: Deployment
metadata:
name: {{ .Release.Name }}-web
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "web") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "web") | nindent 4 }}
spec:
replicas: {{ .Values.web.replicas }}
selector:
matchLabels:
{{- include "sentry.selectorLabels" (list $ "web") | nindent 6 }}
{{- include "cairnobs.selectorLabels" (list $ "web") | nindent 6 }}
template:
metadata:
labels:
{{- include "sentry.selectorLabels" (list $ "web") | nindent 8 }}
{{- include "cairnobs.selectorLabels" (list $ "web") | nindent 8 }}
spec:
containers:
- name: web
@@ -33,11 +33,11 @@ kind: Service
metadata:
name: {{ .Release.Name }}-web
labels:
{{- include "sentry.labels" . | nindent 4 }}
{{- include "sentry.selectorLabels" (list $ "web") | nindent 4 }}
{{- include "cairnobs.labels" . | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "web") | nindent 4 }}
spec:
selector:
{{- include "sentry.selectorLabels" (list $ "web") | nindent 4 }}
{{- include "cairnobs.selectorLabels" (list $ "web") | nindent 4 }}
ports:
- name: http
port: 3000
@@ -1,9 +1,9 @@
# Default values for the sentry chart. See deploy/helm/sentry/README.md
# Default values for the cairnobs chart. See deploy/helm/cairnobs/README.md
# for the multi-tenant-specific values (enterprise.*, tenants) and what
# "multi-tenant-aware" does and doesn't mean at this layer.
#
# Image repositories default to locally-built tags matching each
# service's docker-compose.yml container_name, minus the "sentry-"
# service's docker-compose.yml container_name, minus the "cairnobs-"
# container_name prefix duplication -- push these to a registry this
# cluster can actually pull from before installing; this chart never
# builds images itself (same division of labor as docker-compose.yml:
@@ -22,7 +22,7 @@ redpanda:
# Built from ./transport (docker-compose.yml's redpanda-provision
# service) -- the one-shot topic-creation Job below.
provisionImage:
repository: sentry-redpanda-provision
repository: cairnobs-redpanda-provision
tag: latest
clickhouse:
@@ -38,7 +38,7 @@ clickhouse:
# Built from ./storage (docker-compose.yml's clickhouse-migrate
# service) -- the one-shot schema-migration Job.
migrateImage:
repository: sentry-clickhouse-migrate
repository: cairnobs-clickhouse-migrate
tag: latest
postgres:
@@ -53,12 +53,12 @@ postgres:
# Built from ./metadata (docker-compose.yml's metadata-migrate
# service) -- the one-shot schema-migration Job.
migrateImage:
repository: sentry-metadata-migrate
repository: cairnobs-metadata-migrate
tag: latest
ingest:
image:
repository: sentry-ingest
repository: cairnobs-ingest
tag: latest
replicas: 1
resources: {}
@@ -87,7 +87,7 @@ ingest:
search:
image:
repository: sentry-search
repository: cairnobs-search
tag: latest
# Pinned to 1: search consumes the same Redpanda topic ingest's
# consumer does with its own offset tracking (see search/README.md).
@@ -103,14 +103,14 @@ search:
api:
image:
repository: sentry-api
repository: cairnobs-api
tag: latest
replicas: 2
resources: {}
alerting:
image:
repository: sentry-alerting
repository: cairnobs-alerting
tag: latest
# Pinned to 1 for the same reason as search: rulestore.ClaimDueRules
# has no leader-election/partitioning story for multiple evaluator
@@ -125,7 +125,7 @@ alerting:
web:
image:
repository: sentry-web
repository: cairnobs-web
tag: latest
replicas: 2
resources: {}
@@ -151,7 +151,7 @@ web:
enterprise:
enabled: false
image:
repository: sentry-enterprise-auth
repository: cairnobs-enterprise-auth
tag: latest
# enterprise-api (templates/enterprise-api.yaml) -- swaps in for
# api.yaml's plain api Deployment when enterprise.enabled is true, on
@@ -160,7 +160,7 @@ enterprise:
# enterprise-auth's image above -- see
# enterprise/cmd/enterprise-api/Dockerfile.
apiImage:
repository: sentry-enterprise-api
repository: cairnobs-enterprise-api
tag: latest
# enterprise-ingest (templates/enterprise-ingest.yaml) -- only
# rendered when ingest.requireTenantCredential is also true (see that
@@ -169,7 +169,7 @@ enterprise:
# "repo root build context" reasoning as apiImage above -- see
# enterprise/cmd/enterprise-ingest/Dockerfile.
ingestImage:
repository: sentry-enterprise-ingest
repository: cairnobs-enterprise-ingest
tag: latest
replicas: 1
resources: {}
@@ -195,7 +195,7 @@ enterprise:
tenantOperator:
enabled: false
image:
repository: sentry-tenant-operator
repository: cairnobs-tenant-operator
tag: latest
resources: {}
+1 -1
View File
@@ -1,7 +1,7 @@
# Same shape as every other Go service's Dockerfile in this repo
# (alerting/Dockerfile, enterprise/Dockerfile) -- context is
# deploy/operator/ itself, no /proto dependency.
# docker build -f deploy/operator/Dockerfile -t sentry-tenant-operator deploy/operator/
# docker build -f deploy/operator/Dockerfile -t cairnobs-tenant-operator deploy/operator/
FROM golang:1.25-alpine AS builder
WORKDIR /src
COPY . .
+7 -7
View File
@@ -1,7 +1,7 @@
# deploy/operator
A small `controller-runtime` Operator managing one CRD: `Tenant`
(`sentry.io/v1alpha1`). See `internal/controller/tenant_controller.go`'s
(`cairnobs.io/v1alpha1`). See `internal/controller/tenant_controller.go`'s
doc comment for exactly what it reconciles and -- just as importantly --
what it deliberately doesn't (no ClickHouse calls, no Tantivy filesystem
access, no `enterprise/internal/rbacstore` wiring; those are
@@ -17,7 +17,7 @@ environment, so this package is hand-written rather than generated:
`api/v1alpha1/api_test.go`'s round-trip tests (mutate a copy, assert
the original is untouched -- exactly the class of bug a hand-written
`DeepCopy` is prone to).
- `config/crd/sentry.io_tenants.yaml` -- normally `controller-gen crd`
- `config/crd/cairnobs.io_tenants.yaml` -- normally `controller-gen crd`
output from the `+kubebuilder:validation:*` markers on
`api/v1alpha1/tenant_types.go`; hand-written here and only as strong as
keeping the two in sync by hand. Validated by strict-unmarshaling it
@@ -29,7 +29,7 @@ environment, so this package is hand-written rather than generated:
are present as documentation/intent (matching kubebuilder convention)
but were never run through `controller-gen rbac` -- the actual
ClusterRole is hand-written in
`/deploy/helm/sentry/templates/tenant-operator.yaml`, kept in sync with
`/deploy/helm/cairnobs/templates/tenant-operator.yaml`, kept in sync with
those markers by hand, same caveat as the CRD above.
## Layout
@@ -59,7 +59,7 @@ garbage collection, watch-triggered re-reconciliation) -- see
`internal/controller/tenant_controller_test.go`'s doc comment.
```sh
docker build -f Dockerfile -t sentry-tenant-operator . # context is deploy/operator/, not the repo root
docker build -f Dockerfile -t cairnobs-tenant-operator . # context is deploy/operator/, not the repo root
```
Not verified in this session -- see `/deploy/README.md`.
@@ -67,9 +67,9 @@ Not verified in this session -- see `/deploy/README.md`.
## Trying it against a real cluster
```sh
kubectl apply -f config/crd/sentry.io_tenants.yaml
kubectl apply -f config/crd/cairnobs.io_tenants.yaml
kubectl apply -f - <<'EOF'
apiVersion: sentry.io/v1alpha1
apiVersion: cairnobs.io/v1alpha1
kind: Tenant
metadata:
name: acme
@@ -77,5 +77,5 @@ spec:
displayName: "Acme Corp"
EOF
kubectl get tenant acme -o yaml # status.phase should reach Active
kubectl get secret sentry-tenant-acme-clickhouse -o yaml
kubectl get secret cairnobs-tenant-acme-clickhouse -o yaml
```
@@ -7,7 +7,7 @@
// cluster).
//
// +kubebuilder:object:generate=true
// +groupName=sentry.io
// +groupName=cairnobs.io
package v1alpha1
import (
@@ -16,8 +16,8 @@ import (
)
var (
// GroupVersion is group sentry.io, version v1alpha1.
GroupVersion = schema.GroupVersion{Group: "sentry.io", Version: "v1alpha1"}
// GroupVersion is group cairnobs.io, version v1alpha1.
GroupVersion = schema.GroupVersion{Group: "cairnobs.io", Version: "v1alpha1"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme.
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
+1 -1
View File
@@ -117,7 +117,7 @@ const ConditionReady = "Ready"
// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`
// Tenant is the K8s-native representation of one Sentry tenant's
// Tenant is the K8s-native representation of one Cairn OBS tenant's
// deployment-topology state -- see this file's package-level doc
// comment for what it does and does not manage today.
type Tenant struct {
+3 -3
View File
@@ -18,15 +18,15 @@ import (
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/metrics/server"
sentryv1alpha1 "github.com/sentry/sentry/deploy/operator/api/v1alpha1"
"github.com/sentry/sentry/deploy/operator/internal/controller"
cairnobsv1alpha1 "github.com/cairnobs/cairnobs/deploy/operator/api/v1alpha1"
"github.com/cairnobs/cairnobs/deploy/operator/internal/controller"
)
var scheme = runtime.NewScheme()
func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
utilruntime.Must(sentryv1alpha1.AddToScheme(scheme))
utilruntime.Must(cairnobsv1alpha1.AddToScheme(scheme))
}
func main() {
@@ -7,9 +7,9 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: tenants.sentry.io
name: tenants.cairnobs.io
spec:
group: sentry.io
group: cairnobs.io
names:
kind: Tenant
listKind: TenantList
+1 -1
View File
@@ -1,4 +1,4 @@
module github.com/sentry/sentry/deploy/operator
module github.com/cairnobs/cairnobs/deploy/operator
go 1.25.0
@@ -35,7 +35,7 @@ import (
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
sentryv1alpha1 "github.com/sentry/sentry/deploy/operator/api/v1alpha1"
cairnobsv1alpha1 "github.com/cairnobs/cairnobs/deploy/operator/api/v1alpha1"
)
// TenantReconciler reconciles a Tenant object.
@@ -44,11 +44,11 @@ type TenantReconciler struct {
Scheme *runtime.Scheme
}
// +kubebuilder:rbac:groups=sentry.io,resources=tenants,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=sentry.io,resources=tenants/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=cairnobs.io,resources=tenants,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=cairnobs.io,resources=tenants/status,verbs=get;update;patch
func (r *TenantReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
var tenant sentryv1alpha1.Tenant
var tenant cairnobsv1alpha1.Tenant
if err := r.Get(ctx, req.NamespacedName, &tenant); err != nil {
if apierrors.IsNotFound(err) {
// Deleted -- the owned Secret -provision-tenant created (if
@@ -74,19 +74,19 @@ func (r *TenantReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr
reason, message := "AwaitingProvisioning", "waiting for enterprise-api -provision-tenant to provision ClickHouse for this tenant"
switch {
case tenant.Spec.Suspended:
tenant.Status.Phase = sentryv1alpha1.PhaseSuspended
tenant.Status.Phase = cairnobsv1alpha1.PhaseSuspended
reason, message = "Suspended", "tenant is suspended (spec.suspended=true)"
case provisioned:
tenant.Status.Phase = sentryv1alpha1.PhaseActive
tenant.Status.Phase = cairnobsv1alpha1.PhaseActive
condStatus = metav1.ConditionTrue
reason, message = "Provisioned", fmt.Sprintf("ClickHouse database %q is provisioned", tenant.Status.ClickHouseDatabaseName)
default:
tenant.Status.Phase = sentryv1alpha1.PhaseProvisioning
tenant.Status.Phase = cairnobsv1alpha1.PhaseProvisioning
}
tenant.Status.ObservedGeneration = tenant.Generation
meta.SetStatusCondition(&tenant.Status.Conditions, metav1.Condition{
Type: sentryv1alpha1.ConditionReady,
Type: cairnobsv1alpha1.ConditionReady,
Status: condStatus,
Reason: reason,
Message: message,
@@ -102,6 +102,6 @@ func (r *TenantReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr
func (r *TenantReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&sentryv1alpha1.Tenant{}).
For(&cairnobsv1alpha1.Tenant{}).
Complete(r)
}
@@ -23,7 +23,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
sentryv1alpha1 "github.com/sentry/sentry/deploy/operator/api/v1alpha1"
cairnobsv1alpha1 "github.com/cairnobs/cairnobs/deploy/operator/api/v1alpha1"
)
func newFakeReconciler(t *testing.T, objs ...client.Object) *TenantReconciler {
@@ -32,31 +32,31 @@ func newFakeReconciler(t *testing.T, objs ...client.Object) *TenantReconciler {
if err := corev1.AddToScheme(scheme); err != nil {
t.Fatalf("adding corev1 to scheme: %v", err)
}
if err := sentryv1alpha1.AddToScheme(scheme); err != nil {
t.Fatalf("adding sentryv1alpha1 to scheme: %v", err)
if err := cairnobsv1alpha1.AddToScheme(scheme); err != nil {
t.Fatalf("adding cairnobsv1alpha1 to scheme: %v", err)
}
fakeClient := fake.NewClientBuilder().
WithScheme(scheme).
WithObjects(objs...).
WithStatusSubresource(&sentryv1alpha1.Tenant{}).
WithStatusSubresource(&cairnobsv1alpha1.Tenant{}).
Build()
return &TenantReconciler{Client: fakeClient, Scheme: scheme}
}
func testTenant(name string, suspended bool) *sentryv1alpha1.Tenant {
return &sentryv1alpha1.Tenant{
func testTenant(name string, suspended bool) *cairnobsv1alpha1.Tenant {
return &cairnobsv1alpha1.Tenant{
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: "default"},
Spec: sentryv1alpha1.TenantSpec{DisplayName: name, Suspended: suspended},
Spec: cairnobsv1alpha1.TenantSpec{DisplayName: name, Suspended: suspended},
}
}
func reconcile(t *testing.T, r *TenantReconciler, name string) sentryv1alpha1.Tenant {
func reconcile(t *testing.T, r *TenantReconciler, name string) cairnobsv1alpha1.Tenant {
t.Helper()
ctx := context.Background()
if _, err := r.Reconcile(ctx, ctrl.Request{NamespacedName: types.NamespacedName{Name: name, Namespace: "default"}}); err != nil {
t.Fatalf("Reconcile: %v", err)
}
var got sentryv1alpha1.Tenant
var got cairnobsv1alpha1.Tenant
if err := r.Get(ctx, types.NamespacedName{Name: name, Namespace: "default"}, &got); err != nil {
t.Fatalf("getting tenant: %v", err)
}
@@ -74,7 +74,7 @@ func TestReconcileUnprovisionedTenantIsProvisioningNotActive(t *testing.T) {
got := reconcile(t, r, "acme")
if got.Status.Phase != sentryv1alpha1.PhaseProvisioning {
if got.Status.Phase != cairnobsv1alpha1.PhaseProvisioning {
t.Fatalf("Phase = %q, want Provisioning (nothing has provisioned this tenant yet)", got.Status.Phase)
}
cond := readyCondition(got)
@@ -93,23 +93,23 @@ func TestReconcileReflectsProvisioningStateProvisionTenantSets(t *testing.T) {
r := newFakeReconciler(t, tenant)
ctx := context.Background()
var toUpdate sentryv1alpha1.Tenant
var toUpdate cairnobsv1alpha1.Tenant
if err := r.Get(ctx, types.NamespacedName{Name: "acme", Namespace: "default"}, &toUpdate); err != nil {
t.Fatalf("getting tenant: %v", err)
}
toUpdate.Status.ClickHouseDatabaseName = "acme"
toUpdate.Status.ClickHouseSecretRef = "sentry-tenant-acme-clickhouse"
toUpdate.Status.TantivyIndexPath = "/var/lib/sentry-search/tenants/acme"
toUpdate.Status.ClickHouseSecretRef = "cairnobs-tenant-acme-clickhouse"
toUpdate.Status.TantivyIndexPath = "/var/lib/cairnobs-search/tenants/acme"
if err := r.Status().Update(ctx, &toUpdate); err != nil {
t.Fatalf("simulating -provision-tenant's status write: %v", err)
}
got := reconcile(t, r, "acme")
if got.Status.Phase != sentryv1alpha1.PhaseActive {
if got.Status.Phase != cairnobsv1alpha1.PhaseActive {
t.Fatalf("Phase = %q, want Active", got.Status.Phase)
}
if got.Status.ClickHouseDatabaseName != "acme" || got.Status.ClickHouseSecretRef != "sentry-tenant-acme-clickhouse" || got.Status.TantivyIndexPath != "/var/lib/sentry-search/tenants/acme" {
if got.Status.ClickHouseDatabaseName != "acme" || got.Status.ClickHouseSecretRef != "cairnobs-tenant-acme-clickhouse" || got.Status.TantivyIndexPath != "/var/lib/cairnobs-search/tenants/acme" {
t.Fatalf("reconcile must not clobber the fields -provision-tenant set: %+v", got.Status)
}
cond := readyCondition(got)
@@ -125,7 +125,7 @@ func TestReconcileSuspendedOverridesProvisionedState(t *testing.T) {
got := reconcile(t, r, "acme")
if got.Status.Phase != sentryv1alpha1.PhaseSuspended {
if got.Status.Phase != cairnobsv1alpha1.PhaseSuspended {
t.Fatalf("Phase = %q, want Suspended even though the tenant is provisioned", got.Status.Phase)
}
}
@@ -144,7 +144,7 @@ func TestReconcileUnsuspendingReturnsToActiveNotProvisioning(t *testing.T) {
_ = reconcile(t, r, "acme") // establishes Suspended
var toUpdate sentryv1alpha1.Tenant
var toUpdate cairnobsv1alpha1.Tenant
if err := r.Get(ctx, types.NamespacedName{Name: "acme", Namespace: "default"}, &toUpdate); err != nil {
t.Fatalf("getting tenant: %v", err)
}
@@ -154,7 +154,7 @@ func TestReconcileUnsuspendingReturnsToActiveNotProvisioning(t *testing.T) {
}
got := reconcile(t, r, "acme")
if got.Status.Phase != sentryv1alpha1.PhaseActive {
if got.Status.Phase != cairnobsv1alpha1.PhaseActive {
t.Fatalf("Phase = %q, want Active after unsuspending an already-provisioned tenant", got.Status.Phase)
}
}
@@ -167,9 +167,9 @@ func TestReconcileMissingTenantIsNoOp(t *testing.T) {
}
}
func readyCondition(tenant sentryv1alpha1.Tenant) *metav1.Condition {
func readyCondition(tenant cairnobsv1alpha1.Tenant) *metav1.Condition {
for i := range tenant.Status.Conditions {
if tenant.Status.Conditions[i].Type == sentryv1alpha1.ConditionReady {
if tenant.Status.Conditions[i].Type == cairnobsv1alpha1.ConditionReady {
return &tenant.Status.Conditions[i]
}
}