trip

package
v1.12.2 Latest Latest
Warning

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

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

Documentation

Overview

Package trip is one discover → plan → fire cycle, with nothing in it that belongs to a particular way of being invoked.

It exists because there are now two front ends. The CLI is fired by a person who has seen a bill; the Lambda is fired by an AWS Budgets action, which sees the spend signal itself and does not wait for a cron interval. Both must take exactly the same path — a second implementation of "what gets stopped" is a second thing to get wrong, and the one that only runs at three in the morning during an incident is the one nobody would notice was wrong.

Index

Constants

View Source
const Cooldown = time.Hour

Cooldown is how long after a fire a second trip is refused as a duplicate.

A Budgets action is not delivered once. The same threshold can notify repeatedly, and a retried invocation is the normal case rather than the exceptional one — so without this, the second delivery would discover an account that is already stopped, plan almost nothing, and write a second snapshot whose "prior" state is the stopped one. Restoring that snapshot would put the account back exactly as it was after the first fire: down.

An hour is long enough to cover retries and re-notifications, and short enough that a genuine second incident the same day is not blocked.

Variables

This section is empty.

Functions

func Discover

func Discover(
	ctx context.Context, cfg aws.Config, regions []string,
) ([]model.Resource, map[string]*awsx.Clients, []error)

Discover walks every region in the policy's scope, read-only.

Per-service failures are collected rather than returned: a missing permission on one service should degrade the plan and say so, not leave the operator with nothing during an incident.

func FiredRecently

func FiredRecently(ctx context.Context, st state.Store, now time.Time) (time.Duration, bool)

FiredRecently reports whether any snapshot was fired inside the cooldown.

Read from the state store rather than from anything in the process, because the caller that matters is a Lambda: every delivery is a cold start with no memory of the last one, and the snapshot is the only thing both share.

func Plan

func Plan(
	ctx context.Context, cfg aws.Config, pol policy.Policy, account string, now time.Time,
) (model.Plan, map[string]*awsx.Clients, []error)

Plan discovers and builds, without changing anything.

func PlanID

func PlanID(now time.Time) string

PlanID is the identifier a plan is stored and restored under.

Types

type Options

type Options struct {
	// DryRun plans and reports without changing anything.
	DryRun bool
	// Force applies a plan that carries acknowledgement-required warnings.
	Force bool
	// Now is the clock, injectable for tests.
	Now time.Time
	// SkipCooldown fires even if something was fired inside the window. Only
	// for a human who has decided that is what they want.
	SkipCooldown bool
}

Options are the choices a caller makes about one trip.

type Result

type Result struct {
	Plan      model.Plan
	Fired     bool
	Skipped   string // why nothing was fired, when nothing was
	Changed   int
	Failed    int
	Snapshot  model.Snapshot
	Discovery []error
}

Result is what happened, in the terms a caller reports.

func Fire

func Fire(
	ctx context.Context, cfg aws.Config, pol policy.Policy, account string, st state.Store, log *audit.Log, opt Options,
) (Result, error)

Fire runs the whole cycle. This is the path both front ends take.

Jump to

Keyboard shortcuts

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