commands

package
v0.16.2 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const (
	GroupGettingStarted = "Getting started"
	GroupMonitoring     = "Monitoring your app"
	GroupConfiguring    = "Configuring your app"
	GroupClient         = "Client operations"
	GroupServer         = "Server operations"

	// GroupHidden commands are registered but filtered from help output.
	GroupHidden = "Hidden"
)

Help group constants — used both as the CommandGroup value on registered commands and as the display label in help output.

Every top-level command should be tagged with one of these groups. The TestAllTopLevelCommandsHaveKnownGroup test catches drift.

View Source
const ServiceUsage = "dev.miren.runtime/usage"

ServiceUsage is the cluster-wide resource usage service, served only by the coordinator.

View Source
const (
	Stamp = "Jan _2 03:04:05PM"
)

Variables

View Source
var (
	// ErrNoAutoConfigNeeded indicates that auto-configuration is not needed or not possible
	ErrNoAutoConfigNeeded = errors.New("no auto-configuration needed")
	// ErrAutoConfigFailed indicates that auto-configuration was attempted but failed
	ErrAutoConfigFailed = errors.New("auto-configuration failed")
)
View Source
var ErrAccessDenied = errors.New("access denied")
View Source
var ErrNoConfig = errors.New("no cluster config")

HelpGroupOrder controls the order groups are rendered in top-level help. GroupHidden is intentionally absent — commands in that group are filtered.

View Source
var Meter = spinner.Spinner{
	Frames: []string{
		line("⠋"),
		line("⠙"),
		line("⠹"),
		line("⠸"),
		line("⠼"),
		line("⠴"),
		line("⠦"),
		line("⠧"),
		line("⠇"),
		line("⠏"),
	},
	FPS: time.Second / 10,
}

Meter is the custom spinner animation

Functions

func AddClusterInteractive added in v0.0.3

func AddClusterInteractive(ctx *Context) error

AddClusterInteractive prompts the user to select and add a cluster interactively. It auto-selects the identity if only one is available. Returns nil if a cluster was successfully added.

func AddonCreate added in v0.4.0

func AddonCreate(ctx *Context, opts struct {
	AppCentric
	Spec    string `position:"0" usage:"Addon spec (e.g., miren-postgresql:small)" required:"true"`
	Version string `` /* 134-byte string literal not displayed */
}) error

func AddonDestroy added in v0.4.0

func AddonDestroy(ctx *Context, opts struct {
	AppCentric
	Name  string `position:"0" usage:"Addon name (e.g., miren-postgresql)" required:"true"`
	Force bool   `short:"f" long:"force" description:"Skip confirmation prompt"`
}) error

func AddonList added in v0.4.0

func AddonList(ctx *Context, opts struct {
	FormatOptions
	AppCentric
}) error

func AddonListAvailable added in v0.4.0

func AddonListAvailable(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

func AddonRotate added in v0.12.1

func AddonRotate(ctx *Context, opts struct {
	AppCentric
	Name       string `position:"0" usage:"Addon name (e.g., miren-valkey)" required:"true"`
	Credential string `long:"credential" description:"Which credential to rotate (provider-specific; defaults to the addon's primary credential)"`
	Force      bool   `short:"f" long:"force" description:"Skip confirmation prompt"`
}) error

func AddonVariants added in v0.4.0

func AddonVariants(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
	Addon string `position:"0" usage:"Addon name (e.g., miren-postgresql)" required:"true"`
}) error

func Admin added in v0.3.1

func Admin(ctx *Context, opts struct {
	AppCentric
	List       bool     `long:"list" short:"l" description:"List available admin methods"`
	FuncHelp   bool     `long:"func-help" description:"Show help for a specific admin method"`
	JSON       bool     `long:"json" short:"j" description:"Output as highlighted JSON (default for non-TTY)"`
	Pretty     bool     `long:"pretty" short:"p" description:"Render output in a human-friendly format (default for TTY)"`
	NoValidate bool     `long:"no-validate" description:"Skip method/parameter validation"`
	ParamsFile string   `long:"params-file" short:"f" description:"Read params as JSON from file (use - for stdin)"`
	Method     string   `position:"0" description:"Admin method to call"`
	Params     []string `rest:"true" description:"Method parameters as key=value pairs"`
	Unknown    []string `unknown:"true"`
}) error

func AliasList added in v0.7.0

func AliasList(ctx *Context, opts struct {
	FormatOptions
}) error

func App

func App(ctx *Context, opts struct {
	AppCentric
	FormatOptions
	Watch bool `short:"w" long:"watch" description:"Watch the app stats"`
	Graph bool `short:"g" long:"graph" description:"Graph the app stats"`
}) error

func AppAttach added in v0.14.0

func AppAttach(ctx *Context, opts struct {
	AppCentric

	Run string `position:"0" usage:"Run to attach to" required:"true"`
}) error

AppAttach joins a run that is already going.

Attaching and detaching are invisible to the run: it was started by the controller and outlives any client, so this can be called on a run that was started detached, or called again after a connection drops.

func AppDelete

func AppDelete(ctx *Context, opts struct {
	Force   bool   `short:"f" long:"force" description:"Force delete without confirmation"`
	AppName string `position:"0" usage:"Name of the app to delete"`
	ConfigCentric
}) error

func AppHistory

func AppHistory(ctx *Context, opts struct {
	AppCentric
	FormatOptions

	Limit    int  `short:"n" long:"limit" description:"Maximum number of deployments to show" default:"10"`
	All      bool `long:"all" description:"Show all deployments (ignore limit)"`
	Detailed bool `long:"detailed" description:"Show all columns including git information"`
}) error

func AppList

