engine

package
v0.0.5 Latest Latest
Warning

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

Go to latest
Published: Jun 22, 2026 License: Apache-2.0 Imports: 36 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DefaultCachePath = platformDefaultCachePath

DefaultCachePath returns the platform default directory for cached fact groups.

View Source
var DefaultConfigPath = platformDefaultConfigPath

DefaultConfigPath returns the platform default facter-compatible facter.conf path, read when no facts-native config file exists.

View Source
var ErrExternalFactTooLarge = errors.New("external fact exceeds size limit")

ErrExternalFactTooLarge reports an external fact source exceeding the byte cap.

View Source
var ErrFactNotFound = errors.New("fact not found")

ErrFactNotFound reports a query that no fact resolved. A fact that resolved to a nil value is found: Value returns (nil, nil) for it.

View Source
var ErrNullByte = errors.New("external fact contains a null byte reference")

ErrNullByte reports an external fact name or value containing a NUL byte.

View Source
var ErrUnknownOS = errors.New("unknown os")

ErrUnknownOS reports that a Ruby host_os value does not map to a Facter OS identifier.

View Source
var NativeDefaultConfigPath = platformNativeDefaultConfigPath

NativeDefaultConfigPath returns the platform default facts-native facts.conf path, consulted before the facter-compatible default.

View Source
var Version = "dev" // ponytail: var, not const, so the build pipeline can inject the git tag

Version is overridden at release time via -ldflags "-X github.com/ncode/facts/internal/engine.Version=<git tag>". The literal below is the dev-build fallback when no tag is injected.

Functions

func BlocklistedFactsForFiltering

func BlocklistedFactsForFiltering(entries []string, configured []FactGroup) map[string]bool

BlocklistedFactsForFiltering expands config blocklist entries for resolver filtering.

func BlocklistedFactsWithGroups

func BlocklistedFactsWithGroups(entries []string, configured []FactGroup) map[string]bool

BlocklistedFactsWithGroups expands config blocklist entries into concrete fact names using the built-in group catalog plus any configured groups.

func Collection

func Collection(facts []ResolvedFact) map[string]any

Collection builds the structured fact tree used when no explicit query is provided.

func CollectionWithDottedFacts

func CollectionWithDottedFacts(facts []ResolvedFact, includeTypedDotted bool) map[string]any

CollectionWithDottedFacts builds the structured fact tree and optionally merges dotted custom and external facts into existing structured facts. It is diagnostic-silent: collisions are reported once at discovery (newSnapshot), not here, because the formatter and query paths re-run collection on every render and must not re-emit.

func ConstructOSHierarchy

func ConstructOSHierarchy(hierarchy []any, searchedOS string) []string

ConstructOSHierarchy returns the Ruby-compatible OS inheritance path for searchedOS.

func CurrentDefaultExternalFactDirs

func CurrentDefaultExternalFactDirs() []string

CurrentDefaultExternalFactDirs returns the default external fact directories (facts-native first, facter-compatible after) for the current process environment.

func CustomValueContainsNullByte

func CustomValueContainsNullByte(value any) bool

CustomValueContainsNullByte reports whether any string within value contains a null byte, which the input contract rejects.

func DefaultExternalFactDirs

func DefaultExternalFactDirs(windows, root bool, home, windowsDataDir string) []string

DefaultExternalFactDirs returns the default external fact directories: the facts-native locations first, then Ruby Facter's compatible locations. Facts found in both follow normal directory precedence.

func DetectOSHierarchy

func DetectOSHierarchy(hierarchy []any, identifier, family string, log *slog.Logger) []string

DetectOSHierarchy returns Ruby's detected OS hierarchy for an identifier. Fallback diagnostics are emitted to log; pass a discard logger to ignore them.

func DetectOSIdentifier

func DetectOSIdentifier(hostOS, linuxDistroID string) (string, error)

DetectOSIdentifier maps Ruby's RbConfig host_os value to Facter's OS identifier.

func ExternalFactResolutionRunning

func ExternalFactResolutionRunning() bool

ExternalFactResolutionRunning reports whether Facts is already resolving executable external facts in this process tree.

func FactGroupName

func FactGroupName(groups []FactGroup, fact string) (string, bool)

FactGroupName returns the name of the group containing fact.

func FormatFactGroups

func FormatFactGroups(groups []FactGroup) string

FormatFactGroups renders groups in the same YAML-like shape as Ruby Facter.

func FormatHOCON

func FormatHOCON(facts []ResolvedFact) string

FormatHOCON renders facts using Facter's HOCON presentation contract.

func FormatHOCONWithDottedFacts

func FormatHOCONWithDottedFacts(facts []ResolvedFact, includeTypedDotted bool) string

FormatHOCONWithDottedFacts renders HOCON and optionally merges dotted custom and external facts.

