Help us shape the future of Go! Take the 2026 Go Developer Survey

amconfig

package
v1.0.14 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 2, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package amconfig renders an Alertmanager configuration from stored receivers and routes. It is the part of alerting where a bug becomes org A's alert reaching org B's Slack.

It is the ONE renderer: the control plane renders every org's configuration with it from its Postgres rows, and `forge env up` renders a local stack's configuration with it from the env's KCL (one org, "local"), so an alert routes the same way on a laptop as in production. The package knows nothing about where receivers are stored or how the config reaches Alertmanager.

An org is the unit of routing isolation: a self-hoster with one team uses one.

The routing invariant

The rendered root route has the BLACKHOLE receiver as its default and one child route per org, each matched STRICTLY on `reliant_org_id="<org>"` with continue: false. Everything below an org's route is that org's own: its env routes (matched by labels the rule author set) and its receivers. Nothing an alert, a rule or an env route says can move it out of its org's subtree, because:

  • reliant_org_id is set by the evaluator from the RuleSource's identity and can never come from a rule (forge/pkg/alerting strips reliant_*);
  • every child's own matchers are ANDed under the org matcher, so they narrow, never widen;
  • env routes and receivers are loaded per org and an env route naming a receiver the org does not have is DROPPED at render time (and reported), so a route can only ever point at the receiver of its own org;
  • receiver names are namespaced per org ("<org>/<name>"), so two orgs that both call a receiver "oncall" cannot collide into one;
  • an org with no receivers gets no route and therefore the blackhole.

Autopilot receivers

An autopilot receiver (a Reliant Autopilot automation) is reached by no env route. It gets a route of its own at the TOP of its org's subtree, with continue: true, so every alert of the org that passes its filter reaches it and then carries on to the org's own routing exactly as before. Three things keep that true:

  • the route sits inside the org's subtree, so it narrows the org matcher like any child and cannot see another org's alerts;
  • it is scoped to the environments its automation's project owns (reliant_env_id, resolved by the caller into Autopilot.EnvIDs) — an autopilot receiver with no environment in scope gets no route at all;
  • the org's own routing is wrapped in ONE catch-all child that keeps the org's default receiver. Alertmanager uses a parent's receiver only when no child matched, so without the wrapper a match on the autopilot route would silently cost the org its default (in-app) delivery.

The filter is a severity match OR an alert-name match (the platform's issue alerts, whatever their severity); Alertmanager ANDs a route's matchers, so the OR is two children of a blackhole parent, the first match winning.

TestNoRouteDeliversAcrossOrgs enumerates this property over the real Alertmanager routing tree (dispatch.NewRoute), not over the YAML.

Secrets

Receiver secrets are never in the config. Each is a file in the mounted Secret, referenced through the receiver's *_file fields (slack api_url_file, pagerduty routing_key_file, webhook http_config.authorization.credentials_file, email auth_password_file). The renderer returns the set of files the Secret must contain; it never sees a value.

Index

Constants

View Source
const (
	TypeSlack     = "slack"
	TypeWebhook   = "webhook"
	TypeEmail     = "email"
	TypePagerDuty = "pagerduty"
	TypeInApp     = "reliant_inapp"
	TypeAutopilot = "autopilot"
)

Receiver types, as stored.

View Source
const Blackhole = "blackhole"

Blackhole is the default receiver: it has no integrations, so an alert that reaches it is delivered to no one.

View Source
const DefaultReceiverName = "reliant-inapp"

DefaultReceiverName is the platform-owned in-app receiver every org with rules gets (the syncer adds it). It is the org's default, so what an org names its own receivers can never change where unrouted alerts go.

View Source
const OrgLabel = "reliant_org_id"

OrgLabel is the label every route is scoped by.

View Source
const SecretDir = "/etc/alertmanager/secrets"

SecretDir is where the Alertmanager Secret is mounted.

View Source
const TestLabel = "reliant_test_receiver"

TestLabel selects exactly one receiver of an org for a test notification. Only the platform sets it: the evaluator drops every "reliant_" label a rule declares and routeNode refuses a matcher on one, so no rule can reach a receiver this way.

Variables

This section is empty.

Functions

func ClusterInternal

func ClusterInternal(host string) bool

ClusterInternal reports a host only a cluster (or this machine) resolves, the one place plain http is acceptable for an autopilot receiver: the hop never leaves the cluster network.

func RecvName

func RecvName(org, name string) string

RecvName is the Alertmanager receiver name for an org's receiver.

Types

type AutopilotRoute

type AutopilotRoute struct {
	// EnvIDs are the environments whose alerts reach it. Empty: none do.
	EnvIDs []string
	// Severities are the severity label values that reach it; a single "*"
	// is every alert.
	Severities []string
	// AlwaysAlertnames reach it whatever their severity.
	AlwaysAlertnames []string
}

AutopilotRoute is the resolved filter of an autopilot receiver.

type Input

type Input struct {
	Receivers []Receiver
	Routes    []Route
	Settings  Settings
}

Input is everything the renderer reads.

type Receiver

type Receiver struct {
	OrgID string
	Name  string
	Type  string
	// SecretRef is the file name (inside SecretDir) holding the secret, or "".
	SecretRef string
	Settings  map[string]string
	// Autopilot is where a TypeAutopilot receiver's route reaches; nil for
	// every other type (and an autopilot receiver without it gets no route).
	Autopilot *AutopilotRoute
}

Receiver is one stored receiver.

type Rendered

type Rendered struct {
	// YAML is the Alertmanager configuration.
	YAML []byte
	// Hash identifies the configuration; a syncer compares it to what is live.
	Hash string
	// Files are the secret files the Secret must contain: name -> the org and
	// receiver that need it (the caller fills in the values from its own
	// secret storage).
	Files []SecretFile
	// Skipped says what was left out and why. Never an error: one bad receiver
	// must not take every other org's alerting down.
	Skipped []string
}

Rendered is the renderer's result.

func Render

func Render(in Input) (Rendered, error)

Render builds the configuration. It is pure: same Input, same bytes.

type Route

type Route struct {
	OrgID     string
	EnvID     string
	Position  int
	Matchers  map[string]string
	Receivers []string
	Continue  bool
}

Route is one env route: labels the rule author set, mapped to receiver names.

type SMTP

type SMTP struct {
	Host         string // host:port, e.g. smtp.resend.com:587
	From         string
	Username     string // Resend: "resend"
	PasswordFile string
}

SMTP is the email relay. The password is a FILE, like every secret.

type SecretFile

type SecretFile struct {
	Name     string
	OrgID    string
	Receiver string
}

SecretFile is one file the mounted Secret must hold.

type Settings

type Settings struct {
	// InAppURL is the endpoint the reliant_inapp receivers post to: the
	// control plane's in-app notification webhook, or a local stack's alert
	// log sink.
	InAppURL string
	// InAppTokenFile holds the bearer token that endpoint requires.
	InAppTokenFile string
	// AllowHTTPWebhooks lets a webhook receiver's url be plain http. Only a
	// LOCAL stack sets it, where every receiver is the developer's own machine.
	// A renderer serving several orgs must leave it false: a customer-supplied http URL
	// could name a cluster-internal service, and Alertmanager would post to it
	// from inside the cluster.
	AllowHTTPWebhooks bool
	// SMTP is Resend's relay. Empty Host disables email receivers (they are
	// dropped and reported, never rendered half-configured).
	SMTP SMTP
	// GroupWait / GroupInterval / RepeatInterval default to 30s / 5m / 4h.
	GroupWait, GroupInterval, RepeatInterval string
}

Settings are the process-wide parts of the configuration.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL