files

package
v0.6.0-rc.1 Latest Latest
Warning

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

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

Documentation

Overview

Package files owns the manifest-managed file tree of an HAProxy pod: the mount probe, tree hashing, part verification, the backup journal and the transactional write. Disk is the authority; nothing here parses HAProxy syntax.

Package files owns the manifest-managed file tree of an HAProxy pod: the mount probe, tree hashing, part verification, the backup journal and the transactional write. Disk is the authority; nothing here parses HAProxy syntax.

Index

Constants

View Source
const (
	TempDirName = ".haptic-tmp"
	LKGDirName  = ".haptic-lkg"
)

Directory names the agent reserves inside every mount it writes to.

Variables

View Source
var ErrDigestMismatch = errors.New("part does not match its manifest digest")

ErrDigestMismatch is what a received part failing its manifest digest wraps; it is a refusal, never a retry.

View Source
var ErrInvalidPath = fmt.Errorf("invalid manifest path")

ErrInvalidPath is the class every path rejection wraps, so a caller can report one refusal reason for the whole safety check.

View Source
var ErrPatchBaseMissing = errors.New("patch base is not the file held")

ErrPatchBaseMissing is what a patch wraps when the file on disk is not the base it splices into; the controller answers it by sending the whole file.

Functions

func ValidatePath

func ValidatePath(rel string) error

ValidatePath accepts only paths the agent may own: relative, canonical, and with no dot-prefixed component, which keeps the agent's own state file, its temp directories and its LKG directories out of every manifest.

Types

type Entry

type Entry struct {
	Path   string    `json:"path"`
	Kind   EntryKind `json:"kind"`
	Backup string    `json:"backup,omitempty"`
}

Entry is one path's backup record. Backup is an absolute path inside the path's own mount, empty for KindCreated.

type EntryKind

type EntryKind string

EntryKind is how a path looked when the last-known-good set still held it.

const (
	KindModified EntryKind = "modified" // Backup holds the LKG content.
	KindCreated  EntryKind = "created"  // The path did not exist; restore unlinks it.
	KindDeleted  EntryKind = "deleted"  // Backup holds the content the apply unlinked.
)

The three shapes a restore has to undo.

type Fingerprint

type Fingerprint struct {
	Sum      [sha256.Size]byte
	Mode     fs.FileMode
	UID, GID uint32
}

Fingerprint tells the file the agent wrote from a rewrite of it: its bytes, by SHA-256 rather than the digest anyone can collide, its mode and its owner.

type Journal

type Journal struct {
	Entries []Entry `json:"entries,omitempty"`
}

Journal holds the last-known-good version of every path changed since the LKG plan. The first entry per path wins: later applies must not overwrite a backup with an already-diverged version.

func (*Journal) Empty

func (j *Journal) Empty() bool

Empty reports whether the on-disk set is the LKG set.

func (*Journal) Has

func (j *Journal) Has(rel string) bool

Has reports whether the LKG version of rel is already backed up.

type Mount

type Mount struct {
	Root   string
	Device uint64
}

Mount is one filesystem under the base directory. Hardlinks and renames are confined to a single mount, so temp and LKG directories exist per mount.

type Observation

type Observation struct {
	At          api.FileAt
	Fingerprint Fingerprint
}

Observation is one file of the tree as read back from disk.

type Staged

type Staged struct {
	Rel         string
	Fingerprint Fingerprint
	// contains filtered or unexported fields
}

Staged is a verified part waiting in its target mount's temp directory.

func (*Staged) Discard

func (s *Staged) Discard()

Discard drops a staged part without touching the tree.

type Store

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

Store owns the manifest-managed tree under a base directory.

func NewStore

func NewStore(baseDir string, logger *slog.Logger, reserved ...string) (*Store, error)

NewStore probes the mounts under baseDir and prepares each one's temp and LKG directory. reserved names the paths inside the tree that belong to something other than the manifest, which is the HAProxy sockets.

func (*Store) Abs

func (s *Store) Abs(rel string) (string, error)

Abs turns a validated manifest path into an absolute path inside the tree.

func (*Store) BaseDir

func (s *Store) BaseDir() string

BaseDir is the absolute root of the managed tree.

func (*Store) Begin

func (s *Store) Begin(j *Journal, configRel string) *Transaction

Begin opens a transaction whose rollback target is the journal's contents. configRel is installed last so the tree is never a config newer than the files it references.

func (*Store) ClearJournal

func (s *Store) ClearJournal(j *Journal) error

ClearJournal drops the backups of a set that has become the last known good.

func (*Store) CrossDeviceCopies

func (s *Store) CrossDeviceCopies() uint64

CrossDeviceCopies counts renames that fell back to a copy. The mount probe is supposed to keep this at zero; the server reports a non-zero count as an invariant violation.

func (*Store) HashTree

func (s *Store) HashTree(paths []string) (map[string]api.FileAt, error)

HashTree observes the ownership set on disk. A path that is absent, or that something else turned into a directory or a symlink, is not in the result: it is not a file the agent wrote, and its absence is what makes a plan id unknown after a container restart put the bootstrap config back.

func (*Store) Mounts

func (s *Store) Mounts() []Mount

Mounts lists the probed mounts, deepest root first.

func (*Store) Observe

func (s *Store) Observe(paths []string) (map[string]Observation, error)

Observe is HashTree with each file's fingerprint.

func (*Store) Restore

func (s *Store) Restore(j *Journal, configRel string) error

Restore puts the last-known-good version of every journalled path back. The config file goes last so HAProxy is never told to read a config whose auxiliary files have not been restored yet.

func (*Store) Stage

func (s *Store) Stage(rel string, r io.Reader, digest string, size int64) (*Staged, error)

Stage streams a received part into the temp directory of the mount that will hold it and verifies it against the manifest digest and size before the content can ever reach the tree.

func (*Store) StagePatch

func (s *Store) StagePatch(rel string, r io.Reader, patch *api.FilePatch, digest string, size int64) (*Staged, error)

StagePatch stages a file delivered as a splice: r carries the bytes that replace [patch.Offset, patch.Offset+patch.Length) of the file at rel, which has to be on disk at patch.BaseDigest and patch.BaseSize, and the result is verified against digest and size exactly as a whole part is. A base that is not held is ErrPatchBaseMissing; a patch that does not fit its base is a refusal.

func (*Store) SweepTemp

func (s *Store) SweepTemp() error

SweepTemp removes temp files a crash left behind. Bounded by the directory listing it reads.

type Transaction

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

Transaction is one apply's file work: back up what it is about to change, then install the staged parts and drop the paths the manifest no longer names. It never runs a runtime command and never reloads.

func (*Transaction) Backup

func (t *Transaction) Backup() error

Backup records the last-known-good version of every path the transaction touches. It is the first phase that can fail, and it changes no content.

func (*Transaction) Changes

func (t *Transaction) Changes() int

Changes counts the paths this transaction touches.

func (*Transaction) Delete

func (t *Transaction) Delete(rel string)

Delete schedules the removal of a path the manifest dropped.

func (*Transaction) Discard

func (t *Transaction) Discard()

Discard drops every staged part that has not been installed. The tree is untouched by a discarded transaction.

func (*Transaction) Install

func (t *Transaction) Install(staged *Staged)

Install schedules a verified part.

func (*Transaction) Write

func (t *Transaction) Write() error

Write installs the staged parts, config last, and then drops the deleted paths. A failure leaves the journal complete, so the caller can restore.

Jump to

Keyboard shortcuts

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