func FormatJSON

func FormatJSON(facts []ResolvedFact) (string, error)

FormatJSON renders facts using Facter's JSON presentation contract.

func FormatJSONWithDottedFacts

func FormatJSONWithDottedFacts(facts []ResolvedFact, includeTypedDotted bool) (string, error)

FormatJSONWithDottedFacts renders JSON and optionally merges dotted custom and external facts.

func FormatLegacy

func FormatLegacy(facts []ResolvedFact) string

FormatLegacy renders facts using the original key => value text format.

func FormatLegacyColored

func FormatLegacyColored(facts []ResolvedFact, includeTypedDotted, colorize bool) string

FormatLegacyColored renders legacy text and, when colorize is set, wraps each key in an ANSI color chosen by its nesting depth. The rendering replicates Ruby Facter's LegacyFactFormatter byte for byte: pretty-printed JSON rewritten through Ruby's exact transform pipeline, quirks included.

func FormatYAML

func FormatYAML(facts []ResolvedFact) string

FormatYAML renders facts using Facter's YAML presentation contract.

func FormatYAMLWithDottedFacts

func FormatYAMLWithDottedFacts(facts []ResolvedFact, includeTypedDotted bool) string

FormatYAMLWithDottedFacts renders YAML and optionally merges dotted custom and external facts.

func GroupTTLSeconds

func GroupTTLSeconds(ttls []FactTTL, fact string, log *slog.Logger) (int64, bool)

GroupTTLSeconds returns the configured TTL for fact in seconds.

func NormalizeCustomValue

func NormalizeCustomValue(value any) any

NormalizeCustomValue canonicalizes a custom fact value: time.Time values become RFC 3339 strings and string-keyed maps become map[string]any, so the canonical tree holds only tree-shaped data.

func ValueForQuery

func ValueForQuery(fact ResolvedFact) any

ValueForQuery returns the value selected by fact.UserQuery from fact.Value.

Types

type Config added in v0.0.3

type Config struct {
	Blocklist          []string
	ExternalDirs       []string
	Debug              bool
	Verbose            bool
	LogLevel           string
	NoExternalFacts    bool
	ForceDotResolution bool
	Sequential         bool
	SequentialSet      bool
	TTLs               []FactTTL
	FactGroups         []FactGroup
}

Config contains the supported Facter config values loaded from a config file.

func ParseConfig added in v0.0.3

func ParseConfig(path string, log *slog.Logger) (Config, error)

ParseConfig returns every supported value from a Facter config file. Diagnostics (an unreadable or invalid config file) are emitted to log; pass a discard logger to ignore them.

type Engine

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

Engine is an immutable unit of fact-discovery configuration. All registration happens at construction; resolution happens only through Discover, and concurrent use is safe because nothing mutates after NewEngine except the once-only diagnostic dedup set, which has its own lock.

func NewEngine

func NewEngine(cfg EngineConfig) (*Engine, error)

NewEngine validates and freezes cfg into an Engine.

func (*Engine) Discover

func (e *Engine) Discover(ctx context.Context, queries ...string) (*Snapshot, error)

Discover runs the configured resolvers and returns an immutable Snapshot of the canonical tree. Query matching follows the CLI's dot-notation semantics.

The Snapshot is valid even when err != nil: discovery failures are partial, and err is the join of every per-source failure (including ctx.Err() when the context ends discovery early). Not-applicable facts are absent, never errors.

type EngineConfig

type EngineConfig struct {
	// ConfigFile opts into reading the given facter.conf, honoring its
	// global.external-dir, no-external-facts toggle, fact blocklists,
	// and cache TTLs with CLI-identical semantics.
	ConfigFile string
	// ExternalDirs opts into loading external facts from exactly these
	// directories (no environment variables, no default directories).
	ExternalDirs []string
	// UseCache opts into the persistent fact cache with facter.conf TTL
	// semantics.
	UseCache bool
	// SystemDefaults selects full CLI-equivalent system-following behavior:
	// the default config file (facts.conf first, facter.conf second),
	// default external fact directories (facts-native locations first), and
	// FACTS_*/FACTER_* environment facts (FACTS_* wins name collisions).
	SystemDefaults bool
	// Logger receives engine diagnostics; nil discards them.
	Logger *slog.Logger
	// Facts are registered facts, fixed at construction.
	Facts []ProgrammaticFact

	// CLICompat selects the CLI's loader and error semantics: FACTS_*/FACTER_*
	// environment facts whenever external facts are on, silent skips for
	// failing external executables, and fail-fast on the first hard source
	// error.
	CLICompat bool
	// NoExternalFacts skips external-fact loading (--no-external-facts).
	NoExternalFacts bool
	// BlockedFacts overrides the config-derived blocklist when non-nil.
	BlockedFacts map[string]bool
}

