store

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 8, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Overview

Package store keeps edges, checks and results in PostgreSQL with TimescaleDB.

Index

Constants

View Source
const (
	IncidentCheck = "check" // a check keeps failing on an edge
	IncidentEdge  = "edge"  // an edge stopped reporting
)

Kinds of incident.

View Source
const (
	EventOpened   = "opened"
	EventResolved = "resolved"
)

Events an incident tells its channels about.

View Source
const (
	ResolutionRecovered    = "recovered"
	ResolutionEdgeRevoked  = "edge revoked"
	ResolutionCheckRemoved = "check removed"
)

How an incident ended.

View Source
const (
	RoleAdmin  = "admin"
	RoleViewer = "viewer"
)

The roles of a user.

Variables

View Source
var (

	// ErrNotFound is returned when the row asked for does not exist.
	ErrNotFound = errors.New("not found")
	// ErrExists is returned when a row with that name or id already exists.
	ErrExists = errors.New("already exists")
)
View Source
var (

	// ErrLastAdmin is returned when a change would leave no administrator.
	ErrLastAdmin = errors.New("this is the last administrator")
	// ErrSetupDone is returned when the first administrator exists already.
	ErrSetupDone = errors.New("the setup is already done")
)
View Source
var ErrKeyMissing = errors.New("the value is encrypted and no key was given")

ErrKeyMissing is returned for a value that is encrypted when no key was given.

Functions

func GenerateKey added in v1.1.0

func GenerateKey() (string, error)

GenerateKey returns a new random key, as base64.

func ParseKey added in v1.1.0

func ParseKey(text string) ([]byte, error)

ParseKey reads a key written as base64 or as hexadecimal.

func ValidRole added in v1.1.0

func ValidRole(role string) bool

ValidRole reports whether role is one of the known roles.

func ValidateChannelName added in v1.1.0

func ValidateChannelName(name string) error

ValidateChannelName reports why a name cannot be given to a channel.

func ValidateChannelSecret added in v1.1.0

func ValidateChannelSecret(secret string) error

ValidateChannelSecret reports why a secret cannot be used to sign.

func ValidateChannelURL added in v1.1.0

func ValidateChannelURL(raw string) error

ValidateChannelURL reports why a webhook address cannot be used. Credentials belong in the secret or the path, not in a user name: the address ends up in places where a password should not.

func ValidateEdgeName added in v1.1.0

func ValidateEdgeName(name string) error

ValidateEdgeName reports why a name cannot be given to an edge.

func ValidateUsername added in v1.1.0

func ValidateUsername(username string) error

ValidateUsername reports why a name cannot be given to an account.

Types

type AuditEvent added in v1.1.0

type AuditEvent struct {
	ID       int64
	At       time.Time
	Actor    string // empty when nobody was signed in
	Action   string // login, user.create, edge.revoke...
	Target   string // what it was done to, when that is a name
	ClientIP string
}

AuditEvent is something a person did that changed what the central holds, or that tried to get in.

type Channel added in v1.1.0

type Channel struct {
	Name      string
	URL       string
	Secret    string // empty: what is sent is not signed
	CreatedAt time.Time
}

Channel is a webhook that is told when an incident opens or resolves.

type Cipher added in v1.1.0

type Cipher struct {
	// contains filtered or unexported fields
}

Cipher encrypts what the central must read back: the address and the signing secret of a channel. A hash would not do, they are sent. AES-256-GCM, with the name of the row as additional data, so a value cannot be moved to another row.

func NewCipher added in v1.1.0

func NewCipher(key []byte) (*Cipher, error)

NewCipher builds a cipher from a 32 byte key.

type Edge

type Edge struct {
	ID        string
	Name      string
	CreatedAt time.Time
	RevokedAt *time.Time
}

Edge is a machine allowed to talk to the central. Only the hash of its token is kept.

func (Edge) Active added in v1.1.0

func (e Edge) Active() bool

Active reports whether the edge may still authenticate.

type Incident added in v1.1.0

