# ============================================================================= # T-4.1 — Hermetic SMTP capture sink for the L3 "alerting" conformance test # (R-OBS-02, R-OBS-04). # # The alerting test injects a fault, Alertmanager fires and routes an email, and # the test asserts the email arrived. To keep the test hermetic (no real inbox, # ADR-0011 reproducibility), Alertmanager's email route is pointed at THIS # in-namespace sink instead of a real MTA. The sink is Mailpit: it speaks SMTP # for delivery and exposes an HTTP API the test polls for the captured message. # # Contract the alerting test relies on (chainsaw injects the ephemeral namespace, # so these are intentionally namespace-less): # * Service name .............. smtp-sink (stable DNS the test/AM target) # * SMTP port (delivery) ...... 1025 (Alertmanager `smarthost`) # * HTTP port (query/API) ..... 8025 (test polls for the message) # * Query endpoint ............ GET http://smtp-sink:8025/api/v1/messages # -> JSON: .messages[].Subject / .To / .From # (health: GET /api/v1/messages returns 200 once the sink is up; a delivered # alert appears as a message whose Subject matches the fired alertname.) # # Mailpit stores messages in memory (no PVC, no persistence) — a leaked namespace # leaves nothing behind, and chainsaw's per-test namespace teardown removes it. # ============================================================================= apiVersion: apps/v1 kind: Deployment metadata: name: smtp-sink labels: app.kubernetes.io/name: smtp-sink app.kubernetes.io/part-of: conformance-alerting conformance.home.k3s/fixture: smtp-sink spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: smtp-sink template: metadata: labels: app.kubernetes.io/name: smtp-sink app.kubernetes.io/part-of: conformance-alerting spec: # Hermetic, disposable capture sink — no state worth protecting. automountServiceAccountToken: false securityContext: runAsNonRoot: true runAsUser: 1000 seccompProfile: type: RuntimeDefault containers: - name: mailpit image: axllent/mailpit:v1.21.8 imagePullPolicy: IfNotPresent env: # Bind SMTP + HTTP UI/API on the well-known conformance ports. - name: MP_SMTP_BIND_ADDR value: "0.0.0.0:1025" - name: MP_UI_BIND_ADDR value: "0.0.0.0:8025" # In-memory store: no disk, cleared on pod restart (hermetic per-run). - name: MP_MAX_MESSAGES value: "500" ports: - name: smtp containerPort: 1025 protocol: TCP - name: http containerPort: 8025 protocol: TCP readinessProbe: httpGet: path: /readyz port: http initialDelaySeconds: 2 periodSeconds: 3 timeoutSeconds: 2 livenessProbe: httpGet: path: /livez port: http initialDelaySeconds: 5 periodSeconds: 10 resources: requests: cpu: 25m memory: 32Mi limits: cpu: 100m memory: 128Mi securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL volumeMounts: - name: tmp mountPath: /tmp volumes: - name: tmp emptyDir: {} --- apiVersion: v1 kind: Service metadata: name: smtp-sink labels: app.kubernetes.io/name: smtp-sink app.kubernetes.io/part-of: conformance-alerting spec: selector: app.kubernetes.io/name: smtp-sink ports: - name: smtp port: 1025 targetPort: smtp protocol: TCP - name: http port: 8025 targetPort: http protocol: TCP