EngineConfig is the configuration an Engine is frozen from. The zero value is the hermetic default: core facts only — no config file, no fact directories, no script execution, no environment facts, no persistent cache.

type FactCache

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

FactCache reads and writes Facter-compatible cached fact groups.

func NewFactCache

func NewFactCache(dir string, ttls []FactTTL, groups []FactGroup, log *slog.Logger) *FactCache

NewFactCache returns a cache using configured TTLs and custom fact groups. Diagnostics (cache read/write failures, unsupported custom groups) are emitted to log; pass a discard logger to ignore them.

func (*FactCache) CacheFacts

func (fc *FactCache) CacheFacts(facts []ResolvedFact) error

CacheFacts writes resolved facts into configured cache groups.

func (*FactCache) ResolveFacts

func (fc *FactCache) ResolveFacts(searched []ResolvedFact) ([]ResolvedFact, []ResolvedFact)

ResolveFacts returns facts still requiring resolution plus facts loaded from a fresh cache.

type FactGroup

type FactGroup struct {
	Name  string
	Facts []string
}

FactGroup is a named set of facts used by Facter's block/cache group CLI.

func BuiltinFactGroups

func BuiltinFactGroups() []FactGroup

BuiltinFactGroups returns the static fact group catalog for the Go port.

func ExternalFactGroups

func ExternalFactGroups(dirs []string) ([]FactGroup, error)

ExternalFactGroups returns fact group entries for loadable external fact files.

func MergeFactGroups

func MergeFactGroups(defaults, configured []FactGroup) []FactGroup

MergeFactGroups returns defaults with configured groups replacing same-name defaults.

type FactTTL

type FactTTL struct {
	Fact string
	TTL  string
}

FactTTL is a configured cache duration for a fact or fact group.

type FormatOptions

type FormatOptions struct {
	JSON               bool
	YAML               bool
	HOCON              bool
	IncludeTypedDotted bool
	Colorize           bool
}

FormatOptions selects the presentation format for resolved facts.

type Formatter

type Formatter interface {
	Name() string
	Format([]ResolvedFact) (string, error)
}

Formatter renders resolved facts in one presentation format.

func BuildFormatter

func BuildFormatter(opts FormatOptions) Formatter

BuildFormatter selects a formatter using Ruby's formatter factory precedence.

type OutputShape added in v0.0.3

type OutputShape int

OutputShape names the projection shape a formatter renders.

const (
	// ShapeFullTree is the no-query, full canonical tree output.
	ShapeFullTree OutputShape = iota
	// ShapeSingleQuery is one selected query rendered as a bare value.
	ShapeSingleQuery
	// ShapeMultiQuery is multiple selected queries rendered as a query map.
	ShapeMultiQuery
	// ShapeEmpty is no output (no facts and no queries).
	ShapeEmpty
)

type ProgrammaticFact

type ProgrammaticFact struct {
	Name    string
	Resolve func(ctx context.Context) (any, error)
}

ProgrammaticFact is a fact registered on an Engine at construction. A nil Resolve registers a fact that resolves to nil. The resolved value is normalized like every registered fact value (times to RFC 3339, string-keyed maps to map[string]any); values containing null bytes are rejected with a warning and resolve to nil.

type Projection added in v0.0.3

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

Projection owns query selection and output projection over one set of resolved facts. It centralizes the rules that Snapshot value lookup, the CLI strict-mode path, and the formatter adapters previously reassembled independently: reverse-precedence selection, wildcard matching, canonical tree fallback for nested queries, dotted external/registered fact merge mode, selected-query value extraction, and strict missing-query detection.

A Projection memoizes the canonical tree it builds for fallback digs, so repeated lookups over one Projection do not rebuild the tree per call.

func NewProjection added in v0.0.3

func NewProjection(facts []ResolvedFact, includeTypedDotted bool) *Projection

NewProjection returns a Projection over facts. includeTypedDotted selects the dotted external/registered fact merge mode used for the canonical tree and the nested-query fallback dig.

func (*Projection) Collection added in v0.0.3

func (p *Projection) Collection() map[string]any

Collection returns the canonical fact tree, built once and memoized. The returned map is the live memoized tree, shared with FullTree and (for a Snapshot-bound projection) with the Snapshot's own tree; callers MUST treat it as read-only. Mutating it corrupts the projection and any tree it was constructed from.

func (*Projection) FullTree added in v0.0.3

func (p *Projection) FullTree() map[string]any

FullTree returns the canonical tree for ShapeFullTree rendering.

func (*Projection) LookupValue added in v0.0.3

func (p *Projection) LookupValue(query string) (value any, found bool)

