state

package
v0.10.4 Latest Latest
Warning

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

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

Documentation

Overview

Package state manages the homelab-state working copy (default ~/.hlab): the versioned, declarative description of every VM hlab manages.

Layout:

~/.hlab/
  config.yaml              connection + secrets — GITIGNORED (contains the token)
  plans.yaml               VM/LXC plans — versioned
  vms/<name>.yaml          declaration — VERSIONED (source of truth)
  terraform/               generated terraform workspace
    terraform.tfvars.json    specs — versioned
    secrets.auto.tfvars.json passwords — GITIGNORED
    *.tfstate, .terraform/   operational — GITIGNORED
  .gitignore

Secrets (VM passwords) are never written into the declaration YAML; only a HasPassword flag is recorded.

Index

Constants

This section is empty.

Variables

View Source
var RequiredGitignore = []string{
	"config.yaml",
	"terraform/secrets.auto.tfvars.json",
	"terraform/*.tfstate",
	"terraform/*.tfstate.*",
	"terraform/.terraform/",
	"terraform/.terraform.lock.hcl",
	".env",
}

RequiredGitignore lists the entries that must be present in the state dir's .gitignore. config.yaml carries the Proxmox token; the rest are operational or secret terraform artifacts. Kept in dependency order (config first) so a freshly created file reads sensibly.

Functions

func EnsureGitignore

func EnsureGitignore(dir string, required []string) error

EnsureGitignore makes sure every entry in required is present in dir/.gitignore, appending only the missing ones so an operator's own additions (and entries already there) are left untouched — never rewriting the whole file. A brand-new file gets a header comment. Idempotent.

Types

type Store

type Store struct {
	Dir string
}

Store is the homelab-state directory.

func New

func New(dir string) *Store

func (*Store) Commit

func (s *Store) Commit(message string) error

Commit stages everything and commits with the given message. Best-effort: it is a no-op when git is unavailable or there is nothing to commit.

func (*Store) Delete

func (s *Store) Delete(name string) error

Delete removes a VM declaration file.

func (*Store) Init

func (s *Store) Init() error

Init creates the directory layout and a .gitignore, and initializes git if the directory is not yet a repository.

func (*Store) List

func (s *Store) List() ([]*VMSpec, error)

List returns all VM declarations, sorted by name.

func (*Store) Load

func (s *Store) Load(name string) (*VMSpec, error)

Load reads a single VM declaration by name.

func (*Store) Push

func (s *Store) Push() error

Push pushes to the configured remote, if any. Best-effort.

func (*Store) Save

func (s *Store) Save(vm *VMSpec) error

Save writes a VM declaration to vms/<name>.yaml.

func (*Store) TerraformDir

func (s *Store) TerraformDir() string

type VMSpec

type VMSpec struct {
	Name string `yaml:"name"` // hostname = guest name = terraform key = inventory name

	// Type discriminates the guest kind: "" or "vm" == QEMU VM (back-compat with
	// existing declarations that omit it); "lxc" == LXC container.
	Type string `yaml:"type,omitempty"`

	Node       string `yaml:"node"`
	VMID       int    `yaml:"vmid"`
	Template   string `yaml:"template"`    // human-readable template name
	TemplateID int    `yaml:"template_id"` // source VM id to clone (VMs only)
	Storage    string `yaml:"storage"`
	Bridge     string `yaml:"bridge"`

	// LXC-only fields (ignored for VMs).
	TemplateFile string `yaml:"template_file,omitempty"` // vztmpl volid, e.g. local:vztmpl/debian-12-standard_...tar.zst
	OSType       string `yaml:"os_type,omitempty"`       // bpg operating_system.type: debian|ubuntu|alpine|...
	Unprivileged bool   `yaml:"unprivileged,omitempty"`
	Nesting      bool   `yaml:"nesting,omitempty"`
	SwapMB       int    `yaml:"swap_mb,omitempty"`
	// HostManagedNet: PVE 9.1+ — Proxmox writes the container's network config
	// itself. Required for static-IP CTs there, where the bpg default
	// (host-managed=0) means nobody configures the interface and the guest boots
	// with no IP.
	HostManagedNet bool `yaml:"host_managed_net,omitempty"`

	// CPUType is the QEMU CPU model (VMs only — a container shares the host
	// kernel). Empty means the Terraform default, a portable baseline chosen so a
	// VM can live-migrate between nodes with different host CPUs. Worth overriding
	// per cluster: the default exposes AES but NOT PCLMULQDQ, and a binary compiled
	// to require it dies at startup with SIGILL. Proxmox won't let a single flag be
	// added on top of a model (its `flags` field only takes a security/virt subset),
	// so the whole model has to change — e.g. `EPYC` on an all-AMD cluster.
	CPUType string `yaml:"cpu_type,omitempty"`

	Plan     string `yaml:"plan,omitempty"` // preconfigured plan name (e.g. "KVM2"/"micro"), empty = custom
	Cores    int    `yaml:"cores"`
	MemoryGB int    `yaml:"memory_gb"`           // VM memory (GB)
	MemoryMB int    `yaml:"memory_mb,omitempty"` // LXC memory (MB); sub-GB tiers need this
	DiskGB   int    `yaml:"disk_gb"`

	DHCP    bool     `yaml:"dhcp"`
	IPCIDR  string   `yaml:"ip_cidr,omitempty"`
	Gateway string   `yaml:"gateway,omitempty"`
	DNS     []string `yaml:"dns,omitempty"`

	Username    string   `yaml:"username"`
	SSHKeys     []string `yaml:"ssh_keys,omitempty"` // public key contents
	HasPassword bool     `yaml:"has_password"`       // secret stored separately

	// Dotfiles exists only for legacy-YAML migration: dotfiles is an ordinary
	// software-catalog entry now, but declarations written before that still say
	// `dotfiles: true`. This field must stay so Store.Load can read them (yaml.v3
	// silently drops unknown keys, so removing it would lose the selection);
	// Store.Load migrates a legacy `dotfiles: true` into Software ("dotfiles") and
	// zeroes this, so all downstream code reads only Software, and omitempty keeps
	// it out of newly-written declarations.
	Dotfiles bool     `yaml:"dotfiles,omitempty"`
	Software []string `yaml:"software,omitempty"` // catalog keys, e.g. ["docker","node"]
}

VMSpec is the declarative description of a single guest (VM or LXC container).

func (*VMSpec) IsLXC

func (v *VMSpec) IsLXC() bool

IsLXC reports whether this declaration describes an LXC container.

func (*VMSpec) Kind

func (v *VMSpec) Kind() string

Kind maps the guest type to the Proxmox API path segment ("qemu" or "lxc").

Jump to

Keyboard shortcuts

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