Documentation
¶
Overview ¶
Package statuswebhook delivers signed status page events to subscriber URLs.
Index ¶
- Constants
- Variables
- func Sign(secret, timestamp string, body []byte) string
- func Verify(secret, timestamp string, body []byte, signature string) bool
- type ComponentRef
- type Config
- type Envelope
- type Event
- type PageRef
- type Sealer
- type Service
- func (s *Service) Config() Config
- func (s *Service) Create(ctx context.Context, rawURL, label string, events []string) (store.StatusWebhook, string, error)
- func (s *Service) Delete(ctx context.Context, id string) error
- func (s *Service) Deliveries(ctx context.Context, id string) ([]store.StatusWebhookDelivery, error)
- func (s *Service) Emit(ctx context.Context, ev Event) error
- func (s *Service) ProcessDue(ctx context.Context) (int, error)
- func (s *Service) Rotate(ctx context.Context, id string) (string, error)
- func (s *Service) Run(ctx context.Context) error
- func (s *Service) Test(ctx context.Context, id string, page PageRef) (TestResult, error)
- func (s *Service) ValidateURL(ctx context.Context, raw string) error
- type Store
- type TestResult
- type ValidationError
Constants ¶
const ( EnvMaxSubscribers = "APP_STATUS_WEBHOOK_MAX_SUBSCRIBERS" EnvTimeout = "APP_STATUS_WEBHOOK_TIMEOUT" EnvMaxAttempts = "APP_STATUS_WEBHOOK_MAX_ATTEMPTS" EnvBackoffBase = "APP_STATUS_WEBHOOK_BACKOFF_BASE" EnvBackoffMax = "APP_STATUS_WEBHOOK_BACKOFF_MAX" EnvPauseAfter = "APP_STATUS_WEBHOOK_PAUSE_AFTER" EnvPoll = "APP_STATUS_WEBHOOK_POLL_INTERVAL" EnvLogKeep = "APP_STATUS_WEBHOOK_LOG_KEEP" EnvAllowHTTP = "APP_STATUS_WEBHOOK_ALLOW_HTTP" EnvAllowPrivate = "APP_STATUS_WEBHOOK_ALLOW_PRIVATE" )
Environment variables that tune delivery. Every value has a default; none is a secret.
const ( IncidentOpened = "incident_opened" IncidentUpdated = "incident_updated" IncidentResolved = "incident_resolved" ComponentChanged = "component_changed" MaintenanceScheduled = "maintenance_scheduled" MaintenanceUpdated = "maintenance_updated" MaintenanceCompleted = "maintenance_completed" // Ping is the signed test event; it is never subject to a filter. Ping = "ping" )
Event types a subscriber can filter on.
Variables ¶
ErrSealerUnavailable means a sealed secret cannot be opened because no master key is configured.
var EventTypes = []string{IncidentOpened, IncidentUpdated, IncidentResolved, ComponentChanged, MaintenanceScheduled, MaintenanceUpdated, MaintenanceCompleted}
EventTypes lists every type a subscriber may filter on.
Functions ¶
Types ¶
type ComponentRef ¶
type ComponentRef struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Change string `json:"change"`
}
ComponentRef is the public view of a component in an event.
type Config ¶
type Config struct {
MaxSubscribers int
Timeout time.Duration
MaxAttempts int
BackoffBase time.Duration
BackoffMax time.Duration
PauseAfter int
Poll time.Duration
LogKeep int
AllowHTTP bool
AllowPrivate bool
}
Config holds the delivery limits.
func ConfigFromEnv ¶
func ConfigFromEnv() Config
ConfigFromEnv reads Config, falling back to defaults for unset or invalid values.
type Envelope ¶
type Envelope struct {
ID string `json:"id"`
Type string `json:"type"`
CreatedAt time.Time `json:"created_at"`
Page PageRef `json:"page"`
Incident *statuspage.IncidentView `json:"incident,omitempty"`
Component *ComponentRef `json:"component,omitempty"`
}
Envelope is the JSON body posted to subscribers.
type Event ¶
type Event struct {
Type string
ObjectID string
Stamp string
Page PageRef
Incident *statuspage.IncidentView
Component *ComponentRef
}
Event is what callers hand to Emit. ObjectID and Stamp make the event id deterministic.
type Sealer ¶
type Sealer interface {
SetValue(ctx context.Context, serviceName, envKey, plaintext string) error
Resolve(ctx context.Context, serviceName, envKey string) (string, error)
DeleteAll(ctx context.Context, serviceName string) error
}
Sealer is the envelope-encryption surface signing secrets are stored with; *secrets.Manager satisfies it.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service manages subscribers and delivers events.
func New ¶
New builds a Service. sealer may return nil, in which case secrets are stored in the clear column.
func (*Service) Create ¶
func (s *Service) Create(ctx context.Context, rawURL, label string, events []string) (store.StatusWebhook, string, error)
Create validates and stores a subscriber and returns it with its one-time signing secret.
func (*Service) Deliveries ¶
Deliveries returns a subscriber's log, newest first.
func (*Service) Emit ¶
Emit queues ev for every active subscriber whose filter admits it. Repeating the same event is a no-op, so callers may retry freely.
func (*Service) ProcessDue ¶
ProcessDue attempts every delivery whose time has come and returns how many it tried.
func (*Service) Run ¶
Run delivers queued events until ctx ends. It is one goroutine and returns when ctx does.
type Store ¶
type Store interface {
CreateStatusWebhook(ctx context.Context, w store.StatusWebhook, limit int) error
ListStatusWebhooks(ctx context.Context) ([]store.StatusWebhook, error)
GetStatusWebhook(ctx context.Context, id string) (store.StatusWebhook, error)
SetStatusWebhookSecret(ctx context.Context, id, plain string, sealed bool) error
SetStatusWebhookPaused(ctx context.Context, id string, paused bool, reason string) error
DeleteStatusWebhook(ctx context.Context, id string) error
AddStatusWebhookDelivery(ctx context.Context, d store.StatusWebhookDelivery) (bool, error)
DueStatusWebhookDeliveries(ctx context.Context, now time.Time, limit int) ([]store.StatusWebhookDelivery, error)
ListStatusWebhookDeliveries(ctx context.Context, webhookID string, limit int) ([]store.StatusWebhookDelivery, error)
RecordStatusWebhookAttempt(ctx context.Context, d store.StatusWebhookDelivery, ok, countStreak bool, pauseAfter, keep int) (bool, error)
}
Store is the persistence surface; *store.DB satisfies it.
type TestResult ¶
type TestResult struct {
Delivered bool `json:"delivered"`
StatusCode int `json:"status_code"`
Error string `json:"error,omitempty"`
}
TestResult is the outcome of a test ping.
type ValidationError ¶
type ValidationError string
ValidationError is a user-facing problem with a subscriber's input.
func (ValidationError) Error ¶
func (e ValidationError) Error() string