func AppList(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

func AppRestart added in v0.7.0

func AppRestart(ctx *Context, opts struct {
	Service string `short:"s" long:"service" description:"Restart only a specific service"`
	AppCentric
}) error

func AppRun added in v0.2.0

func AppRun(ctx *Context, opts struct {
	AppCentric

	Task   string `long:"task" description:"Task to run; defaults to the console task"`
	Detach bool   `long:"detach" description:"Create the run without attaching a terminal"`

	Args []string `rest:"true"`
}) error

AppRun creates a run and, unless detached, attaches to it.

The command surface is nearly unchanged: no arguments still opens a shell, arguments still run that command, and the exit code still propagates. What changed underneath is that the invocation now leaves a durable record, which is what makes exit codes retrievable afterwards, --detach possible, and "who shelled into production" answerable.

Once attached, Ctrl-P Ctrl-Q leaves the run running. Ctrl-C is not an exit: it reaches the command as an interrupt, which is what you want when the command is the workload rather than a child of your terminal.

func AppRuns added in v0.14.0

func AppRuns(ctx *Context, opts struct {
	AppCentric
	FormatOptions

	Task  string `long:"task" description:"Only show runs of this task"`
	Limit int    `short:"n" long:"limit" description:"Maximum runs to show"`
}) error

func AppRunsCancel added in v0.14.0

func AppRunsCancel(ctx *Context, opts struct {
	AppCentric

	Run string `position:"0" usage:"Run to cancel" required:"true"`
}) error

func AppSetWorkloadRole added in v0.14.0

func AppSetWorkloadRole(ctx *Context, opts struct {
	AppCentric
	Args []string `rest:"true"`
}) error

func AppStatus

func AppStatus(ctx *Context, opts struct {
	AppCentric
	FormatOptions
}) error

func AppVersions added in v0.8.0

func AppVersions(ctx *Context, opts struct {
	AppCentric
	FormatOptions

	Ephemeral bool `long:"ephemeral" description:"Show only ephemeral versions"`
	Limit     int  `short:"n" long:"limit" description:"Max versions to show" default:"20"`
}) error

func AuthCIAdd added in v0.5.0

func AuthCIAdd(ctx *Context, opts struct {
	GitHub        string `long:"github" description:"GitHub owner/repo shorthand (sets issuer, provider, and repository claim conditions)"`
	Issuer        string `long:"issuer" description:"OIDC issuer URL"`
	Subject       string `long:"subject" description:"Glob pattern for the token subject"`
	AllowedEvents string `long:"allowed-events" description:"Comma-separated event names to allow (default: push,workflow_dispatch)"`
	AllowedRefs   string `long:"allowed-refs" description:"Glob pattern for allowed git refs"`
	Description   string `long:"description" description:"Human-readable description of this binding"`
	AppCentric
}) error

func AuthCIList added in v0.5.0

func AuthCIList(ctx *Context, opts struct {
	AppCentric
}) error

func AuthCIRemove added in v0.5.0

func AuthCIRemove(ctx *Context, opts struct {
	ID string `position:"0" usage:"ID of the CI authentication binding to remove" required:"true"`
	ConfigCentric
}) error

func AuthGenerate

func AuthGenerate(ctx *Context, opts struct {
	DataPath    string `short:"d" long:"data-path" description:"Data path" default:"/var/lib/miren"`
	ConfigPath  string `short:"c" long:"config-path" description:"Path to the config file, - for stdout" default:"clientconfig.yaml"`
	Name        string `short:"n" long:"name" description:"Name of the client certificate" default:"miren-user"`
	Target      string `short:"t" long:"target" description:"Hostname to embed in the config" default:"localhost"`
	ClusterName string `short:"C" long:"cluster-name" description:"Name of the cluster" default:"local"`
	PublicIP    bool   `short:"p" long:"public-ip" description:"Use public IP for the target, if available"`
}) error

func AuthProviderAddGitHub added in v0.9.0

func AuthProviderAddGitHub(ctx *Context, opts struct {
	Name         string   `position:"0" usage:"Name for this identity provider" required:"true"`
	ClientID     string   `long:"client-id" description:"GitHub OAuth app client ID" required:"true"`
	ClientSecret string   `long:"client-secret" description:"GitHub OAuth app client secret" required:"true"`
	Orgs         []string `` /* 183-byte string literal not displayed */
	Update       bool     `long:"update" description:"Overwrite an existing provider with the same name (rotates client secret)"`
	ConfigCentric
}) error

func AuthProviderAddOIDC added in v0.9.0

func AuthProviderAddOIDC(ctx *Context, opts struct {
	Name         string   `position:"0" usage:"Name for this identity provider" required:"true"`
	ProviderURL  string   `long:"provider-url" description:"OIDC provider URL (e.g., https://accounts.google.com)" required:"true"`
	ClientID     string   `long:"client-id" description:"OAuth2 client ID" required:"true"`
	ClientSecret string   `long:"client-secret" description:"OAuth2 client secret" required:"true"`
	Scopes       []string `long:"scope" description:"OAuth2 scopes (can be specified multiple times)"`
	Update       bool     `long:"update" description:"Overwrite an existing provider with the same name (rotates client secret)"`
	ConfigCentric
}) error

func AuthProviderAddPassword added in v0.8.0

func AuthProviderAddPassword(ctx *Context, opts struct {
	Name     string `position:"0" usage:"Name for this password provider" required:"true"`
	Password string `long:"password" description:"Password (omit to prompt interactively, use @file to read from file)"`
	Update   bool   `long:"update" description:"Overwrite an existing provider with the same name (rotates password)"`
	ConfigCentric
}) error

func AuthProviderList added in v0.8.0

func AuthProviderList(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

func AuthProviderRemove added in v0.8.0

func AuthProviderRemove(ctx *Context, opts struct {
	Name  string `position:"0" usage:"Name of the identity provider to remove" required:"true"`
	Force bool   `long:"force" description:"Remove the provider even if it is attached to routes"`
	ConfigCentric
}) error

func AuthProviderShow added in v0.8.0

func AuthProviderShow(ctx *Context, opts struct {
	Name string `position:"0" usage:"Name of the identity provider" required:"true"`
	FormatOptions
	ConfigCentric
}) error

func CheckIfUpgradeNeeded

func CheckIfUpgradeNeeded(ctx context.Context, targetVersion string, force bool, mgrOpts *release.ManagerOptions) (bool, error)

CheckIfUpgradeNeeded checks if target version is newer than current Returns true if upgrade is needed, false if already up to date If mgrOpts is nil, uses default manager options (for server path)

func CheckVersionStatus

func CheckVersionStatus(ctx context.Context, targetVersion string, mgrOpts *release.ManagerOptions) (current, latest release.VersionInfo, err error)

CheckVersionStatus checks if an update is available for the given target version Returns the current and latest version info If mgrOpts is nil, uses default manager options (for server path)

func Cluster

func Cluster(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

Cluster is the default command for the cluster group - shows the list

func ClusterAdd

func ClusterAdd(ctx *Context, opts clusterAddOpts) error

func ClusterAvailable added in v0.15.0

func ClusterAvailable(ctx *Context, opts clusterAvailableOpts) error

ClusterAvailable lists the clusters Miren Cloud has for this account, which is where the name `miren cluster add --cluster` wants comes from.

func ClusterCurrent added in v0.4.0

func ClusterCurrent(ctx *Context, opts struct {
	AppCentric
}) error

func ClusterExportAddress added in v0.5.0

func ClusterExportAddress(ctx *Context, opts struct {
	ConfigCentric
}) error

func ClusterList

func ClusterList(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

ClusterList lists all configured clusters (replaces config info)

func ClusterRemove

func ClusterRemove(ctx *Context, opts struct {
	Cluster string `position:"0" usage:"Name of the cluster to remove"`
	ConfigCentric
}) error

func ClusterRestart added in v0.16.0

func ClusterRestart(ctx *Context, opts struct {
	ConfigCentric
	Yes bool `long:"yes" short:"y" description:"Skip the confirmation prompt"`
}) error

func ClusterSwitch

func ClusterSwitch(ctx *Context, opts struct {
	ConfigCentric
	Cluster string `position:"0" usage:"Name of the cluster to switch to"`
}) error

func ClusterUpgrade added in v0.16.0

func ClusterUpgrade(ctx *Context, opts struct {
	ConfigCentric
	Version        string `short:"V" long:"version" description:"Specific version to upgrade to (e.g., v0.2.0)"`
	Channel        string `long:"channel" description:"Channel to use: 'latest' (stable releases, default) or 'main' (bleeding edge)"`
	Release        bool   `short:"r" long:"release" description:"Upgrade full release package (not just base)"`
	NoAutoRollback bool   `long:"no-auto-rollback" description:"Disable automatic rollback on failure"`
	HealthTimeout  int    `long:"health-timeout" default:"0" description:"Seconds to wait for the restarted server to report ready"`
	Yes            bool   `long:"yes" short:"y" description:"Skip the confirmation prompt"`
}) error

func Colors

func Colors(ctx *Context, opts struct {
}) error

Colors prints the resolved CLI color theme and a swatch of each semantic role. It's a support aid: users on a misdetected terminal can run `miren colors` and paste the output so we can see what was detected and how to override it.

func ConfigInfo

func ConfigInfo(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

func ConfigLoad

func ConfigLoad(ctx *Context, opts struct {
	Config    string `long:"config" description:"Path to the config file to update"`
	Input     string `short:"i" long:"input" description:"Path to the input config file to add" required:"true"`
	Force     bool   `short:"f" long:"force" description:"Force the update"`
	SetActive bool   `short:"a" long:"set-active" description:"Set the active cluster"`
}) error

func CtrNuke

func CtrNuke(c *Context, opts struct {
	Namespace        string `short:"n" long:"namespace" description:"namespace to nuke"`
	Containers       bool   `short:"c" long:"containers" description:"nuke containers only"`
	ContainerdSocket string `long:"containerd-socket" description:"path to containerd socket"`
}) error

func DebugAdvertise added in v0.8.0

func DebugAdvertise(ctx *Context, opts struct {
	FormatOptions
	CloudURL      string   `long:"cloud-url" description:"Cloud URL to use for netcheck (default: https://api.miren.cloud)"`
	SkipNetcheck  bool     `long:"skip-netcheck" description:"Skip the netcheck call and only report interface scan"`
	AdditionalIPs []string `long:"additional-ip" description:"Simulate a server-configured AdditionalIP (repeatable)"`
	ListenAddr    string   `long:"listen" description:"Simulate the server's listen address (default: 0.0.0.0:8443)"`
}) error

DebugAdvertise runs the same advertise-address computation the server uses (coordinate.ComputeAdvertise) and prints a per-candidate explanation plus the final advertised list, so we can debug cases where the server advertises addresses that aren't actually reachable from clients.

func DebugBundle added in v0.3.0

func DebugBundle(ctx *Context, opts struct {
	OutputFile      string `short:"o" long:"output" description:"Output file path" default:"miren-debug.tar.gz"`
	Since           string `short:"s" long:"since" description:"Include logs since this time" default:"1 day ago"`
	Namespace       string `long:"namespace" description:"containerd namespace" default:"miren"`
	Socket          string `long:"socket" description:"path to containerd socket"`
	DockerContainer string `short:"d" long:"docker-container" description:"Docker container name to get logs from" default:"miren"`
}) error

func DebugCloudSync added in v0.15.0

func DebugCloudSync(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

DebugCloudSync reports the runtime side of cloud entity synchronization.

func DebugConnection

func DebugConnection(ctx *Context, opts struct {
	Identity string `short:"i" long:"identity" description:"Identity name to use for authentication"`
	Cluster  string `short:"c" long:"cluster" description:"Cluster name from config to test"`
	Server   string `short:"s" long:"server" description:"Server hostname or IP address to test directly"`
	Insecure bool   `long:"insecure" description:"Skip TLS certificate verification"`
}) error

DebugConnection tests connectivity and authentication with a server

func DebugCtr

func DebugCtr(ctx *Context, opts struct {
	Namespace string   `short:"n" long:"namespace" description:"containerd namespace" default:"miren"`
	Socket    string   `long:"socket" description:"path to containerd socket"`
	Args      []string `rest:"true"`
}) error

func DebugDeployEvents added in v0.16.0

func DebugDeployEvents(ctx *Context, opts struct {
	File       string `position:"0" usage:"JSONL file written by 'miren deploy --format jsonl' (default: stdin)"`
	Timestamps bool   `short:"t" long:"timestamps" description:"Prefix each line with the time elapsed since the first event"`
	BuildLogs  bool   `long:"build-logs" description:"Show the log lines of every build step, not just the steps"`
}) error

DebugDeployEvents renders a `miren deploy --format jsonl` stream back into the readable form a person would have seen, so a log captured by CI or a script can be read without picking through JSON.

func DebugDiskCreate

func DebugDiskCreate(ctx *Context, opts struct {
	ConfigCentric
	Name       string `short:"n" long:"name" description:"Name for the disk" required:"true"`
	Size       int    `short:"s" long:"size" description:"Size of disk in GB" default:"10"`
	Filesystem string `short:"f" long:"filesystem" description:"Filesystem type (ext4, xfs, btrfs)" default:"ext4"`
	CreatedBy  string `short:"c" long:"created-by" description:"Creator ID for the disk"`
	RemoteOnly bool   `short:"r" long:"remote-only" description:"Store disk only in remote storage (no local replica)"`
	VolumeID   string `short:"V" long:"volume-id" description:"Attach to existing volume instead of creating new one"`
}) error

DebugDiskCreate creates a new disk entity for testing

func DebugDiskDelete

func DebugDiskDelete(ctx *Context, opts struct {
	ConfigCentric
	ID string `short:"i" long:"id" description:"Disk ID to delete" required:"true"`
}) error

DebugDiskDelete deletes a disk entity

func DebugDiskLease

func DebugDiskLease(ctx *Context, opts struct {
	ConfigCentric
	DiskID    string `short:"d" long:"disk" description:"Disk ID to lease" required:"true"`
	SandboxID string `short:"s" long:"sandbox" description:"Sandbox ID for the lease"`
	AppID     string `short:"a" long:"app" description:"App ID for the lease"`
	Path      string `short:"p" long:"path" description:"Mount path in sandbox" default:"/data"`
	ReadOnly  bool   `short:"r" long:"readonly" description:"Mount as read-only"`
	Hours     int    `short:"H" long:"hours" description:"Lease duration in hours" default:"2"`
}) error

DebugDiskLease creates a disk lease for testing

func DebugDiskLeaseDelete

func DebugDiskLeaseDelete(ctx *Context, opts struct {
	ConfigCentric
	ID    string `short:"i" long:"id" description:"Lease ID to delete" required:"true"`
	Force bool   `short:"f" long:"force" description:"Force deletion without releasing"`
}) error

DebugDiskLeaseDelete deletes a disk lease entity

func DebugDiskLeaseList

func DebugDiskLeaseList(ctx *Context, opts struct {
	ConfigCentric
	DiskID    string `short:"d" long:"disk" description:"Filter by disk ID"`
	SandboxID string `short:"s" long:"sandbox" description:"Filter by sandbox ID"`
	Status    string `long:"status" description:"Filter by status (pending, bound, released, failed)"`
}) error

DebugDiskLeaseList lists all disk lease entities

func DebugDiskLeaseRelease

func DebugDiskLeaseRelease(ctx *Context, opts struct {
	ConfigCentric
	ID string `short:"i" long:"id" description:"Lease ID to release" required:"true"`
}) error

DebugDiskLeaseRelease releases a disk lease

func DebugDiskLeaseStatus

func DebugDiskLeaseStatus(ctx *Context, opts struct {
	ConfigCentric
	ID string `short:"i" long:"id" description:"Lease ID to check" required:"true"`
}) error

DebugDiskLeaseStatus shows detailed status of a specific disk lease

func DebugDiskList

func DebugDiskList(ctx *Context, opts struct {
	ConfigCentric
}) error

DebugDiskList lists all disk entities

func DebugDiskMounts

func DebugDiskMounts(ctx *Context, opts struct{}) error

DebugDiskMounts lists all mounted runtime-managed disks by reading /proc/mounts

func DebugDiskStatus

func DebugDiskStatus(ctx *Context, opts struct {
	ConfigCentric
	ID string `short:"i" long:"id" description:"Disk ID to check" required:"true"`
}) error

DebugDiskStatus shows the status of a specific disk

func DebugEtcdctl added in v0.14.0

func DebugEtcdctl(ctx *Context, opts debugEtcdctlOptions) error

func DebugNetDBGC added in v0.2.0

func DebugNetDBGC(ctx *Context, opts struct {
	ConfigCentric
	Subnet string `short:"s" long:"subnet" description:"Only GC IPs in this subnet"`
	DryRun bool   `short:"n" long:"dry-run" description:"Show what would be released without making changes"`
	Force  bool   `short:"f" long:"force" description:"Skip confirmation prompt"`
}) error

DebugNetDBGC garbage collects IPs not associated with live sandboxes

func DebugNetDBList added in v0.2.0

func DebugNetDBList(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
	Subnet   string `short:"s" long:"subnet" description:"Filter by subnet CIDR"`
	Reserved bool   `short:"r" long:"reserved" description:"Show only reserved (in-use) IPs"`
	Released bool   `short:"R" long:"released" description:"Show only released IPs"`
}) error

DebugNetDBList lists all IP leases from the netdb

func DebugNetDBRelease added in v0.2.0

func DebugNetDBRelease(ctx *Context, opts struct {
	ConfigCentric
	IP     string `short:"i" long:"ip" description:"Specific IP to release"`
	Subnet string `short:"s" long:"subnet" description:"Release all reserved IPs in subnet"`
	All    bool   `short:"a" long:"all" description:"Release all reserved IPs (use with caution)"`
	Force  bool   `short:"f" long:"force" description:"Skip confirmation prompt"`
}) error

DebugNetDBRelease manually releases IP leases

func DebugNetDBStatus added in v0.2.0

func DebugNetDBStatus(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

DebugNetDBStatus shows subnet utilization stats

func DebugRBAC

func DebugRBAC(ctx *Context, opts struct {
	OutputDir string `short:"d" long:"dir" description:"Registration directory" default:"/var/lib/miren/server"`
	Raw       bool   `short:"r" long:"raw" description:"Show raw JSON response"`
}) error

DebugRBAC fetches and displays the RBAC rules from miren.cloud

func DebugRBACTest

func DebugRBACTest(ctx *Context, opts struct {
	OutputDir string            `short:"d" long:"dir" description:"Registration directory" default:"/var/lib/miren/server"`
	Groups    []string          `short:"g" long:"group" description:"Groups to test with"`
	Tags      map[string]string `short:"t" long:"tag" description:"Tags to test with (key:value)"`
	Resource  string            `short:"r" long:"resource" description:"Resource to test" required:"true"`
	Action    string            `short:"a" long:"action" description:"Action to test" required:"true"`
}) error

DebugRBACTest tests RBAC evaluation locally with fetched rules

func DebugReindex

func DebugReindex(ctx *Context, opts struct {
	ConfigCentric
	DryRun  bool `short:"d" long:"dry-run" description:"Show what would be done without making changes"`
	Confirm bool `short:"y" long:"yes" description:"Skip confirmation prompt"`
}) error

DebugReindex rebuilds all entity indexes from scratch

func DebugSagaList added in v0.14.0

func DebugSagaList(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
	Status     string `short:"s" long:"status" description:"Filter by status (pending, running, undoing, completed, failed)"`
	Definition string `short:"d" long:"definition" description:"Filter by saga definition name"`
	All        bool   `short:"A" long:"all" description:"Include completed and failed sagas"`
}) error

func DebugSagaShow added in v0.14.0

func DebugSagaShow(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
	Id   string `short:"i" long:"id" description:"Saga execution ID"`
	Full bool   `long:"full" description:"Print complete action outputs instead of truncating them (JSON always includes them)"`

	Args []string `rest:"true"`
}) error

func Deploy

func Deploy(ctx *Context, opts deployOpts) error

Deploy runs the deploy and, when asked for a machine-readable format, keeps stdout to that format alone.

With --format json the running commentary goes to stderr and stdout gets one document at the end, emitted on failure too (with a non-zero exit) so a script has one shape to parse either way. With --format jsonl nothing unstructured is printed anywhere: stdout is a stream of JSON lines as the deploy progresses, ending in a "result" line with that same document, and the human text is dropped rather than moved.

func DeployCancel added in v0.3.0

func DeployCancel(ctx *Context, opts struct {
	ConfigCentric
	DeploymentID string `short:"d" long:"deployment" description:"ID of the deployment to cancel" required:"true"`
}) error

func DeployTargetAdd added in v0.16.0

func DeployTargetAdd(ctx *Context, opts deployTargetAddOpts) error

func DeployTargetList added in v0.16.0

func DeployTargetList(ctx *Context, opts deployTargetProjectOpts) error

func DeployTargetRemove added in v0.16.0

func DeployTargetRemove(ctx *Context, opts deployTargetNameOpts) error

func DeployTargetSetDefault added in v0.16.0

func DeployTargetSetDefault(ctx *Context, opts deployTargetNameOpts) error

func DiskBackup added in v0.6.0

func DiskBackup(ctx *Context, opts struct {
	ConfigCentric
	Name     string `short:"n" long:"name" description:"Disk name to backup" required:"true"`
	Output   string `short:"o" long:"output" description:"Output snapshot path (default: DISK-YYYYMMDD-HHMMSS.miren.zst)"`
	DataPath string `long:"data-path" description:"Path to miren data directory" default:"/var/lib/miren"`
	Cloud    bool   `long:"cloud" description:"Also upload the snapshot to miren.cloud as a restore point"`
	Pin      string `long:"pin" description:"Name the uploaded restore point, pinning it against cleanup"`
}) (retErr error)

DiskBackup backs up a disk to a compressed snapshot file.

func DiskListDeleted added in v0.7.0

func DiskListDeleted(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
	DataPath string `long:"data-path" description:"Path to miren data directory" default:"/var/lib/miren"`
}) error

DiskListDeleted lists disks that have been soft-deleted and are available for recovery via disk undelete.

func DiskRestore added in v0.6.0

func DiskRestore(ctx *Context, opts struct {
	ConfigCentric
	Snapshot string `short:"s" long:"snapshot" description:"Path to snapshot file" required:"true"`
	Name     string `short:"n" long:"name" description:"Disk name to restore to (default: original name from snapshot)"`
	DataPath string `long:"data-path" description:"Path to miren data directory" default:"/var/lib/miren"`
	Force    bool   `short:"f" long:"force" description:"Overwrite existing disk image without confirmation"`
}) (retErr error)

DiskRestore restores a disk from a compressed snapshot file.

func DiskUndelete added in v0.7.0

func DiskUndelete(ctx *Context, opts struct {
	ConfigCentric
	Name     string `short:"n" long:"name" description:"Disk name to undelete" required:"true"`
	VolumeID string `short:"V" long:"volume-id" description:"Volume ID to restore (when multiple deleted disks share a name)"`
	DataPath string `long:"data-path" description:"Path to miren data directory" default:"/var/lib/miren"`
}) error

DiskUndelete restores a recently deleted disk from the soft-delete holding area.

func Doctor added in v0.2.0

func Doctor(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

Doctor runs the full diagnostic sweep.

It is deliberately a single command. The previous version printed a three-line summary and then told you to go read three other commands, which made the summary a menu rather than a diagnosis. Everything runs here.

func DownloadRelease

func DownloadRelease(ctx *Context, opts struct {
	Branch string `short:"b" long:"branch" description:"Branch name to download"`
	Global bool   `short:"g" long:"global" description:"Install globally to /var/lib/miren/release"`
	Force  bool   `short:"f" long:"force" description:"Force download even if release directory exists"`
	Output string `short:"o" long:"output" description:"Custom output directory"`
}) error

DownloadRelease is the CLI command handler for downloading a release

func EntityCheck

func EntityCheck(ctx *Context, opts struct {
	Path string `short:"p" long:"path" description:"Path to check"`
}) error

func EntityCreate

func EntityCreate(ctx *Context, opts struct {
	ConfigCentric
	Address string   `short:"a" long:"address" description:"Address to listen on" default:"localhost:8443"`
	Path    []string `short:"p" long:"path" description:"Path to the entity file"`
	Id      string   `short:"i" long:"id" description:"ID of the entity (optional, auto-generated if not provided)"`
	DryRun  bool     `short:"d" long:"dry-run" description:"Dry run, do not actually create the entity"`
}) error

func EntityDelete

func EntityDelete(ctx *Context, opts struct {
	ConfigCentric
	Id      string `short:"i" long:"id" description:"Entity ID" required:"true"`
	Address string `short:"a" long:"address" description:"Address to listen on" default:"localhost:8443"`
}) error

func EntityEnsure

func EntityEnsure(ctx *Context, opts struct {
	ConfigCentric
	Address string   `short:"a" long:"address" description:"Address to listen on" default:"localhost:8443"`
	Path    []string `short:"p" long:"path" description:"Path to the entity file"`
	Id      string   `short:"i" long:"id" description:"ID of the entity (required)" required:"true"`
	DryRun  bool     `short:"d" long:"dry-run" description:"Dry run, do not actually ensure the entity"`
}) error

func EntityGet

func EntityGet(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
	Id     string `short:"i" long:"id" description:"Entity ID" required:"true"`
	Expand bool   `long:"expand" description:"Show nested components in full"`
	// Bounded even though you named this entity: you cannot know it holds a
	// megabyte blob until it is already scrolling past. Roomier than the
	// listing's cap, since you did ask for this one.
	MaxValue int    `long:"max-value-len" description:"Elide values longer than this, 0 for no limit" default:"512"`
	Address  string `short:"a" long:"address" description:"Address to listen on" default:"localhost:8443"`
}) error

func EntityList

func EntityList(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
	Attribute string `short:"a" long:"attribute" description:"Attribute to filter by"`
	Value     string `short:"V" long:"value" description:"Value to filter by"`
	Kind      string `short:"k" long:"kind" description:"Kind of entity to filter by"`
	Limit     int64  `short:"n" long:"limit" description:"Max entities to show, 0 for all" default:"50"`
	After     string `long:"after" description:"Resume from the cursor printed by a previous page"`
	Detail    bool   `short:"l" long:"detail" description:"Show each entity in full instead of one line each"`
	Expand    bool   `long:"expand" description:"Show nested components in full"`
	Columns   string `long:"columns" description:"Comma-separated fields to use as table columns"`
	// A saga's JSON blobs are unbounded in principle and one is enough to bury
	// a listing, so the text view caps them. --json never applies the cap.
	MaxValue int    `long:"max-value-len" description:"Elide values longer than this, 0 for no limit" default:"120"`
	Address  string `long:"address" description:"Address to listen on" default:"localhost:8443"`
}) error

func EntityPatch

func EntityPatch(ctx *Context, opts struct {
	ConfigCentric
	Address  string   `short:"a" long:"address" description:"Address to listen on" default:"localhost:8443"`
	Path     []string `short:"p" long:"path" description:"Path to the entity file with updates"`
	Id       string   `short:"i" long:"id" description:"ID of the entity (required)" required:"true"`
	Revision int64    `short:"r" long:"revision" description:"Expected revision for optimistic concurrency"`
	DryRun   bool     `short:"d" long:"dry-run" description:"Dry run, do not actually patch the entity"`
}) error

func EntityPut

func EntityPut(ctx *Context, opts struct {
	ConfigCentric
	Address string   `short:"a" long:"address" description:"Address to listen on" default:"localhost:8443"`
	Path    []string `short:"p" long:"path" description:"Path to the entity"`
	Id      string   `short:"i" long:"id" description:"ID of the entity"`
	DryRun  bool     `short:"d" long:"dry-run" description:"Dry run, do not actually put the entity"`
	Update  bool     `short:"u" long:"update" description:"Update the entity if it exists"`
}) error

func EntityReplace

func EntityReplace(ctx *Context, opts struct {
	ConfigCentric
	Address  string   `short:"a" long:"address" description:"Address to listen on" default:"localhost:8443"`
	Path     []string `short:"p" long:"path" description:"Path to the entity file"`
	Id       string   `short:"i" long:"id" description:"ID of the entity (required)" required:"true"`
	Revision int64    `short:"r" long:"revision" description:"Expected revision for optimistic concurrency"`
	DryRun   bool     `short:"d" long:"dry-run" description:"Dry run, do not actually replace the entity"`
}) error

func EnvDelete

func EnvDelete(ctx *Context, opts struct {
	Keys    []string `rest:"true" usage:"Environment variable keys to delete" required:"true"`
	Service string   `short:"S" long:"service" description:"Delete env var from specific service only (if not specified, deletes global env var)"`
	Force   bool     `short:"f" long:"force" description:"Skip confirmation prompt"`
	AppCentric
}) error

func EnvGet

func EnvGet(ctx *Context, opts struct {
	Key     string `position:"0" usage:"Environment variable key to get" required:"true"`
	Service string `short:"S" long:"service" description:"Get env var for specific service (if not specified, gets global env var)"`
	Unmask  bool   `short:"u" long:"unmask" description:"Show actual value of sensitive variables instead of masking them"`
	AppCentric
}) error

func EnvList

func EnvList(ctx *Context, opts struct {
	FormatOptions
	AppCentric
}) error

func EnvSet

func EnvSet(ctx *Context, opts struct {
	AppCentric
	Args      []string `rest:"true" usage:"KEY=VALUE pairs to set, the same as passing each with -e"`
	Service   string   `short:"S" long:"service" description:"Set env var for specific service only (if not specified, sets for all services)"`
	Env       []string `` /* 150-byte string literal not displayed */
	Sensitive []string `` /* 179-byte string literal not displayed */
	Backend   string   `` /* 140-byte string literal not displayed */
	Ref       string   `long:"ref" description:"Backend-relative reference to the secret, e.g. payments/stripe-key"`
}) error

func ExpandPath

func ExpandPath(path string) string

func FindReleasePath

func FindReleasePath() string

FindReleasePath looks for an existing miren release directory. It checks the user's home directory first (~/.miren/release), then falls back to the system path (/var/lib/miren/release). Returns empty string if no release directory is found.

func HandleVersionDrift added in v0.8.0

func HandleVersionDrift(ctx context.Context, mgr *release.Manager, serviceName string) (bool, error)

HandleVersionDrift checks whether the running daemon for the given systemd service differs from the binary on disk. If they differ, the service is restarted via mgr (no download, no install) and the function returns true.

This exists because `CheckIfUpgradeNeeded` only compares on-disk binary vs target version. If a previous `miren upgrade` already replaced the on-disk binary, the running daemon is stale even though "current == target". Drift detection catches that case and triggers just the restart.

If the running version can't be determined (service inaccessible, /proc not readable, etc.), we log a note and return (false, nil) rather than forcing a surprise restart.

func IdentityAnchor added in v0.14.0

func IdentityAnchor(ctx *Context, opts IdentityAnchorOptions) error

IdentityAnchor moves where this cluster's workload identity is anchored.

The signing key does not move: it is generated here and stays here under either anchor. What changes is the iss claim in every token minted from now on, and who serves the discovery document verifiers fetch to check them.

Because iss changes, this is a cutover for anything that federates against this cluster — an AWS IAM OIDC provider, a GCP workload identity pool — and each of those has to be repointed at the new issuer. Inside the cluster the move is seamless: the outgoing anchor is recorded so it keeps verifying until the tokens carrying it have expired.

func Init

func Init(ctx *Context, opts struct {
	Name string `short:"n" long:"name" description:"Application name (defaults to directory name)"`
	Dir  string `short:"d" long:"dir" description:"Application directory (defaults to current directory)"`
	ConfigCentric
}) error

func InternalContainerBoot added in v0.16.0

func InternalContainerBoot(ctx *Context, opts struct {
	ReleaseDir   string   `long:"release-dir" description:"Release directory in the data volume" default:"/var/lib/miren/release"`
	LifecycleDir string   `` /* 130-byte string literal not displayed */
	Args         []string `rest:"true"`
}) error

InternalContainerBoot is the container image's entrypoint for `server`. It runs from the image's own binary, decides which binary the volume should boot, and execs it with the arguments it was given. Exec, not spawn: the server must stay tini's direct child so signals and exit codes reach it the way they do today.

func InternalContainerWatchdog added in v0.16.0

func InternalContainerWatchdog(ctx *Context, opts struct {
	Operation    string `long:"operation" required:"true" description:"Upgrade operation to watch"`
	ServerPID    int    `long:"server-pid" required:"true" description:"PID of the server this boot runs"`
	ReleaseDir   string `long:"release-dir" description:"Release directory in the data volume" default:"/var/lib/miren/release"`
	LifecycleDir string `long:"lifecycle-dir" description:"Operation ledger" default:"/var/lib/miren/server/lifecycle"`
	Detached     bool   `long:"detached" description:"Run the watchdog in this process (set by the first invocation)"`
}) error

InternalContainerWatchdog runs the watchdog for one boot of an upgraded build; see containerboot.Watchdog. Started by container-boot right before it execs the server.

It runs detached: the first invocation starts a second copy of itself and returns, so the watchdog ends up a child of tini rather than of the server, where it would sit as a zombie until the server exits.

func InternalRecordExit added in v0.16.0

func InternalRecordExit(ctx *Context, opts struct {
	Unit   string `long:"unit" description:"systemd unit whose exit is being recorded" default:"miren.service"`
	Output string `long:"output" description:"Directory to write the exit record to" default:"/var/lib/miren/server"`
}) error

InternalRecordExit is the ExecStopPost hook in the managed resource-limit drop-in. systemd runs it after the main process is gone, which is the only moment the reason for the stop is readable — see pkg/exitrecord.

It never returns an error. A failure here would make systemd report the unit as failing to stop, which is a worse outcome than losing one diagnostic record. Problems go to stderr instead, which the unit routes to the journal.

func LoadLocalAppConfig added in v0.16.0

func LoadLocalAppConfig() (*appconfig.AppConfig, error)

LoadLocalAppConfig returns the app config from the working directory, or (nil, nil) when there isn't one. A load error is returned without being printed; callers that carry on regardless should call WarnLocalAppConfig.

func Login

func Login(ctx *Context, opts struct {
	CloudURL      string `short:"u" long:"url" description:"Cloud URL" default:"https://miren.cloud"`
	IdentityName  string `short:"i" long:"identity" description:"Name for this identity in config" default:"cloud"`
	KeyName       string `short:"k" long:"key-name" description:"Name for the authentication key" default:"miren-cli"`
	NoSave        bool   `long:"no-save" description:"Don't save credentials to config file"`
	Force         bool   `short:"f" long:"force" description:"Overwrite existing identity without prompting"`
	PersistentKey bool   `long:"persistent-key" description:"Register a persistent key instead of the default renewable token login"`
}) error

Login authenticates with miren.cloud using device flow

func LoginWithDefaults added in v0.2.1

func LoginWithDefaults(ctx *Context) error

LoginWithDefaults runs the login flow with default settings

func Logout

func Logout(ctx *Context, opts struct {
	ConfigCentric
	IdentityName string `short:"i" long:"identity" description:"Name of the identity to remove"`
}) error

Logout removes the local identity and key files

func LogsApp added in v0.5.0

func LogsApp(ctx *Context, opts struct {
	AppCentric
	FormatOptions

	Last    *time.Duration `short:"l" long:"last" description:"Show logs from the last duration"`
	Since   string         `long:"since" description:"Show logs since a time (RFC3339, '2006-01-02 15:04', or a duration like '2h' ago)"`
	Until   string         `` /* 134-byte string literal not displayed */
	Follow  bool           `short:"f" long:"follow" description:"Follow log output (live tail)"`
	Filter  string         `short:"g" long:"grep" description:"Filter logs (e.g., 'error', '\"exact phrase\"', 'error -debug', '/regex/')"`
	Service string         `long:"service" description:"Filter logs by service name (e.g., 'web', 'worker')"`
}) error

LogsApp shows application logs. This is the default subcommand for `miren logs`.

func LogsBuild added in v0.5.0

func LogsBuild(ctx *Context, opts struct {
	AppCentric
	FormatOptions

	Version string         `position:"0" usage:"Build version (e.g., v3)" required:"true"`
	Last    *time.Duration `short:"l" long:"last" description:"Show logs from the last duration"`
	Since   string         `long:"since" description:"Show logs since a time (RFC3339, '2006-01-02 15:04', or a duration like '2h' ago)"`
	Until   string         `` /* 134-byte string literal not displayed */
	Follow  bool           `short:"f" long:"follow" description:"Follow log output (live tail)"`
	Filter  string         `short:"g" long:"grep" description:"Filter logs (e.g., 'error', '\"exact phrase\"', 'error -debug', '/regex/')"`
}) error

LogsBuild shows build logs for a specific version.

func LogsRun added in v0.14.0

func LogsRun(ctx *Context, opts struct {
	AppCentric
	FormatOptions

	Run    string         `position:"0" usage:"Run ID" required:"true"`
	Last   *time.Duration `short:"l" long:"last" description:"Show logs from the last duration"`
	Since  string         `long:"since" description:"Show logs since a time (RFC3339, '2006-01-02 15:04', or a duration like '2h' ago)"`
	Until  string         `` /* 134-byte string literal not displayed */
	Follow bool           `short:"f" long:"follow" description:"Follow log output (live tail)"`
	Filter string         `short:"g" long:"grep" description:"Filter logs (e.g., 'error', '\"exact phrase\"', 'error -debug', '/regex/')"`
}) error

LogsRun reads back one run's output.

It joins the logs family rather than hanging off `miren app runs`, because `miren app runs logs` is a double plural sitting one character away from `miren app run` -- the wrong direction to typo.

func LogsSandbox added in v0.5.0

func LogsSandbox(ctx *Context, opts struct {
	ConfigCentric
	FormatOptions

	SandboxID string         `position:"0" usage:"Sandbox ID" required:"true"`
	Last      *time.Duration `short:"l" long:"last" description:"Show logs from the last duration"`
	Since     string         `long:"since" description:"Show logs since a time (RFC3339, '2006-01-02 15:04', or a duration like '2h' ago)"`
	Until     string         `` /* 134-byte string literal not displayed */
	Follow    bool           `short:"f" long:"follow" description:"Follow log output (live tail)"`
	Filter    string         `short:"g" long:"grep" description:"Filter logs (e.g., 'error', '\"exact phrase\"', 'error -debug', '/regex/')"`
}) error

LogsSandbox shows logs for a specific sandbox.

func LogsSystem added in v0.5.0

func LogsSystem(ctx *Context, opts struct {
	ConfigCentric
	FormatOptions

	Component string         `position:"0" usage:"System component to filter by (e.g., 'etcd', 'scheduler')"`
	Last      *time.Duration `short:"l" long:"last" description:"Show logs from the last duration"`
	Since     string         `long:"since" description:"Show logs since a time (RFC3339, '2006-01-02 15:04', or a duration like '2h' ago)"`
	Until     string         `` /* 134-byte string literal not displayed */
	Follow    bool           `short:"f" long:"follow" description:"Follow log output (live tail)"`
	Filter    string         `short:"g" long:"grep" description:"Filter logs (e.g., 'error', '\"exact phrase\"', 'error -debug', '/regex/')"`
}) error

LogsSystem shows system/server logs, optionally filtered by component.

func MinuteLabeler

func MinuteLabeler(i int, v float64) string

func PerformDownloadRelease

func PerformDownloadRelease(ctx *Context, opts DownloadReleaseOptions) error

PerformDownloadRelease performs the actual download with the given options

func PrintJSON

func PrintJSON(data any) error

PrintJSON prints data as formatted JSON to stdout

func PrintJSONTo

func PrintJSONTo(w io.Writer, data any) error

PrintJSONTo prints JSON to the given writer with pretty formatting.

func PrintRunningVersionDrift added in v0.8.0

func PrintRunningVersionDrift(serviceName string, onDisk release.VersionInfo) bool

PrintRunningVersionDrift prints an additional line about the running daemon when its version differs from the on-disk binary. Used by --check paths to surface drift without trying to upgrade. Returns true when drift was reported, so callers can adjust their conclusion text.

func PrintUpgradeSuccess

func PrintUpgradeSuccess(ctx context.Context, oldVersion release.VersionInfo, commandType string, mgrOpts *release.ManagerOptions)

PrintUpgradeSuccess prints a formatted success message after upgrade If mgrOpts is nil, uses default manager options (for server path)

func PrintVersionComparison

func PrintVersionComparison(current, latest release.VersionInfo)

PrintVersionComparison prints a formatted comparison of current vs latest versions

func Register

func Register(ctx *Context, opts RegisterOptions) error

Register handles cluster registration with miren.cloud

func RegisterAll added in v0.3.0

func RegisterAll(d *mflags.Dispatcher)

func RegisterStandalone added in v0.9.0

func RegisterStandalone(ctx *Context, opts RegisterOptions) error

RegisterStandalone is the CLI entrypoint for `miren server register`. It runs Register and then bounces the local miren.service if one is active, so the user doesn't have to restart manually. The install paths call Register directly because they own the service lifecycle themselves.

func RegisterStatus

func RegisterStatus(ctx *Context, opts struct {
	Dir string `short:"d" long:"dir" description:"Registration directory" default:"/var/lib/miren/server"`
}) error

RegisterStatus displays the current registration status

func RenderTopLevelHelp added in v0.8.0

func RenderTopLevelHelp(d *mflags.Dispatcher)

RenderTopLevelHelp renders grouped help output for the top-level command list. Commands are rendered in the order defined by HelpGroupOrder. Commands in GroupHidden are filtered out.

func Rollback added in v0.4.0

func Rollback(ctx *Context, opts struct {
	AppCentric
}) error

func Route

func Route(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

Route is the default command for the route group - shows the list

func RouteDown added in v0.14.0

func RouteDown(ctx *Context, opts struct {
	Host    string `position:"0" usage:"Hostname for the route (e.g., example.com); omit and pass --default for the default route"`
	Default bool   `long:"default" description:"Take the default route down (instead of a hostname)"`
	Reason  string `long:"reason" description:"Explanation shown to visitors on the holding page"`
	BackAt  string `` /* 147-byte string literal not displayed */
	Yes     bool   `long:"yes" short:"y" description:"Skip the confirmation prompt for --default"`
	FormatOptions
	ConfigCentric
}) error

func RouteList

func RouteList(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

func RouteProtect added in v0.8.0

func RouteProtect(ctx *Context, opts struct {
	Host        string   `position:"0" usage:"Hostname for the route (e.g., example.com); omit and pass --default for the default route"`
	Default     bool     `long:"default" description:"Protect the default route (instead of a hostname)"`
	Provider    string   `long:"provider" description:"Name of the identity provider" required:"true"`
	ClaimHeader []string `long:"claim-header" description:"Claim to header mapping in format 'claim:header' (e.g., 'email:X-User-Email')"`
	FormatOptions
	ConfigCentric
}) error

func RouteRemove

func RouteRemove(ctx *Context, opts struct {
	Host string `position:"0" usage:"Hostname of the route to remove"`
	ConfigCentric
}) error

func RouteSet

func RouteSet(ctx *Context, opts struct {
	Host    string `position:"0" usage:"Hostname for the route (e.g., example.com or *.example.com)" required:"true"`
	AppName string `position:"1" usage:"Application name to route to"`
	Service string `long:"service" description:"HTTP-capable app service to route to" default:"web"`
	ConfigCentric
}) error

func RouteSetDefault

func RouteSetDefault(ctx *Context, opts struct {
	AppName string `position:"0" usage:"Application name to set as default route"`
	ConfigCentric
}) error

func RouteShow

func RouteShow(ctx *Context, opts struct {
	Host    string `position:"0" usage:"Hostname of the route to show; omit and pass --default for the default route"`
	Default bool   `long:"default" description:"Show the default route (instead of a hostname)"`
	FormatOptions
	ConfigCentric
}) error

func RouteTLSCheck added in v0.16.0

func RouteTLSCheck(ctx *Context, opts struct {
	Host  string `position:"0" usage:"Hostname for the route (e.g., *.example.com)"`
	Path  string `position:"1" usage:"Path on the app to ask before issuing a certificate (e.g., /tls-check); omit to show the current value"`
	Clear bool   `long:"clear" description:"Remove the check so names under the route only get certificates as live ephemeral deploys"`
	FormatOptions
	ConfigCentric
}) error

func RouteTimeout added in v0.14.0

func RouteTimeout(ctx *Context, opts struct {
	Host    string `position:"0" usage:"Hostname for the route (e.g., example.com); omit and pass --default for the default route"`
	Timeout string `position:"1" usage:"Request timeout as a duration (e.g., 10m, 300s); omit to show the current value"`
	Default bool   `long:"default" description:"Apply to the default route (instead of a hostname)"`
	Clear   bool   `long:"clear" description:"Remove the override so the route uses the server default"`
	FormatOptions
	ConfigCentric
}) error

func RouteUnprotect added in v0.8.0

func RouteUnprotect(ctx *Context, opts struct {
	Host    string `position:"0" usage:"Hostname for the route (e.g., example.com); omit and pass --default for the default route"`
	Default bool   `long:"default" description:"Remove protection from the default route (instead of a hostname)"`
	ConfigCentric
}) error

func RouteUnsetDefault

func RouteUnsetDefault(ctx *Context, opts struct {
	ConfigCentric
}) error

func RouteUp added in v0.14.0

func RouteUp(ctx *Context, opts struct {
	Host    string `position:"0" usage:"Hostname for the route (e.g., example.com); omit and pass --default for the default route"`
	Default bool   `long:"default" description:"Bring the default route back (instead of a hostname)"`
	FormatOptions
	ConfigCentric
}) error

func RouteWaf added in v0.8.0

func RouteWaf(ctx *Context, opts struct {
	Host    string `position:"0" usage:"Hostname for the route (e.g., example.com); omit and pass --default for the default route"`
	Default bool   `long:"default" description:"Apply to the default route (instead of a hostname)"`
	Level   int    `long:"level" description:"OWASP CRS paranoia level (1-4)" default:"1"`
	Disable bool   `long:"disable" description:"Disable WAF on the route"`
	FormatOptions
	ConfigCentric
}) error

func RunnerCordon added in v0.11.0

func RunnerCordon(ctx *Context, opts struct {
	ConfigCentric

	Reason string `long:"reason" description:"Optional reason for cordoning the runner"`
	Node   string `position:"0" usage:"Runner to cordon (name, ID, or short ID)" required:"true"`
}) error

func RunnerDrain added in v0.11.0

func RunnerDrain(ctx *Context, opts struct {
	ConfigCentric

	Timeout int64  `long:"timeout" description:"Max seconds to wait for the node to empty (0 uses the server default)"`
	Reason  string `long:"reason" description:"Optional reason for draining the runner"`
	Node    string `position:"0" usage:"Runner to drain (name, ID, or short ID)" required:"true"`
}) error

func RunnerInstall added in v0.7.0

func RunnerInstall(ctx *Context, opts struct {
	Token           string   `short:"t" long:"token" description:"Enrollment token from 'miren runner token create'"`
	Coordinator     string   `short:"c" long:"coordinator" description:"Override coordinator address from the token"`
	Name            string   `long:"name" description:"Human-readable name for this runner (defaults to hostname)"`
	ListenAddr      string   `short:"l" long:"listen" description:"Address this runner will listen on"`
	Labels          []string `long:"labels" description:"Runner labels (key=value)"`
	Branch          string   `short:"b" long:"branch" description:"Branch to download"`
	Force           bool     `short:"f" long:"force" description:"Overwrite existing service file"`
	NoStart         bool     `long:"no-start" description:"Do not start the service after installation"`
	SkipSystemCheck bool     `long:"skip-system-check" description:"Skip minimum system requirements check"`
	ConfigPath      string   `long:"config" description:"Path to runner config" default:"/var/lib/miren/runner/config.yaml"`
	DataPath        string   `long:"data-path" description:"Path to store runner data" default:"/var/lib/miren/runner"`
}) error

RunnerInstall sets up a systemd unit to run a miren distributed runner. It handles the full provisioning flow: downloading the release bundle, joining a coordinator (interactively or via flags), creating the systemd service, and enabling it.

func RunnerJoin added in v0.3.1

func RunnerJoin(ctx *Context, opts struct {
	Coordinator string   `short:"c" long:"coordinator" description:"Override coordinator address from the token"`
	Token       string   `long:"token" description:"Enrollment token (or pass as positional arg / via stdin)"`
	ListenAddr  string   `short:"l" long:"listen" description:"Address this runner will listen on"`
	Name        string   `long:"name" description:"Human-readable name for this runner (defaults to hostname)"`
	Labels      []string `long:"labels" description:"Additional labels for the runner (key=value)"`
	ConfigPath  string   `long:"config" description:"Path to save runner config" default:"/var/lib/miren/runner/config.yaml"`
	RunnerID    string   `long:"runner-id" description:"Specific runner ID to use (for reconnecting)"`

	TokenArg string `position:"0" usage:"Join token from 'miren runner token create'"`
}) error

func RunnerList added in v0.3.1

func RunnerList(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

func RunnerOperationsAbandon added in v0.16.0

func RunnerOperationsAbandon(ctx *Context, opts struct {
	Dir string `long:"dir" description:"Operation directory" default:"/var/lib/miren/runner/lifecycle"`
	ID  string `position:"0" usage:"Operation id" required:"true"`
}) error

RunnerOperationsAbandon ends an operation nobody will finish, such as an executor that died mid-operation. A runner has no data restore to settle.

func RunnerOperationsList added in v0.16.0

func RunnerOperationsList(ctx *Context, opts struct {
	FormatOptions
	Dir string `long:"dir" description:"Operation directory" default:"/var/lib/miren/runner/lifecycle"`
}) error

func RunnerOperationsRun added in v0.16.0

func RunnerOperationsRun(ctx *Context, opts struct {
	Operation string `long:"operation" required:"true" description:"Operation id to execute or resume"`
	Dir       string `long:"dir" description:"Operation directory" default:"/var/lib/miren/runner/lifecycle"`
	Config    string `` /* 130-byte string literal not displayed */
}) error

RunnerOperationsRun is the executor entry point the transient systemd unit invokes for a runner operation.

func RunnerOperationsShow added in v0.16.0

func RunnerOperationsShow(ctx *Context, opts struct {
	FormatOptions
	Dir string `long:"dir" description:"Operation directory" default:"/var/lib/miren/runner/lifecycle"`
	ID  string `position:"0" usage:"Operation id" required:"true"`
}) error

func RunnerReissue added in v0.12.0

func RunnerReissue(ctx *Context, opts struct {
	Coordinator string `short:"c" long:"coordinator" description:"Override coordinator address (defaults to the runner config)"`
	ListenAddr  string `short:"l" long:"listen" description:"Address this runner listens on (covered by the new cert; auto-discovered if unset)"`
	ConfigPath  string `long:"config" description:"Path to the runner config" default:"/var/lib/miren/runner/config.yaml"`
}) error

RunnerReissue rotates the runner's client certificate in place. It authenticates to the coordinator with the runner's existing certificate and asks for a fresh one (new key, same identity and CommonName), then writes only the credential material back to the config. Use it to rotate credentials on demand, for hygiene or in response to a suspected key compromise, without a full re-join: the runner keeps its identity and its sandbox schedules stay bound to the same node.

The on-disk certificate must still be valid, because it is the authentication. A runner whose certificate has expired or is otherwise unusable can't be rotated this way and should be re-provisioned with `runner remove` followed by `runner join --runner-id <id>`, which re-establishes the same identity from a fresh join token.

func RunnerRemove added in v0.7.0

func RunnerRemove(ctx *Context, opts struct {
	ConfigCentric

	Force bool   `long:"force" short:"f" description:"Force removal even if the runner has active sandboxes"`
	Node  string `position:"0" usage:"Runner to remove (name, ID, or short ID)" required:"true"`
}) error

func RunnerServiceStatus added in v0.7.0

func RunnerServiceStatus(ctx *Context, opts struct {
	Follow bool `short:"f" long:"follow" description:"Follow logs in real-time"`
}) error

RunnerServiceStatus shows the status of the miren-runner systemd service. This is separate from RunnerStatus which shows runner health via RPC.

func RunnerStart added in v0.4.0

func RunnerStart(ctx *Context, opts struct {
	ConfigPath       string `long:"config" description:"Path to runner config" default:"/var/lib/miren/runner/config.yaml"`
	DataPath         string `long:"data-path" description:"Path to store runner data" default:"/var/lib/miren/runner"`
	ContainerdSocket string `long:"containerd-socket" description:"Path to containerd socket"`
	ListenAddr       string `short:"l" long:"listen" description:"Address this runner will listen on (overrides config)"`
}) error

func RunnerStatus added in v0.7.0

func RunnerStatus(ctx *Context, opts struct {
	ConfigPath string `long:"config" description:"Path to runner config" default:"/var/lib/miren/runner/config.yaml"`
	DataPath   string `long:"data-path" description:"Path to runner data" default:"/var/lib/miren/runner"`
}) error

func RunnerTokenCreate added in v0.7.0

func RunnerTokenCreate(ctx *Context, opts struct {
	ConfigCentric

	Labels   []string `short:"l" long:"labels" description:"Labels to apply to the runner (key=value format)"`
	Expires  int      `short:"e" long:"expires" default:"1" description:"Hours until the invite expires"`
	Reusable bool     `short:"r" long:"reusable" description:"Create a reusable invite (not consumed on use)"`
	Name     string   `short:"n" long:"name" description:"Human-readable name for this invite"`
	TTL      string   `long:"ttl" description:"Time-to-live (e.g. 24h, 7d, 2w). Overrides --expires"`
	Addr     string   `short:"a" long:"addr" description:"Override coordinator address baked into the token"`
}) error

func RunnerTokenList added in v0.7.0

func RunnerTokenList(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

func RunnerTokenRevoke added in v0.7.0

func RunnerTokenRevoke(ctx *Context, opts struct {
	ConfigCentric

	TokenID string `position:"0" usage:"ID of the token to revoke" required:"true"`
}) error

func RunnerUncordon added in v0.11.0

func RunnerUncordon(ctx *Context, opts struct {
	ConfigCentric

	Node string `position:"0" usage:"Runner to uncordon (name, ID, or short ID)" required:"true"`
}) error

func RunnerUninstall added in v0.7.0

func RunnerUninstall(ctx *Context, opts struct {
	RemoveData bool   `long:"remove-data" description:"Remove runner data directory"`
	DataPath   string `long:"data-path" description:"Path to runner data" default:"/var/lib/miren/runner"`
}) error

RunnerUninstall removes the miren-runner systemd service.

func RunnerUpgrade added in v0.7.0

func RunnerUpgrade(ctx *Context, opts struct {
	Version        string `short:"V" long:"version" description:"Specific version to upgrade to (e.g., v0.2.0); default is the coordinator's build"`
	Channel        string `` /* 133-byte string literal not displayed */
	Check          bool   `short:"c" long:"check" description:"Check for available updates only"`
	Force          bool   `short:"f" long:"force" description:"Force upgrade even if already up to date"`
	SkipHealth     bool   `long:"skip-health" description:"Deprecated: readiness is always verified"`
	NoAutoRollback bool   `long:"no-auto-rollback" description:"Disable automatic rollback on failure"`
	HealthTimeout  int    `long:"health-timeout" default:"0" description:"Seconds to wait for the restarted runner to report ready"`
}) error

RunnerUpgrade is kept for existing scripts; it runs the same operation `miren upgrade` does on a runner host, with a nudge.

func RunnerUpgradeRollback added in v0.7.0

func RunnerUpgradeRollback(ctx *Context, opts struct {
	SkipHealth bool `long:"skip-health" description:"Skip health check after rollback"`
}) error

RunnerUpgradeRollback rolls back the runner to the previous version

func SandboxDelete

func SandboxDelete(ctx *Context, opts struct {
	Force     bool   `short:"f" long:"force" description:"Force delete without confirmation"`
	SandboxID string `position:"0" usage:"ID of the sandbox to delete" required:"true"`
	ConfigCentric
}) error

func SandboxExec

func SandboxExec(ctx *Context, opts sandboxExecOptions) error

func SandboxInspect added in v0.15.0

func SandboxInspect(ctx *Context, opts struct {
	Sandbox string `position:"0" usage:"ID or short ID of the sandbox to inspect" required:"true"`

	Since  string `long:"since" description:"Measure over this window, e.g. 30s, 5m, 1h (default 1m)"`
	Series bool   `long:"series" description:"Include CPU and memory history"`

	FormatOptions
	ConfigCentric
}) error

SandboxInspect reports one sandbox in detail: what it is using, what it runs, and why it has been failing if it has.

This is the last step before reading logs. A listing says which sandbox is hot; this says whether that is normal for it, and whether the pool behind it has given up replacing it.

func SandboxList

func SandboxList(ctx *Context, opts struct {
	All     bool   `short:"a" long:"all" description:"Include dead sandboxes (excluded by default)"`
	Status  string `short:"s" long:"status" description:"Filter by status (pending, not_ready, running, stopped, dead)"`
	App     string `long:"app" description:"Only show sandboxes belonging to this app"`
	Service string `long:"service" description:"Only show sandboxes of this service (e.g. web, worker)"`
	FormatOptions
	ConfigCentric
}) error

func SandboxPoolList

func SandboxPoolList(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

func SandboxPoolSetDesired

func SandboxPoolSetDesired(ctx *Context, opts struct {
	RawID   bool   `long:"raw-id" description:"Use the provided ID as-is without adding the pool/ prefix"`
	PoolID  string `position:"0" usage:"Pool ID (e.g., pool-CUSkT8J58BmgkDeGyPP2e or pool/pool-CUSkT8J58BmgkDeGyPP2e)" required:"true"`
	Desired string `position:"1" usage:"Desired instance count (absolute number, +N to increase, or -N to decrease)" required:"true"`
	ConfigCentric
}) error

func SandboxStop

func SandboxStop(ctx *Context, opts struct {
	SandboxID string `position:"0" usage:"ID of the sandbox to stop" required:"true"`
	ConfigCentric
}) error

func SecretDestroy added in v0.14.0

func SecretDestroy(ctx *Context, opts struct {
	ConfigCentric
	Ref     string `position:"0" usage:"Reference naming a version, e.g. payments/stripe-key@x1A" required:"true"`
	Backend string `short:"b" long:"backend" description:"Backend instance holding the secret (default: cluster)"`
	Force   bool   `short:"f" long:"force" description:"Skip the confirmation prompt"`
}) error

func SecretDisable added in v0.14.0

func SecretDisable(ctx *Context, opts struct {
	ConfigCentric
	Ref     string `position:"0" usage:"Reference naming a version, e.g. payments/stripe-key@x1A" required:"true"`
	Backend string `short:"b" long:"backend" description:"Backend instance holding the secret (default: cluster)"`
}) error

func SecretEnable added in v0.14.0

func SecretEnable(ctx *Context, opts struct {
	ConfigCentric
	Ref     string `position:"0" usage:"Reference naming a version, e.g. payments/stripe-key@x1A" required:"true"`
	Backend string `short:"b" long:"backend" description:"Backend instance holding the secret (default: cluster)"`
}) error

func SecretKeyring added in v0.14.0

func SecretKeyring(ctx *Context, opts struct {
	ConfigCentric
	FormatOptions
}) error

func SecretList added in v0.14.0

func SecretList(ctx *Context, opts struct {
	ConfigCentric
	FormatOptions
	Backend string `short:"b" long:"backend" description:"Backend instance to list (default: cluster)"`
}) error

func SecretRotateKey added in v0.14.0

func SecretRotateKey(ctx *Context, opts struct {
	ConfigCentric
}) error

func SecretSet added in v0.14.0

func SecretSet(ctx *Context, opts struct {
	ConfigCentric
	Path    string `position:"0" usage:"Secret path, e.g. payments/stripe-key" required:"true"`
	Backend string `short:"b" long:"backend" description:"Backend instance to store into (default: cluster)"`
	Value   string `` /* 203-byte string literal not displayed */
}) error

func SecretVersions added in v0.14.0

func SecretVersions(ctx *Context, opts struct {
	ConfigCentric
	FormatOptions
	Path    string `position:"0" usage:"Secret path, e.g. payments/stripe-key" required:"true"`
	Backend string `short:"b" long:"backend" description:"Backend instance to read (default: cluster)"`
}) error

func Section

func Section(name, desc, help string, opts ...SectionOption) mflags.Command

func Server

func Server(ctx *Context, opts serverconfig.CLIFlags) error

func ServerConfigGenerate

func ServerConfigGenerate(ctx *Context, opts struct {
	Output   string `short:"o" long:"output" description:"Output file path (defaults to stdout)"`
	Mode     string `short:"m" long:"mode" description:"Server mode: standalone (default), distributed (experimental)" default:"standalone"`
	Defaults bool   `short:"d" long:"defaults" description:"Generate config with default values"`
}) error

ServerConfigGenerate generates a server configuration file

func ServerConfigValidate

func ServerConfigValidate(ctx *Context, opts struct {
	ConfigFile string `short:"f" long:"file" description:"Configuration file to validate" required:"true"`
}) error

ServerConfigValidate validates a server configuration file

func ServerInstall

func ServerInstall(ctx *Context, opts struct {
	Address         string            `short:"a" long:"address" description:"Server address to bind to" default:"0.0.0.0:8443"`
	Verbosity       string            `long:"verbosity" description:"Extra verbosity to bake into the unit (e.g. -v); the server defaults to Info without it"`
	Branch          string            `short:"b" long:"branch" description:"Branch to download if release not found"`
	Force           bool              `short:"f" long:"force" description:"Overwrite existing service file"`
	NoStart         bool              `long:"no-start" description:"Do not start the service after installation"`
	WithoutCloud    bool              `long:"without-cloud" description:"Skip cloud registration setup"`
	ClusterName     string            `short:"n" long:"name" description:"Cluster name for cloud registration"`
	CloudURL        string            `short:"u" long:"url" description:"Cloud URL for registration" default:"https://miren.cloud"`
	Tags            map[string]string `short:"t" long:"tag" description:"Tags for the cluster (key:value)"`
	SkipSystemCheck bool              `long:"skip-system-check" description:"Skip minimum system requirements check"`
	EnrollToken     string            `long:"enroll-token" description:"Unattended enroll token from miren.cloud (registers without browser approval)"`
}) error

ServerInstall sets up systemd units to run the miren server

func ServerInstallContainer added in v0.11.1

func ServerInstallContainer(ctx *Context, opts struct {
	Image         string            `short:"i" long:"image" description:"Container image to use (full reference; mutually exclusive with --version)"`
	Version       string            `` /* 183-byte string literal not displayed */
	Name          string            `short:"n" long:"name" description:"Container name"`
	Runtime       string            `long:"runtime" description:"Container runtime to use: docker or podman (auto-detected by default, preferring docker)"`
	Force         bool              `short:"f" long:"force" description:"Remove existing container if present"`
	AllowRootless bool              `long:"allow-rootless" description:"Install even on a rootless runtime (control plane only; app workloads won't run)"`
	HTTPPort      int               `long:"http-port" description:"HTTP port mapping" default:"80"`
	IngressMode   string            `` /* 265-byte string literal not displayed */
	HostNetwork   bool              `long:"host-network" description:"Use host networking (ignores port mappings)"`
	WithoutCloud  bool              `long:"without-cloud" description:"Skip cloud registration setup"`
	ClusterName   string            `long:"cluster-name" description:"Cluster name for cloud registration"`
	CloudURL      string            `short:"u" long:"url" description:"Cloud URL for registration" default:"https://miren.cloud"`
	Tags          map[string]string `short:"t" long:"tag" description:"Tags for the cluster (key:value)"`
	Labs          []string          `short:"l" long:"labs" description:"Miren Labs features to enable. Prefix with - to disable."`
}) error

ServerInstallContainer sets up a container (via Docker or Podman) to run the miren server.

func ServerOperationsAbandon added in v0.16.0

func ServerOperationsAbandon(ctx *Context, opts struct {
	Dir string `long:"dir" description:"Operation directory" default:"/var/lib/miren/server/lifecycle"`
	ID  string `position:"0" usage:"Operation id" required:"true"`
}) error

ServerOperationsAbandon ends an operation nobody will finish: an executor that died mid-operation, or a rollback whose data restore keeps the server from booting.

func ServerOperationsList added in v0.16.0

func ServerOperationsList(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
	Dir string `` /* 138-byte string literal not displayed */
}) error

func ServerOperationsRun added in v0.16.0

func ServerOperationsRun(ctx *Context, opts struct {
	Operation string `long:"operation" required:"true" description:"Operation id to execute or resume"`
	Dir       string `long:"dir" description:"Operation directory" default:"/var/lib/miren/server/lifecycle"`
	HealthURL string `long:"health-url" description:"Health endpoint to verify readiness against (default: derived from the server config)"`
}) error

ServerOperationsRun is the executor entry point the transient systemd unit invokes.

func ServerOperationsShow added in v0.16.0

func ServerOperationsShow(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
	Dir string `` /* 138-byte string literal not displayed */
	ID  string `position:"0" usage:"Operation id" required:"true"`
}) error

func ServerRestart added in v0.16.0

func ServerRestart(ctx *Context, opts struct{}) error

func ServerStatus

func ServerStatus(ctx *Context, opts struct {
	Follow bool `short:"f" long:"follow" description:"Follow logs in real-time"`
}) error

ServerStatus shows the status of the miren systemd service

func ServerStatusContainer added in v0.11.1

func ServerStatusContainer(ctx *Context, opts struct {
	Name    string `short:"n" long:"name" description:"Container name" default:"miren"`
	Runtime string `long:"runtime" description:"Container runtime to use: docker or podman (auto-detected by default, preferring docker)"`
	Follow  bool   `short:"f" long:"follow" description:"Follow logs in real-time"`
}) error

ServerStatusContainer shows the status of the miren container.

func ServerUninstall

func ServerUninstall(ctx *Context, opts struct {
	RemoveData bool   `long:"remove-data" description:"Remove /var/lib/miren directory after backing it up"`
	BackupDir  string `long:"backup-dir" description:"Directory to save backup tarball" default:"."`
	SkipBackup bool   `long:"skip-backup" description:"Skip backup when removing data (dangerous)"`
}) error

ServerUninstall removes the systemd service and optionally removes /var/lib/miren

func ServerUninstallContainer added in v0.11.1

func ServerUninstallContainer(ctx *Context, opts struct {
	Name         string `short:"n" long:"name" description:"Container name" default:"miren"`
	Runtime      string `long:"runtime" description:"Container runtime to use: docker or podman (auto-detected by default, preferring docker)"`
	RemoveVolume bool   `long:"remove-volume" description:"Remove the data volume"`
	Force        bool   `short:"f" long:"force" description:"Force removal even if container is running"`
}) error

ServerUninstallContainer removes the miren container and optionally the volume.

func ServerUpgrade

func ServerUpgrade(ctx *Context, opts struct {
	Version        string `short:"V" long:"version" description:"Specific version to upgrade to (e.g., v0.2.0)"`
	Channel        string `long:"channel" description:"Channel to use: 'latest' (stable releases, default) or 'main' (bleeding edge)"`
	Check          bool   `short:"c" long:"check" description:"Check for available updates only"`
	Force          bool   `short:"f" long:"force" description:"Force upgrade even if already up to date"`
	Release        bool   `short:"r" long:"release" description:"Upgrade full release package (not just base)"`
	SkipHealth     bool   `long:"skip-health" description:"Deprecated: readiness is always verified"`
	NoAutoRollback bool   `long:"no-auto-rollback" description:"Disable automatic rollback on failure (also skips the pre-upgrade etcd snapshot)"`
	HealthTimeout  int    `long:"health-timeout" default:"0" description:"Seconds to wait for the restarted server to report ready"`
}) error

ServerUpgrade is kept for existing scripts; it runs the same operation `miren upgrade` does, with a nudge.

func ServerUpgradeRollback

func ServerUpgradeRollback(ctx *Context, opts struct {
	SkipHealth bool `long:"skip-health" description:"Skip health check after rollback"`
}) error

ServerUpgradeRollback rolls back the server to the previous version

func TestLoad

func TestLoad(ctx *Context, opts struct {
	Requests    int           `short:"n" long:"requests" description:"Number of requests to make" default:"200"`
	Concurrency int           `short:"c" long:"concurrency" description:"Number of concurrent requests to make" default:"50"`
	RateLimit   float64       `short:"q" long:"rate-limit" description:"Rate limit in requests per second" default:"0"`
	Duration    time.Duration `short:"z" long:"duration" description:"Duration of the test"`

	Method      string   `short:"m" long:"method" description:"HTTP method to use" default:"GET"`
	Header      []string `short:"H" long:"header" description:"HTTP header to use"`
	Timeout     int      `short:"t" long:"timeout" description:"Timeout for each request in seconds" default:"20"`
	HTTP2       bool     `long:"h2" description:"Use HTTP/2"`
	Host        string   `long:"host" description:"Host header to use"`
	ContentType string   `short:"T" long:"content-type" description:"Content-Type header to use" default:"text/html"`
	AuthHeader  string   `short:"a" long:"auth" description:"Basic auth header to use"`
	Accept      string   `short:"A" long:"accept" description:"Accept header to use"`
	Body        string   `short:"d" long:"data" description:"HTTP request body"`
	BodyFile    string   `short:"D" long:"data-file" description:"File to use as request body"`
	ProxyAddr   string   `short:"x" long:"proxy" description:"Proxy URL to use"`
	UserAgent   string   `short:"U" long:"user-agent" description:"User-Agent header to use"`

	CPUS   *int   `long:"cpus" description:"Number of CPUs to use"`
	Output string `short:"o" long:"output" description:"Output type, the only supported value is 'csv'"`

	DisableCompression bool `long:"disable-compression" description:"Disable compression"`
	DisableKeepAlives  bool `long:"disable-keepalives" description:"Disable keep-alives"`
	DisableRedirects   bool `long:"disable-redirects" description:"Disable redirects"`

	URL string `position:"0" usage:"URL to load test" required:"true"`
}) error

func Top added in v0.15.0

func Top(ctx *Context, opts topOptions) error

Top reports what a cluster is spending its CPU and memory on.

func Unregister added in v0.14.0

func Unregister(ctx *Context, opts UnregisterOptions) error

Unregister is the inverse of `miren server register`: it detaches the cluster from the miren.cloud organization it registered with and clears the local registration state, so the cluster can be retired or re-registered elsewhere.

The cloud half runs first. The service account key is the only credential that can authorize the cloud-side removal, and it lives in the files the local half deletes — clearing those first would strand an unreachable cluster row in the organization with no way to finish from this machine.

func Upgrade

func Upgrade(ctx *Context, opts struct {
	Version string `` /* 135-byte string literal not displayed */
	Channel string `` /* 134-byte string literal not displayed */
	Check   bool   `short:"c" long:"check" description:"Check for available updates only"`
	Force   bool   `` /* 139-byte string literal not displayed */
	User    bool   `short:"u" long:"user" description:"Install the CLI to ~/.miren/release/miren instead of the system location"`
}) error

Upgrade upgrades the server and then the CLI on a systemd server host, and just the CLI anywhere else.

func Version

func Version(ctx *Context, opts VersionOptions) error

func WarnLocalAppConfig added in v0.16.0

func WarnLocalAppConfig()

WarnLocalAppConfig prints a warning for a broken local app config, once per invocation. Safe to call whether or not the load failed.

func Whoami

func Whoami(ctx *Context, opts struct {
	FormatOptions
	ConfigCentric
}) error

Whoami displays information about the current authenticated user

Types

type AppCentric

type AppCentric struct {
	ConfigCentric `group:"Config Options"`

	App string `short:"a" long:"app" env:"MIREN_APP" description:"Application name"`
	Dir string `short:"d" long:"dir" description:"Directory to run from" default:"."`
	// contains filtered or unexported fields
}

func (*AppCentric) LoadCluster added in v0.4.0

func (a *AppCentric) LoadCluster() (*clientconfig.ClusterConfig, string, error)

LoadCluster implements per-app cluster pinning. Resolution priority:

  1. -C flag (explicit override) — also saves to state
  2. MIREN_CLUSTER env var
  3. Per-app cluster from ~/.config/miren/app-state.toml (handled by ConfigCentric)
  4. Global active_cluster from clientconfig (fallback)

func (*AppCentric) ResolvedDir added in v0.7.0

func (a *AppCentric) ResolvedDir() string

ResolvedDir returns the directory that should be used as the app source. When a config is found in a parent directory, this returns that parent directory instead of the original Dir value.

func (*AppCentric) Validate

func (a *AppCentric) Validate(glbl *GlobalFlags) error

type BeginKeyRegistrationRequest

type BeginKeyRegistrationRequest struct {
	Name      string `json:"name"`
	KeyType   string `json:"key_type"`
	PublicKey string `json:"public_key"`
}

BeginKeyRegistrationRequest represents the request to begin key registration

type BeginKeyRegistrationResponse

type BeginKeyRegistrationResponse struct {
	Envelope  string `json:"envelope"`
	Challenge string `json:"challenge"`
}

BeginKeyRegistrationResponse represents the response from begin key registration

type ClusterResponse

type ClusterResponse = cloudapi.Cluster

ClusterResponse is a cluster as Miren Cloud describes it. Aliased rather than redeclared so the commands keep their familiar name while the type, and the API that returns it, live in one place.

type Cmd

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

Cmd wraps a command function with mflags parsing

func Infer

func Infer(name, syn string, f any, opts ...CommandOption) *Cmd

Infer creates a command from a function with the signature: func(ctx *Context, opts StructType) error

func NewHelpCommand added in v0.6.0

func NewHelpCommand(d *mflags.Dispatcher) *Cmd

NewHelpCommand returns an Infer-based help command bound to the given dispatcher.

func (*Cmd) CommandGroup added in v0.8.0

func (w *Cmd) CommandGroup() string

CommandGroup implements mflags.CommandGroupProvider.

func (*Cmd) Description added in v0.5.0

func (w *Cmd) Description() string

Description implements mflags.DescriptionProvider.

func (*Cmd) Examples added in v0.5.0

func (w *Cmd) Examples() []mflags.Example

func (*Cmd) FlagSet added in v0.3.0

func (w *Cmd) FlagSet() *mflags.FlagSet

FlagSet implements mflags.Command

func (*Cmd) Help

func (w *Cmd) Help() string

Help returns help text for the command

func (*Cmd) Invoke

func (w *Cmd) Invoke(args ...string) error

func (*Cmd) ReadOptions

func (w *Cmd) ReadOptions(path string) error

func (*Cmd) RequiredFeature added in v0.5.0

func (w *Cmd) RequiredFeature() string

RequiredFeature implements mflags.RequiredFeatureProvider.

func (*Cmd) Run

func (w *Cmd) Run(fs *mflags.FlagSet, args []string) error

Run implements mflags.Command

func (*Cmd) Synopsis

func (w *Cmd) Synopsis() string

Synopsis returns a short description

func (*Cmd) Usage added in v0.3.0

func (w *Cmd) Usage() string

Usage implements mflags.Command

type CommandOption added in v0.5.0

type CommandOption func(*Cmd)

func WithDaemon added in v0.13.0

func WithDaemon() CommandOption

WithDaemon marks a command as a long-running service rather than a one-shot CLI invocation, which starts its -v ladder at Info instead of Warn. See baseLogLevel.

This lives at the registration site rather than in the unit file so the level is right however the daemon was launched — systemd, a container entrypoint, or by hand — instead of depending on every launch path remembering to pass a flag. Not remembering is how a coordinator ended up pinned at Debug forever and a runner at Warn, neither deliberately.

func WithDescription added in v0.5.0

func WithDescription(desc string) CommandOption

WithDescription sets an extended markdown description for the command.

func WithExample added in v0.5.0

func WithExample(example mflags.Example) CommandOption

func WithGroup added in v0.8.0

func WithGroup(group string) CommandOption

WithGroup assigns this command to a named group for help rendering.

func WithLabsFeature added in v0.5.0

func WithLabsFeature(feature string) CommandOption

WithLabsFeature marks this command as requiring the given labs feature flag.

type CommandOutput

type CommandOutput struct {
	Stderr bytes.Buffer
	Stdout bytes.Buffer
}

func RunCommand

func RunCommand(f any, args ...string) (*CommandOutput, error)

type CompleteKeyRegistrationRequest

type CompleteKeyRegistrationRequest struct {
	Envelope  string `json:"envelope"`
	Signature string `json:"signature"`
}

CompleteKeyRegistrationRequest represents the request to complete key registration

type ConfigCentric

type ConfigCentric struct {
	Config  string `long:"config" description:"Path to the config file"`
	Cluster string `short:"C" long:"cluster" description:"Cluster name" env:"MIREN_CLUSTER"`
	// contains filtered or unexported fields
}

func (*ConfigCentric) LoadCluster

func (c *ConfigCentric) LoadCluster() (*clientconfig.ClusterConfig, string, error)

func (*ConfigCentric) LoadConfig

func (c *ConfigCentric) LoadConfig() (*clientconfig.Config, error)

func (*ConfigCentric) RequestedCluster added in v0.13.0

func (c *ConfigCentric) RequestedCluster() string

RequestedCluster returns the cluster the user explicitly asked for with -C or MIREN_CLUSTER, or "" when they didn't ask for one. Failing to honor an explicit request has to be fatal; falling back to a default is only acceptable when no particular cluster was named.

func (*ConfigCentric) SaveConfig

func (c *ConfigCentric) SaveConfig() error

type Context

type Context struct {
	context.Context

	Log *slog.Logger

	// A separate logger for UI output, which is always at least debug level
	UILog *slog.Logger

	Stdout io.Writer
	Stderr io.Writer

	ClientConfig  *clientconfig.Config
	ClusterConfig *clientconfig.ClusterConfig
	ClusterName   string

	// CommandName is the full command path the user invoked, e.g. "route
	// list". Error messages use it to describe failures in terms of what was
	// typed rather than the internal capability name behind it.
	CommandName string

	Config struct {
		ServerAddress string
	}
	// contains filtered or unexported fields
}

func (*Context) Begin

func (c *Context) Begin(format string, args ...any)

func (*Context) Close

func (c *Context) Close() error

func (*Context) Completed

func (c *Context) Completed(format string, args ...any)

func (*Context) Info

func (c *Context) Info(format string, args ...any)

func (*Context) Level

func (c *Context) Level() slog.Level

func (*Context) Printf

func (c *Context) Printf(format string, args ...any)

func (*Context) ProgressToStderr added in v0.15.0

func (c *Context) ProgressToStderr() (restore func())

ProgressToStderr sends running commentary — Info, Warn, Completed, Printf — to stderr, and returns a function restoring it.

A command printing a machine-readable document has to keep stdout to itself: one "Using identity 'cloud'" line in front of a JSON array turns it into something no parser will accept, and the caller only finds out at the parse error. The context is redirected in place rather than copied, because it carries a live log level that must not be copied.

func (*Context) RPCClient

func (c *Context) RPCClient(name string) (*rpc.NetworkClient, error)

func (*Context) SetExitCode

func (c *Context) SetExitCode(code int)

func (*Context) Verbose added in v0.4.0

func (c *Context) Verbose() bool

func (*Context) Warn

func (c *Context) Warn(format string, args ...any)

type DebugAuthResponse

type DebugAuthResponse struct {
	Success       bool              `json:"success"`
	ServerVersion string            `json:"server_version,omitempty"`
	AuthMethod    string            `json:"auth_method,omitempty"`
	Identity      string            `json:"identity,omitempty"`
	UserInfo      map[string]string `json:"user_info,omitempty"`
	Message       string            `json:"message,omitempty"`
}

DebugAuthResponse represents the response from the debug-auth endpoint

type DeviceFlowExchangeResponse

type DeviceFlowExchangeResponse struct {
	Status           string `json:"status"`
	Error            string `json:"error,omitempty"`
	ErrorDescription string `json:"error_description,omitempty"`
	AccessToken      string `json:"access_token,omitempty"`
	RefreshToken     string `json:"refresh_token,omitempty"`
	TokenType        string `json:"token_type,omitempty"`
	ExpiresIn        int    `json:"expires_in,omitempty"`
}

DeviceFlowExchangeResponse represents the response from /api/v1/device/token

type DeviceFlowInitResponse

type DeviceFlowInitResponse struct {
	DeviceCode              string `json:"device_code"`
	UserCode                string `json:"user_code"`
	VerificationURL         string `json:"verification_uri"`
	VerificationURLComplete string `json:"verification_uri_complete,omitempty"`
	ExpiresIn               int    `json:"expires_in"`
	PollingInterval         int    `json:"polling_interval"`
}

DeviceFlowInitResponse represents the response from /api/v1/device/code

type DownloadReleaseOptions

type DownloadReleaseOptions struct {
	Branch string
	Global bool
	Force  bool
	Output string
}

DownloadReleaseOptions contains options for downloading a release

type EnvVarSpec added in v0.3.0

type EnvVarSpec struct {
	Key       string
	Value     string
	Sensitive bool
	FromFile  bool   // true if value was read from a file
	FromFile_ string // original filename if FromFile is true
}

EnvVarSpec represents a parsed environment variable specification

func ParseEnvVarSpecs added in v0.3.0

func ParseEnvVarSpecs(envSpecs, sensitiveSpecs []string) ([]EnvVarSpec, error)

ParseEnvVarSpecs parses environment variable specifications from -e and -s flags. Each spec can be: KEY=VALUE, KEY=@file, or KEY (to prompt interactively).

type ErrExitCode

type ErrExitCode int

func (ErrExitCode) Error

func (e ErrExitCode) Error() string

type FormatOptions

type FormatOptions struct {
	Format string `long:"format" description:"Output format (text, json)" default:"text"`
	JSON   bool   `long:"json" description:"Shorthand for --format json"`
}

FormatOptions provides common output formatting options

func (*FormatOptions) IsJSON

func (f *FormatOptions) IsJSON() bool

IsJSON returns true if JSON format is selected (case-insensitive)

type GlobalFlags

type GlobalFlags struct {
	Verbose       []bool `short:"v" long:"verbose" description:"Enable verbose output"`
	ServerAddress string `long:"server-address" description:"Server address to connect to" default:"127.0.0.1:8443"`
	// We actually process this manually, but we include it here so that it validates.
	Options string `long:"options" description:"Path to file containing options"`
}

type IdentityAnchorOptions added in v0.14.0

type IdentityAnchorOptions struct {
	Anchor   string `position:"0" usage:"Where to anchor workload identity: cluster or cloud" required:"true"`
	DataPath string `short:"d" long:"data-path" description:"Server data path" default:"/var/lib/miren"`
}

IdentityAnchorOptions contains options for moving a cluster's workload identity anchor.

type KeyRegistrationResponse

type KeyRegistrationResponse struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Fingerprint string `json:"fingerprint"`
	CreatedAt   string `json:"created_at"`
}

KeyRegistrationResponse represents a successfully registered key

type LocalEnvDetection added in v0.8.0

type LocalEnvDetection struct {
	// Available are env vars that are both detected and available locally
	Available []LocalEnvVar
	// Missing are env vars that were detected but not found locally
	Missing []LocalEnvVar
	// Additional are env vars found locally that look app-related but weren't detected
	Additional []LocalEnvVar
}

LocalEnvDetection contains the results of scanning the local environment

func DetectLocalEnvVars added in v0.8.0

func DetectLocalEnvVars(detectedKeys []string) LocalEnvDetection

DetectLocalEnvVars scans the local environment and cross-references with detected env vars

type LocalEnvVar added in v0.8.0

type LocalEnvVar struct {
	Key       string
	Value     string
	HasValue  bool   // true if the env var is set (even if empty)
	Source    string // "detected" (from stackbuild), "local" (found in env), "both"
	Sensitive bool   // heuristic: looks like a secret/key/token
}

LocalEnvVar represents an environment variable found in the local environment

type Model

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

func (Model) Init

func (m Model) Init() tea.Cmd

func (Model) Update

func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd)

func (Model) View

func (m Model) View() string

type OptsValidate

type OptsValidate interface {
	Validate(glbl *GlobalFlags) error
}

type RegisterOptions

type RegisterOptions struct {
	ClusterName string            `short:"n" long:"name" description:"Cluster name" required:"true"`
	CloudURL    string            `short:"u" long:"url" description:"Cloud URL" default:"https://miren.cloud"`
	Tags        map[string]string `short:"t" long:"tag" description:"Tags for the cluster (key:value)"`
	OutputDir   string            `short:"o" long:"output" description:"Output directory for registration" default:"/var/lib/miren/server"`

	// EnrollToken, when set, registers unattended: no browser approval, no
	// polling. It is minted by an org admin in miren.cloud and normally arrives
	// via the cloud-init bootstrap payload rather than being typed by hand.
	EnrollToken string `long:"enroll-token" description:"Unattended enroll token from miren.cloud"`
}

RegisterOptions contains options for cluster registration

type SectionOption added in v0.5.0

type SectionOption func(*section)

func WithSectionDescription added in v0.5.0

func WithSectionDescription(desc string) SectionOption

WithSectionDescription sets an extended markdown description for the section.

func WithSectionGroup added in v0.8.0

func WithSectionGroup(group string) SectionOption

WithSectionGroup assigns this section to a named group for help rendering.

type TickMsg

type TickMsg struct {
	Time time.Time
}

type UnregisterOptions added in v0.14.0

type UnregisterOptions struct {
	Force     bool   `short:"f" long:"force" description:"Skip the confirmation prompt"`
	LocalOnly bool   `long:"local-only" description:"Clear local registration without telling miren.cloud"`
	OutputDir string `short:"o" long:"output" description:"Directory holding the registration" default:"/var/lib/miren/server"`
}

UnregisterOptions contains options for detaching a cluster from miren.cloud

type VersionOptions

type VersionOptions struct {
	ConfigCentric
	Deps   bool   `long:"deps" description:"Show dependencies"`
	Format string `long:"format" description:"Output format (text, json)" default:"text"`
	Server bool   `short:"s" long:"server" description:"Also report the version of the active cluster's server"`
}

Source Files

Jump to

Keyboard shortcuts

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