Documentation
¶
Overview ¶
============================================================================= NFTBan v1.73 - Installer Executor Interface ============================================================================= SPDX-License-Identifier: MPL-2.0 meta:name="installer-executor" meta:type="lib" meta:owner="Antonios Voulvoulis <contact@nftban.com>" meta:created_date="2026-04-04" meta:description="Executor interface abstracting system commands for testability" meta:inventory.files="internal/installer/executor/executor.go" meta:inventory.binaries="" meta:inventory.env_vars="" meta:inventory.config_files="" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges="none" =============================================================================
============================================================================= NFTBan v1.73 - Installer Mock Executor ============================================================================= SPDX-License-Identifier: MPL-2.0 meta:name="installer-executor-mock" meta:type="test" meta:owner="Antonios Voulvoulis <contact@nftban.com>" meta:created_date="2026-04-04" meta:description="In-memory mock executor for unit testing" meta:inventory.files="internal/installer/executor/mock.go" meta:inventory.binaries="" meta:inventory.env_vars="" meta:inventory.config_files="" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges="none" =============================================================================
============================================================================= NFTBan v1.73 - Installer Real Executor ============================================================================= SPDX-License-Identifier: MPL-2.0 meta:name="installer-executor-real" meta:type="lib" meta:owner="Antonios Voulvoulis <contact@nftban.com>" meta:created_date="2026-04-04" meta:description="Production executor using os/exec and syscalls" meta:inventory.files="internal/installer/executor/real.go" meta:inventory.binaries="" meta:inventory.env_vars="" meta:inventory.config_files="" meta:inventory.systemd_units="" meta:inventory.network="" meta:inventory.privileges="root" =============================================================================
Index ¶
- type Executor
- type FileMeta
- type MockExecutor
- func (m *MockExecutor) Chmod(_ string, _ os.FileMode) error
- func (m *MockExecutor) Chown(_ string, _, _ int) error
- func (m *MockExecutor) CommandCallCount(nameAndArgs ...string) int
- func (m *MockExecutor) CommandCalled(nameAndArgs ...string) bool
- func (m *MockExecutor) CommandExists(name string) bool
- func (m *MockExecutor) DaemonReload() error
- func (m *MockExecutor) FileExists(path string) bool
- func (m *MockExecutor) Getenv(key string) string
- func (m *MockExecutor) GroupExists(name string) bool
- func (m *MockExecutor) MkdirAll(path string, _ os.FileMode) error
- func (m *MockExecutor) NftAddElement(family, table, set string, element string) error
- func (m *MockExecutor) NftCheck(_ string) error
- func (m *MockExecutor) NftDeleteTable(family, table string) error
- func (m *MockExecutor) NftListSet(family, table, set string) (string, error)
- func (m *MockExecutor) NftTableExists(family, table string) bool
- func (m *MockExecutor) OnCommand(fn func(), name string, args ...string)
- func (m *MockExecutor) ReadFile(path string) ([]byte, error)
- func (m *MockExecutor) Remove(path string) error
- func (m *MockExecutor) Rename(oldpath, newpath string) error
- func (m *MockExecutor) Run(name string, args ...string) Result
- func (m *MockExecutor) RunContext(_ context.Context, name string, args ...string) Result
- func (m *MockExecutor) RunTimeout(_ time.Duration, name string, args ...string) Result
- func (m *MockExecutor) ServiceActive(unit string) bool
- func (m *MockExecutor) ServiceDisable(unit string) error
- func (m *MockExecutor) ServiceEnable(unit string) error
- func (m *MockExecutor) ServiceMask(unit string) error
- func (m *MockExecutor) ServiceStart(unit string) error
- func (m *MockExecutor) ServiceStop(unit string) error
- func (m *MockExecutor) ServiceUnmask(unit string) error
- func (m *MockExecutor) Stat(path string) (FileMeta, error)
- func (m *MockExecutor) Symlink(_, _ string) error
- func (m *MockExecutor) UserExists(name string) bool
- func (m *MockExecutor) WriteFileAtomic(path string, data []byte, _ os.FileMode) error
- type RealExecutor
- func (r *RealExecutor) Chmod(path string, perm os.FileMode) error
- func (r *RealExecutor) Chown(path string, uid, gid int) error
- func (r *RealExecutor) CommandExists(name string) bool
- func (r *RealExecutor) DaemonReload() error
- func (r *RealExecutor) FileExists(path string) bool
- func (r *RealExecutor) Getenv(key string) string
- func (r *RealExecutor) GroupExists(name string) bool
- func (r *RealExecutor) MkdirAll(path string, perm os.FileMode) error
- func (r *RealExecutor) NftAddElement(family, table, set string, element string) error
- func (r *RealExecutor) NftCheck(configContent string) error
- func (r *RealExecutor) NftDeleteTable(family, table string) error
- func (r *RealExecutor) NftListSet(family, table, set string) (string, error)
- func (r *RealExecutor) NftTableExists(family, table string) bool
- func (r *RealExecutor) ReadFile(path string) ([]byte, error)
- func (r *RealExecutor) Remove(path string) error
- func (r *RealExecutor) Rename(oldpath, newpath string) error
- func (r *RealExecutor) Run(name string, args ...string) Result
- func (r *RealExecutor) RunContext(ctx context.Context, name string, args ...string) Result
- func (r *RealExecutor) RunTimeout(timeout time.Duration, name string, args ...string) Result
- func (r *RealExecutor) ServiceActive(unit string) bool
- func (r *RealExecutor) ServiceDisable(unit string) error
- func (r *RealExecutor) ServiceEnable(unit string) error
- func (r *RealExecutor) ServiceMask(unit string) error
- func (r *RealExecutor) ServiceStart(unit string) error
- func (r *RealExecutor) ServiceStop(unit string) error
- func (r *RealExecutor) ServiceUnmask(unit string) error
- func (r *RealExecutor) Stat(path string) (FileMeta, error)
- func (r *RealExecutor) Symlink(oldname, newname string) error
- func (r *RealExecutor) UserExists(name string) bool
- func (r *RealExecutor) WriteFileAtomic(path string, data []byte, perm os.FileMode) error
- type RecordedCommand
- type Result
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Executor ¶
type Executor interface {
// Run executes a command and returns the result. Timeout defaults to 30s.
Run(name string, args ...string) Result
// RunContext executes a command with the given context for cancellation/timeout.
RunContext(ctx context.Context, name string, args ...string) Result
// RunTimeout is a convenience wrapper: creates a context with the given timeout.
RunTimeout(timeout time.Duration, name string, args ...string) Result
// ReadFile reads the contents of a file.
ReadFile(path string) ([]byte, error)
// WriteFileAtomic writes data to a temp file then renames to path (atomic on same FS).
WriteFileAtomic(path string, data []byte, perm os.FileMode) error
// FileExists returns true if path exists (file or directory).
FileExists(path string) bool
// MkdirAll creates a directory tree (like os.MkdirAll).
MkdirAll(path string, perm os.FileMode) error
// Chown changes file ownership.
Chown(path string, uid, gid int) error
// Chmod changes file permissions.
Chmod(path string, perm os.FileMode) error
// Remove deletes a file or empty directory.
Remove(path string) error
// Symlink creates a symbolic link (newname -> oldname).
Symlink(oldname, newname string) error
// Rename atomically renames oldpath to newpath. Same-filesystem
// semantics equivalent to syscall.Rename. Implementations route
// through whatever primitive their host abstraction provides
// (RealExecutor uses os.Rename; MockExecutor records the call and
// updates its in-memory file map).
//
// Added in PR-26-code-B per §43.2 lock to replace the previous
// Run("mv", ...) indirection used by restore_deps_csf.go's A.3
// binary-restore step. Mutation surface is bounded by
// INV-PR26-NEW-MUTATION-SURFACES-BOUNDED (§44 row 2).
Rename(oldpath, newpath string) error
// Stat returns the FileMeta (mode / uid / gid / size) for a path.
// Read-only introspection. Added in PR-26-code-C for the CSF
// cron-backup manifest writer + reader. Per §51.5-A2 invariant,
// read-only typed introspection is OUTSIDE the bounded-3 mutation
// cap; no new mutation surface is introduced.
//
// Returns an error if the path does not exist or cannot be
// stat'd (per os.Stat semantics in the real implementation).
Stat(path string) (FileMeta, error)
// NftTableExists returns true if the given nft table exists in the kernel.
// family: "ip", "ip6", or "inet". table: e.g. "nftban".
NftTableExists(family, table string) bool
// NftListSet returns the elements of an nft set as a raw string.
// Returns ("", error) if the set does not exist.
NftListSet(family, table, set string) (string, error)
// NftAddElement adds an element to an nft set.
NftAddElement(family, table, set string, element string) error
// NftDeleteTable deletes an nft table. Ignores "not found" errors.
NftDeleteTable(family, table string) error
// NftCheck runs nft -c -f on the given config content (syntax validation).
// Returns nil if valid, error with details if invalid.
NftCheck(configContent string) error
// ServiceActive returns true if the systemd unit is active.
ServiceActive(unit string) bool
// ServiceEnable enables a systemd unit.
ServiceEnable(unit string) error
// ServiceStart starts a systemd unit.
ServiceStart(unit string) error
// ServiceStop stops a systemd unit.
ServiceStop(unit string) error
// ServiceDisable disables a systemd unit.
ServiceDisable(unit string) error
// ServiceMask masks a systemd unit (prevents start by any means).
ServiceMask(unit string) error
// ServiceUnmask unmasks a systemd unit (inverse of ServiceMask).
// Used by the CSF restore A.1 step. Added in PR-26-code-B per
// §43.2 lock to replace the previous
// Run("systemctl", "unmask", ...) indirection. Mutation surface
// is bounded by INV-PR26-NEW-MUTATION-SURFACES-BOUNDED (§44 row 2).
ServiceUnmask(unit string) error
// DaemonReload runs systemctl daemon-reload.
DaemonReload() error
// CommandExists returns true if the named command is in PATH.
CommandExists(name string) bool
// UserExists returns true if the named system user exists.
UserExists(name string) bool
// GroupExists returns true if the named system group exists.
GroupExists(name string) bool
// Getenv returns the value of an environment variable.
Getenv(key string) string
}
Executor contract (frozen):
Command execution:
- Run: execute a command, return exit code + output
- RunContext: execute with context (for timeout/cancellation)
File operations:
- ReadFile / WriteFileAtomic / FileExists / MkdirAll
- Chown / Chmod / Remove / Symlink
nftables queries:
- NftTableExists / NftListSet / NftAddElement / NftDeleteTable / NftCheck
systemd:
- ServiceActive / ServiceEnable / ServiceStart / ServiceStop
- ServiceDisable / ServiceMask / ServiceUnmask / DaemonReload
File operations (atomic):
- Rename — atomic same-filesystem rename via os.Rename
File metadata (read-only introspection):
- Stat — return mode/uid/gid/size for a path
System:
- CommandExists / UserExists / GroupExists / Getenv
type FileMeta ¶ added in v1.100.4
FileMeta carries the read-only metadata Stat returns. Added in PR-26-code-C for the CSF cron-backup manifest writer + reader, which need to record and verify mode / uid / gid / size of the backed-up files.
Per §51.5-A2 invariant, this is read-only introspection — it is OUTSIDE the bounded-3 mutation surface cap of INV-PR26-NEW-MUTATION-SURFACES-BOUNDED. No new mutation surface is introduced.
type MockExecutor ¶
type MockExecutor struct {
// Commands records every command executed (for assertion).
Commands []RecordedCommand
// RunResults maps "name:arg1:arg2" to a preset Result.
// If a command is not in RunResults, it returns exit 0 with empty output.
RunResults map[string]Result
// Files maps path -> content for ReadFile/FileExists.
Files map[string][]byte
// FileStats maps path -> FileMeta for Stat. PR-26-code-C
// addition. When a path is in Files but absent from FileStats,
// Stat synthesizes a default-mode (0644 root:root) FileMeta with
// Size derived from the in-memory content. Tests that need to
// pin specific mode/uid/gid populate FileStats explicitly.
FileStats map[string]FileMeta
// WrittenFiles records what was written via WriteFileAtomic.
WrittenFiles map[string][]byte
// Dirs records directories created via MkdirAll.
Dirs map[string]bool
// NftTables maps "family:table" -> exists.
NftTables map[string]bool
// NftSets maps "family:table:set" -> element list as string.
NftSets map[string]string
// Services maps "unit" -> active.
Services map[string]bool
// Users maps "name" -> exists.
Users map[string]bool
// Groups maps "name" -> exists.
Groups map[string]bool
// Env maps "key" -> value.
Env map[string]string
// ExistingCommands maps "name" -> exists.
ExistingCommands map[string]bool
// PR-26-code-B: typed-method error injection. When set non-nil,
// the corresponding typed method returns the assigned error
// instead of nil. Mirrors the RunResults pattern that controls
// Run() exit codes.
ServiceUnmaskErr error
RenameErr error
// contains filtered or unexported fields
}
MockExecutor implements Executor with in-memory state for testing.
func NewMockExecutor ¶
func NewMockExecutor() *MockExecutor
NewMockExecutor creates a MockExecutor with all maps initialized.
func (*MockExecutor) CommandCallCount ¶ added in v1.98.0
func (m *MockExecutor) CommandCallCount(nameAndArgs ...string) int
CommandCallCount returns how many times a command matching the given prefix was recorded.
func (*MockExecutor) CommandCalled ¶ added in v1.98.0
func (m *MockExecutor) CommandCalled(nameAndArgs ...string) bool
CommandCalled returns true if a command matching the given name and args prefix was recorded.
func (*MockExecutor) CommandExists ¶
func (m *MockExecutor) CommandExists(name string) bool
func (*MockExecutor) DaemonReload ¶
func (m *MockExecutor) DaemonReload() error
func (*MockExecutor) FileExists ¶
func (m *MockExecutor) FileExists(path string) bool
func (*MockExecutor) Getenv ¶
func (m *MockExecutor) Getenv(key string) string
func (*MockExecutor) GroupExists ¶
func (m *MockExecutor) GroupExists(name string) bool
func (*MockExecutor) NftAddElement ¶
func (m *MockExecutor) NftAddElement(family, table, set string, element string) error
func (*MockExecutor) NftCheck ¶
func (m *MockExecutor) NftCheck(_ string) error
func (*MockExecutor) NftDeleteTable ¶
func (m *MockExecutor) NftDeleteTable(family, table string) error
func (*MockExecutor) NftListSet ¶
func (m *MockExecutor) NftListSet(family, table, set string) (string, error)
func (*MockExecutor) NftTableExists ¶
func (m *MockExecutor) NftTableExists(family, table string) bool
func (*MockExecutor) OnCommand ¶ added in v1.98.0
func (m *MockExecutor) OnCommand(fn func(), name string, args ...string)
OnCommand registers a callback that fires when a specific command is executed. Use for simulating side-effects (e.g., fixing a service state after permissions enforce).
func (*MockExecutor) Remove ¶
func (m *MockExecutor) Remove(path string) error
func (*MockExecutor) Rename ¶ added in v1.100.4
func (m *MockExecutor) Rename(oldpath, newpath string) error
Rename simulates atomic rename in the mock's in-memory file map and records a "rename" command for trace assertions. Returns m.RenameErr (nil by default); when non-nil, the file map is left unchanged (matching real-world atomic-rename failure semantics). PR-26-code-B addition.
func (*MockExecutor) RunContext ¶
func (*MockExecutor) RunTimeout ¶
func (*MockExecutor) ServiceActive ¶
func (m *MockExecutor) ServiceActive(unit string) bool
func (*MockExecutor) ServiceDisable ¶
func (m *MockExecutor) ServiceDisable(unit string) error
func (*MockExecutor) ServiceEnable ¶
func (m *MockExecutor) ServiceEnable(unit string) error
func (*MockExecutor) ServiceMask ¶
func (m *MockExecutor) ServiceMask(unit string) error
func (*MockExecutor) ServiceStart ¶
func (m *MockExecutor) ServiceStart(unit string) error
func (*MockExecutor) ServiceStop ¶
func (m *MockExecutor) ServiceStop(unit string) error
func (*MockExecutor) ServiceUnmask ¶ added in v1.100.4
func (m *MockExecutor) ServiceUnmask(unit string) error
ServiceUnmask records a systemctl unmask call and returns m.ServiceUnmaskErr (nil by default). Mirrors ServiceMask semantics for parity. PR-26-code-B addition.
func (*MockExecutor) Stat ¶ added in v1.100.4
func (m *MockExecutor) Stat(path string) (FileMeta, error)
Stat returns FileMeta from FileStats if explicitly set; otherwise synthesizes a default-mode (0644 root:root) entry with Size derived from the in-memory content. Returns os.ErrNotExist if neither FileStats nor Files contains the path. PR-26-code-C addition.
func (*MockExecutor) Symlink ¶
func (m *MockExecutor) Symlink(_, _ string) error
func (*MockExecutor) UserExists ¶
func (m *MockExecutor) UserExists(name string) bool
func (*MockExecutor) WriteFileAtomic ¶
type RealExecutor ¶
type RealExecutor struct{}
RealExecutor implements Executor using real system calls.
func (*RealExecutor) CommandExists ¶
func (r *RealExecutor) CommandExists(name string) bool
func (*RealExecutor) DaemonReload ¶
func (r *RealExecutor) DaemonReload() error
func (*RealExecutor) FileExists ¶
func (r *RealExecutor) FileExists(path string) bool
func (*RealExecutor) Getenv ¶
func (r *RealExecutor) Getenv(key string) string
func (*RealExecutor) GroupExists ¶
func (r *RealExecutor) GroupExists(name string) bool
func (*RealExecutor) MkdirAll ¶
func (r *RealExecutor) MkdirAll(path string, perm os.FileMode) error
func (*RealExecutor) NftAddElement ¶
func (r *RealExecutor) NftAddElement(family, table, set string, element string) error
func (*RealExecutor) NftCheck ¶
func (r *RealExecutor) NftCheck(configContent string) error
func (*RealExecutor) NftDeleteTable ¶
func (r *RealExecutor) NftDeleteTable(family, table string) error
func (*RealExecutor) NftListSet ¶
func (r *RealExecutor) NftListSet(family, table, set string) (string, error)
func (*RealExecutor) NftTableExists ¶
func (r *RealExecutor) NftTableExists(family, table string) bool
func (*RealExecutor) Remove ¶
func (r *RealExecutor) Remove(path string) error
func (*RealExecutor) Rename ¶ added in v1.100.4
func (r *RealExecutor) Rename(oldpath, newpath string) error
Rename atomically renames oldpath to newpath via os.Rename. Same- filesystem semantics; cross-filesystem renames will return an error per the os.Rename contract (the caller must ensure same-FS).
Added in PR-26-code-B per §43.2: replaces the prior Run("mv", ...) indirection used by restore_deps_csf.go's A.3 step. Routing through os.Rename (rather than shelling to mv) avoids a process spawn and gives a typed error path consistent with WriteFileAtomic.
func (*RealExecutor) RunContext ¶
func (*RealExecutor) RunTimeout ¶
func (*RealExecutor) ServiceActive ¶
func (r *RealExecutor) ServiceActive(unit string) bool
func (*RealExecutor) ServiceDisable ¶
func (r *RealExecutor) ServiceDisable(unit string) error
func (*RealExecutor) ServiceEnable ¶
func (r *RealExecutor) ServiceEnable(unit string) error
func (*RealExecutor) ServiceMask ¶
func (r *RealExecutor) ServiceMask(unit string) error
func (*RealExecutor) ServiceStart ¶
func (r *RealExecutor) ServiceStart(unit string) error
func (*RealExecutor) ServiceStop ¶
func (r *RealExecutor) ServiceStop(unit string) error
func (*RealExecutor) ServiceUnmask ¶ added in v1.100.4
func (r *RealExecutor) ServiceUnmask(unit string) error
func (*RealExecutor) Stat ¶ added in v1.100.4
func (r *RealExecutor) Stat(path string) (FileMeta, error)
Stat returns FileMeta (mode/uid/gid/size) via os.Stat + syscall.Stat_t. Read-only introspection. Added in PR-26-code-C for the CSF cron-backup manifest writer + reader.
On non-POSIX hosts (Windows), uid/gid extraction would not work as written; the production target is Linux only, so this is acceptable.
func (*RealExecutor) Symlink ¶
func (r *RealExecutor) Symlink(oldname, newname string) error
func (*RealExecutor) UserExists ¶
func (r *RealExecutor) UserExists(name string) bool
func (*RealExecutor) WriteFileAtomic ¶
type RecordedCommand ¶
RecordedCommand tracks a command that was executed.