type Incident struct {
	ID         int64
	Kind       string
	CheckID    string // empty for an edge incident
	EdgeID     string
	EdgeName   string
	StartedAt  time.Time
	ResolvedAt *time.Time
	Detail     string
	Resolution string
}

Incident is something that went wrong on an edge, until it is resolved.

func (Incident) Open added in v1.1.0

func (i Incident) Open() bool

Open reports whether the incident is still going on.

type Info added in v1.1.0

type Info struct {
	ServerVersion    string
	TimescaleVersion string // empty when the extension is not created in this database
	// TimescaleLatest is the version the server has; it differs from
	// TimescaleVersion until the extension is updated.
	TimescaleLatest string
	// TimescaleAvailable tells whether the server has the extension at all.
	TimescaleAvailable bool
	SchemaVersion      int // 0 when no migration was applied
	LatestVersion      int // the newest migration this binary knows
}

Info describes a database as it is, without changing it.

func Inspect added in v1.1.0

func Inspect(ctx context.Context, url string) (Info, error)

Inspect reads the state of a database without migrating it, which is what a diagnostic must do: it must not change what it looks at.

type Notification added in v1.1.0

type Notification struct {
	Incident Incident
	Event    string
	Channel  Channel
}

Notification is an event of an incident that a channel has not been told yet.

func (Notification) At added in v1.1.0

func (n Notification) At() time.Time

At is when the event happened.

type Option added in v1.1.0

type Option func(*Store)

Option changes how a Store is opened.

func WithCipher added in v1.1.0

func WithCipher(c *Cipher) Option

WithCipher encrypts the secrets of the channels, and reads them back.

type Outcome added in v1.1.0

type Outcome struct {
	At    time.Time
	OK    bool
	Error string
}

Outcome is what one run of a check came to.

type PairOutcomes added in v1.1.0

type PairOutcomes struct {
	CheckID string
	EdgeID  string
	Newest  []Outcome
}

PairOutcomes are the latest outcomes of one check on one edge, newest first.

type Result

type Result struct {
	EdgeID string
	api.Result
}

Result is a measurement with the edge that made it.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is the database of the central.

func Open

func Open(ctx context.Context, url string, opts ...Option) (*Store, error)

Open connects to the database and brings its schema up to date.

func (*Store) AddChannel added in v1.1.0

func (s *Store) AddChannel(ctx context.Context, name, rawURL, secret string) (Channel, error)

AddChannel registers a webhook.

func (*Store) AddCheck added in v1.1.0

func (s *Store) AddCheck(ctx context.Context, c api.Check) error

AddCheck registers a check that every edge will run.

func (*Store) AddEdge added in v1.1.0

func (s *Store) AddEdge(ctx context.Context, name string) (Edge, string, error)

AddEdge registers an edge and returns its token, which is not stored and cannot be shown again.

func (*Store) AddFirstAdmin added in v1.1.0

func (s *Store) AddFirstAdmin(ctx context.Context, username, passwordHash string) error

AddFirstAdmin creates the administrator of a central that has no account yet. Two calls at once create one, and the other gets ErrSetupDone.

func (*Store) AddUser added in v1.1.0

func (s *Store) AddUser(ctx context.Context, username, role, passwordHash string) error

AddUser creates an account; the password is already hashed.

func (*Store) AuthenticateEdge added in v1.1.0

func (s *Store) AuthenticateEdge(ctx context.Context, token string) (edge Edge, ok bool, err error)

AuthenticateEdge returns the active edge that owns the token. A token nobody owns is ok=false with no error; an error means the database failed.

func (*Store) AuthenticateSession added in v1.1.0

func (s *Store) AuthenticateSession(ctx context.Context, token string) (user User, ok bool, err error)

AuthenticateSession returns the user of a live session. A token nobody owns or that expired is ok=false with no error; an error means the database failed.

func (*Store) ChannelEncryption added in v1.1.0

func (s *Store) ChannelEncryption(ctx context.Context) (clear, sealed int, err error)

ChannelEncryption counts the channels stored in clear and the ones encrypted.

func (*Store) Close

func (s *Store) Close()

Close releases the connections.

func (*Store) CreateSession