LookupValue resolves a single query to its canonical-tree value. found reports whether any fact resolved the query: a fact that legitimately resolved to a nil value is found (value nil, found true), while a query no fact resolved is missing (value nil, found false). This is the Snapshot missing-vs-nil contract.

func (*Projection) MissingQueries added in v0.0.3

func (p *Projection) MissingQueries(selected []ResolvedFact) []string

MissingQueries returns the user queries among selected facts that no fact resolved to a non-nil value, in order, for CLI strict-mode reporting. A selected fact with an empty UserQuery (full output) is never missing.

func (*Projection) MultiQueryValues added in v0.0.3

func (p *Projection) MultiQueryValues() map[string]any

MultiQueryValues returns the user-query-to-value map for ShapeMultiQuery rendering.

func (*Projection) Select added in v0.0.3

func (p *Projection) Select(queries []string) []ResolvedFact

Select returns one resolved fact per query, applying reverse-precedence selection, wildcard matching, and canonical tree fallback. With no queries it returns the backing facts unchanged, matching the full-output contract.

func (*Projection) Shape added in v0.0.3

func (p *Projection) Shape() OutputShape

Shape reports which output shape the backing facts project to, following the formatter contract: no user queries with facts present is the full tree, a single user query is a bare value, multiple user queries are a query map, and no facts at all is empty.

func (*Projection) SingleQueryValue added in v0.0.3

func (p *Projection) SingleQueryValue() any

SingleQueryValue returns the lone selected query's value for ShapeSingleQuery rendering.

type ResolvedFact

type ResolvedFact struct {
	Name      string
	Value     any
	UserQuery string
	Type      string
	File      string
}

ResolvedFact is a fact value after resolution and before presentation.

func CoreFacts

func CoreFacts(s *Session) []ResolvedFact

CoreFacts returns the small cross-platform fact set used by the initial Go CLI.

func FilterBlockedFacts

func FilterBlockedFacts(facts []ResolvedFact, blocked map[string]bool) []ResolvedFact

FilterBlockedFacts removes facts whose root name is blocklisted.

func LoadExternalFacts

func LoadExternalFacts(s *Session, dirs []string) ([]ResolvedFact, error)

LoadExternalFacts loads static external facts from the provided directories.

func LoadExternalFactsWithBlocklist

func LoadExternalFactsWithBlocklist(s *Session, dirs []string, blocked map[string]bool) ([]ResolvedFact, error)

LoadExternalFactsWithBlocklist loads external facts from dirs plus the FACTS_*/FACTER_* environment variables — the CLI's system-following semantics — skipping files whose base name is blocklisted by the Facter config.

func Select

func Select(facts []ResolvedFact, queries []string) []ResolvedFact

Select returns resolved facts for the user-provided queries.

func SelectWithDottedFacts

func SelectWithDottedFacts(facts []ResolvedFact, queries []string, includeTypedDotted bool) []ResolvedFact

SelectWithDottedFacts returns resolved facts and optionally merges dotted custom and external facts into structured facts for partial queries.

type Session

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

Session carries the state of one resolution run: memoized host probes and resolution-scoped caches. Resolvers share a Session so facts derived from the same probe agree within a run; a fresh Session re-reads the host, which is how discovery stays current and how independent engines stay isolated.

func NewSession

func NewSession() *Session

NewSession returns an empty Session; probes run on first use.

func NewSessionContext

func NewSessionContext(ctx context.Context) *Session

NewSessionContext returns an empty Session whose command executions and metadata requests are bound to ctx.

func (*Session) Context

func (s *Session) Context() context.Context

Context returns the context this session's resolution work runs under.

type Snapshot

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

Snapshot is the immutable result of one discovery run: the canonical tree plus pure query operations over it. Safe for concurrent use.

func (*Snapshot) All

func (sn *Snapshot) All() iter.Seq2[string, any]

All iterates the top-level canonical-tree entries in sorted name order. Yielded values are copies; mutating them does not affect the Snapshot.

func (*Snapshot) Facts

func (sn *Snapshot) Facts() []ResolvedFact

Facts returns the resolved facts backing the Snapshot, for the CLI's formatter pipeline.

func (*Snapshot) Tree

func (sn *Snapshot) Tree() map[string]any

Tree returns a copy of the canonical tree. Mutating the returned value does not affect the Snapshot.

func (*Snapshot) Value

func (sn *Snapshot) Value(query string) (any, error)

Value returns the canonical-tree node selected by the dot-notation query — the same value the CLI reports for the same query. A query no fact resolved returns an error satisfying errors.Is(err, ErrFactNotFound); a custom or external fact that legitimately resolved to nil returns (nil, nil).

Lookup reuses the canonical tree built once for the Snapshot; it does not rebuild the tree per call.

Jump to

Keyboard shortcuts

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