installstate

package
v0.24.0 Latest Latest
Warning

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

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

Documentation

Overview

Package installstate owns the agent's installation ownership record and the lock that guards it. The record is internal bookkeeping, not a configuration input.

It answers three questions nothing else on the host can answer:

  • Is there an installation here, and is it the one we are being asked to perform? The record carries the machine name and a fingerprint of the identity-defining configuration, so a retry can tell its own interrupted attempt from a different installation. Without it, bootstrap can only demand a pristine host and abort otherwise.
  • How far did the last attempt get? It does not say, deliberately. Every stage reapplies on every attempt and decides from the host what it still has to do, so there is nothing here that could disagree with the host. The phase records only whether an installation is under way, finished, or being torn down, which is a thing the host cannot be asked.
  • Is anything else mutating this host? The lock serializes bootstrap, reset, repave, NodeReboot, host agent activation and AgentUpgrade, which all touch the same files and services.

It is separate from the bootstrap coordinator because the daemon's repave, NodeReboot, AgentUpgrade and AgentReset paths, reset, and host agent activation all need the record or the lock without running a bootstrap.

Index

Constants

View Source
const (
	DefaultDirectory = "/var/lib/unbounded/agent"
)

Variables

View Source
var ErrInstallationInProgress = errors.New("installation has not finished")

ErrInstallationInProgress reports that an installation owns this host and has not finished. It is distinct from ErrLockHeld, which says another process is working right now: this one says the host is mid-installation whether or not anyone is currently acting on it.

Callers that run because systemd started them, rather than because a person asked, must not treat this as a failure. An installation in progress is an ordinary state, and reporting it as a crash is how a service ends up being restarted, rate-limited, and recovered for a problem it does not have.

View Source
var ErrLockHeld = errors.New("another host lifecycle operation holds the installation lock")
View Source
var ErrNotFound = errors.New("installation record not found")

Functions

func Admit

func Admit(store *Store, machine, fingerprint string) (Record, Disposition, error)

Admit reads ownership and classifies a bootstrap attempt. Callers that mutate the host must hold the installation lock around this call.

func Fingerprint

func Fingerprint(data []byte) string

Fingerprint hashes canonical JSON supplied before ephemeral credentials are resolved.

The caller decides what canonical means, and the hash is over exactly the bytes it is given. A release that adds a field to the fingerprinted struct changes the hash of every host that did not have it, and each of those reads as a different installation demanding an explicit reset. An optional field therefore has to carry omitempty and be absent at its default, so records written before it existed keep hashing the same way.

TestBootstrapV1CompatibilityFixtures enforces this: its fixtures carry a literal fingerprint, so any change to what is hashed fails there rather than on upgraded hosts.

Types

type Disposition

type Disposition int
const (
	Fresh Disposition = iota
	Resume
	AlreadyComplete
)

type Lock

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

func AcquireWithin added in v0.13.0

func AcquireWithin(ctx context.Context, wait time.Duration, acquire func() (*Lock, error)) (*Lock, error)

AcquireWithin calls acquire until it returns anything but ErrLockHeld, or until wait has passed. It returns ErrLockHeld if the lock is still held then, and ctx's error if ctx ends first.

func (*Lock) Release

func (l *Lock) Release() error

type Phase

type Phase string

Phase is what an installation is currently doing, not how far it has got.

It deliberately records no progress. A record that claimed a stage was finished would be a statement about the host that could stop being true without anyone noticing, and a retry that trusted it would skip work the host no longer has. The stages instead decide what to do by looking at the host, so the only thing worth persisting is which mode we are in.

const (
	// Installing means an installation is under way. It says nothing about what
	// has been done, so there is nothing in it that can go stale.
	Installing Phase = "installing"
	// Complete means the installation finished. A later start verifies and
	// repairs from the applied config rather than reapplying bootstrap inputs,
	// which after an ordinary repave describe a retired slot.
	Complete Phase = "complete"
	// Resetting means a teardown started and may not have finished. This is the
	// one thing the host cannot be asked: a half-removed installation and a
	// half-built one look the same, because direction of travel is not visible.
	Resetting Phase = "resetting"
)

type Record

type Record struct {
	SchemaVersion     int    `json:"schemaVersion"`
	InstallID         string `json:"installID"`
	MachineName       string `json:"machineName"`
	ConfigFingerprint string `json:"configFingerprint"`
	Phase             Phase  `json:"phase"`
}

func NewRecord

func NewRecord(machine, fingerprint string) (Record, error)

func (Record) Validate

func (r Record) Validate() error

type Store

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

func DefaultStore

func DefaultStore() *Store

func NewStore

func NewStore(root, lockPath string) *Store

func (*Store) AcquireLock

func (s *Store) AcquireLock() (*Lock, error)

func (*Store) AcquireMutationLock

func (s *Store) AcquireMutationLock() (*Lock, error)

AcquireMutationLock serializes ordinary lifecycle work with bootstrap and reset. Legacy hosts without a record remain supported. When both locks are needed, acquire installation ownership before the binary activation lock.

func (*Store) Load

func (s *Store) Load() (Record, error)

func (*Store) MarkComplete

func (s *Store) MarkComplete(r Record) error

MarkComplete commits completion. The durable record is the only completion signal; no separate marker file is maintained.

func (*Store) Remove

func (s *Store) Remove() error

Remove is called only after teardown's filesystem barriers succeed.

Dropping ownership is itself a durable step. If the unlink cannot be flushed, the record is put back, because a reset that reports failure must leave the host visibly owned. Otherwise the removal survives in page cache only, the error sends the operator away, and the next start is admitted as a fresh install onto a half-torn-down host.

func (*Store) Root

func (s *Store) Root() string

func (*Store) Save

func (s *Store) Save(r Record) error

Jump to

Keyboard shortcuts

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