func (s *Store) CreateSession(ctx context.Context, username string, ttl time.Duration) (string, time.Time, error)

CreateSession opens a session and returns its token, which is not stored.

func (*Store) DeleteSession

func (s *Store) DeleteSession(ctx context.Context, token string) error

DeleteSession ends a session; an unknown token is not an error.

func (*Store) DeleteUser

func (s *Store) DeleteUser(ctx context.Context, username string) error

DeleteUser removes an account and its sessions, unless it is the last administrator.

func (*Store) EncryptChannels added in v1.1.0

func (s *Store) EncryptChannels(ctx context.Context) (int, error)

EncryptChannels encrypts the channels written before there was a key, and returns how many it changed.

func (*Store) GetChannel added in v1.1.0

func (s *Store) GetChannel(ctx context.Context, name string) (Channel, error)

GetChannel returns one webhook.

func (*Store) GrantReadOnly added in v1.1.0

func (s *Store) GrantReadOnly(ctx context.Context, role string) error

GrantReadOnly lets a database role read the results, checks and incidents, and the name and dates of the edges, never the hash of their token. It is safe to repeat.

func (*Store) HasUsers added in v1.1.0

func (s *Store) HasUsers(ctx context.Context) (bool, error)

HasUsers reports whether any account exists.

func (*Store) InsertResults

func (s *Store) InsertResults(ctx context.Context, edgeID string, results []api.Result) error

InsertResults stores a batch reported by an edge, all or nothing.

func (*Store) LastResultPerEdge added in v1.1.0

func (s *Store) LastResultPerEdge(ctx context.Context) (map[string]time.Time, error)

LastResultPerEdge returns when each edge last reported. An edge that never reported is absent.

func (*Store) LastResultSince added in v1.1.0

func (s *Store) LastResultSince(ctx context.Context, since time.Time) (map[string]time.Time, error)

LastResultSince is LastResultPerEdge restricted to the results after a time, which a database that has run for a year can answer quickly.

func (*Store) ListAudit added in v1.1.0

func (s *Store) ListAudit(ctx context.Context, limit int) ([]AuditEvent, error)

ListAudit returns the latest events, newest first. At most 500 are returned whatever limit asks.

func (*Store) ListChannels added in v1.1.0

func (s *Store) ListChannels(ctx context.Context) ([]Channel, error)

ListChannels returns the webhooks ordered by name; never nil.

func (*Store) ListChecks added in v1.1.0

func (s *Store) ListChecks(ctx context.Context) ([]api.Check, error)

ListChecks returns the checks ordered by id; never nil.

func (*Store) ListEdges

func (s *Store) ListEdges(ctx context.Context) ([]Edge, error)

ListEdges returns every edge, revoked ones included, oldest first.

func (*Store) ListIncidents added in v1.1.0

func (s *Store) ListIncidents(ctx context.Context, openOnly bool, limit int) ([]Incident, error)

ListIncidents returns the latest incidents, newest first, open ones only when asked. At most 500 are returned whatever limit asks.

func (*Store) ListUsers

func (s *Store) ListUsers(ctx context.Context) ([]User, error)

ListUsers returns the accounts ordered by name.

func (*Store) OpenIncident added in v1.1.0

func (s *Store) OpenIncident(ctx context.Context, kind, checkID, edgeID, detail string, at time.Time) (bool, error)

OpenIncident records an incident, unless the same subject already has one open. It reports whether it opened a new one.

func (*Store) OpenIncidents added in v1.1.0

func (s *Store) OpenIncidents(ctx context.Context) ([]Incident, error)

OpenIncidents returns the incidents that are still going on.

func (*Store) PasswordHash added in v1.1.0

func (s *Store) PasswordHash(ctx context.Context, username string) (User, string, error)

PasswordHash returns the account and its stored hash.

func (*Store) PendingNotifications added in v1.1.0

func (s *Store) PendingNotifications(ctx context.Context, since time.Time) ([]Notification, error)

PendingNotifications returns the events the channels were not told of, oldest first: only for incidents started after the channel was added, none older than since, and a resolution only once the opening was told.

func (*Store) Ping

func (s *Store) Ping(ctx context.Context) error

Ping checks that the database answers.

func (*Store) PurgeAudit added in v1.1.0

func (s *Store) PurgeAudit(ctx context.Context, before time.Time) (int64, error)

PurgeAudit deletes the events older than a time and returns how many there were.

func (*Store) PurgeSessions

func (s *Store) PurgeSessions(ctx context.Context) (int64, error)

PurgeSessions deletes the expired sessions and returns how many there were.

func (*Store) RecentOutcomes added in v1.1.0

func (s *Store) RecentOutcomes(ctx context.Context, n int, since time.Time) ([]PairOutcomes, error)

RecentOutcomes returns, for every check on every active edge that reported since the given time, its n latest outcomes.

func (*Store) RecentResults added in v1.1.0

func (s *Store) RecentResults(ctx context.Context, checkID string, limit int) ([]Result, error)

RecentResults returns the latest results of a check, newest first. At most maxRecent are returned whatever limit asks.

func (*Store) RecordAudit added in v1.1.0

func (s *Store) RecordAudit(ctx context.Context, e AuditEvent) error

RecordAudit adds an event to the trail.

func (*Store) RecordDelivery added in v1.1.0

func (s *Store) RecordDelivery(ctx context.Context, incidentID int64, event, channel string, at time.Time) error

RecordDelivery notes that a channel was told of an event.

func (*Store) RemoveChannel added in v1.1.0

func (s *Store) RemoveChannel(ctx context.Context, name string) error

RemoveChannel stops telling a webhook, and forgets what it was told.

func (*Store) RemoveCheck added in v1.1.0

func (s *Store) RemoveCheck(ctx context.Context, id string) error

RemoveCheck stops assigning a check. Its results are kept.

func (*Store) ResolveIncident added in v1.1.0

func (s *Store) ResolveIncident(ctx context.Context, id int64, at time.Time, resolution string) error

ResolveIncident ends an incident that is still open.

func (*Store) Retention added in v1.1.0

func (s *Store) Retention(ctx context.Context) (time.Duration, error)

Retention returns how long results are kept; zero means for ever.

func (*Store) RevokeEdge

func (s *Store) RevokeEdge(ctx context.Context, name string) error

RevokeEdge stops the active edge of that name from authenticating.

func (*Store) SetPasswordHash added in v1.1.0

func (s *Store) SetPasswordHash(ctx context.Context, username, passwordHash string) error

SetPasswordHash replaces the hash and ends every session of the user.

func (*Store) SetRetention added in v1.1.0

func (s *Store) SetRetention(ctx context.Context, d time.Duration) error

SetRetention drops the results older than d, in the background, or keeps them for ever when d is zero.

func (*Store) Summaries added in v1.1.0

func (s *Store) Summaries(ctx context.Context, since time.Time) ([]Summary, error)

Summaries returns one summary per check and edge that reported since the given time.

func (*Store) WithAlertLock added in v1.1.0

func (s *Store) WithAlertLock(ctx context.Context, fn func(context.Context) error) (bool, error)

WithAlertLock runs fn if no other central is evaluating alerts, so that several centrals on one database do not tell everything twice. It reports whether fn ran.

type Summary added in v1.1.0

type Summary struct {
	CheckID   string
	EdgeID    string
	Samples   int
	Succeeded int
	LastAt    time.Time
	LastOK    bool
	LastRTT   float64
	LastError string
	// P95RTT is the 95th percentile of the round-trip time of the successful
	// runs; nil when none succeeded.
	P95RTT *float64
}

Summary is how a check did on an edge over a window, with its latest result.

type User

type User struct {
	Username  string
	Role      string
	CreatedAt time.Time
}

User is an account of the web UI. Its password hash never leaves the store except through PasswordHash.

Directories

Path Synopsis
Package storetest gives tests a throwaway database; tests skip without NETPROBE_TEST_DATABASE_URL.
Package storetest gives tests a throwaway database; tests skip without NETPROBE_TEST_DATABASE_URL.

Jump to

Keyboard shortcuts

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