exec

package
v0.1.7 Latest Latest
Warning

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

Go to latest
Published: Mar 19, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package exec implements the tailkitd exec integration: an in-memory registry of tool commands watched for live updates, a safe runner, a job store, and the HTTP handlers for POST /exec/{tool}/{cmd} and GET /exec/jobs/{id}.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ExecEntry

type ExecEntry struct {
	Tool    tailkit.Tool
	Command tailkit.Command
}

ExecEntry is a resolved, ready-to-run entry in the command registry. It pairs the Tool metadata with the specific Command so the runner has everything it needs without a second lookup.

type Handler

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

Handler holds the dependencies for the exec HTTP endpoints and exposes methods that return http.HandlerFunc values for registration on the mux.

func NewHandler

func NewHandler(registry *Registry, runner *Runner, jobs *JobStore, logger *zap.Logger) *Handler

NewHandler constructs an exec Handler.

func (*Handler) Register

func (h *Handler) Register(mux *http.ServeMux)

Register mounts the exec endpoints onto mux:

POST /exec/{tool}/{cmd}   — fire-and-forget, returns job_id immediately
GET  /exec/jobs/{id}      — poll a job for results

type JobStore

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

JobStore is an in-memory store for async job results. Jobs are evicted automatically after jobTTL (5 minutes). Concurrent access is safe.

func NewJobStore

func NewJobStore(logger *zap.Logger) *JobStore

NewJobStore constructs a JobStore and starts the background eviction goroutine. The goroutine exits when ctx is done — pass the same context as the server lifetime.

func (*JobStore) GetResult

func (s *JobStore) GetResult(id string) (tailkit.JobResult, bool)

GetResult retrieves a job result by ID. Returns (result, true) if the job exists (accepted, running, or completed). Returns (zero, false) if the job has been evicted or never existed.

func (*JobStore) NewJob

func (s *JobStore) NewJob() string

NewJob creates a new job entry with status "accepted" and returns its ID. The returned ID should be given to the caller immediately before the job runs.

func (*JobStore) StartEviction

func (s *JobStore) StartEviction(ctx interface{ Done() <-chan struct{} })

StartEviction begins the background eviction loop. Call once after construction. The loop exits when ctx is cancelled.

func (*JobStore) StoreResult

func (s *JobStore) StoreResult(id string, result tailkit.JobResult)

StoreResult replaces the job entry for id with the completed result. If id does not exist (evicted between acceptance and completion), the result is stored anyway — a late store is better than losing it.

type Registry

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

Registry maintains an in-memory index of all registered tool commands, keyed by "tool/command". It watches the tools directory with fsnotify and rebuilds the index automatically when files are created, modified, or deleted.

The index is rebuilt atomically — readers always see either the old or the new complete index, never a partial rebuild.

func NewRegistry

func NewRegistry(ctx context.Context, dir string, logger *zap.Logger) (*Registry, error)

NewRegistry constructs an exec Registry and performs an initial load from dir. It starts a background goroutine that watches dir with fsnotify and rebuilds the index on any change. The goroutine exits when ctx is cancelled.

func (*Registry) Commands

func (r *Registry) Commands(toolName string) []tailkit.Command

Commands returns all registered commands, grouped by tool name. Used by GET /tools to include exec-registered commands.

func (*Registry) Lookup

func (r *Registry) Lookup(toolName, cmdName string) (ExecEntry, bool)

Lookup finds an ExecEntry by tool and command name. Returns (entry, true) if found, (zero, false) if the tool or command is not registered.

type Runner

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

Runner executes registered commands safely. It validates caller-supplied args against declared patterns, substitutes them into ExecParts per-slot using text/template, and runs the resolved command with exec.CommandContext.

Invariant: the runner never joins ExecParts into a single string and splits it — substitution happens per-element so spaces inside arg values cannot be used to inject additional arguments.

func NewRunner

func NewRunner(logger *zap.Logger) *Runner

NewRunner constructs a Runner with the given logger.

func (*Runner) Run

func (r *Runner) Run(ctx context.Context, entry ExecEntry, args map[string]string) tailkit.JobResult

Run validates args, substitutes them into the command entry, and executes it. It always returns a JobResult — errors during execution are captured in the result rather than returned as Go errors, because the caller needs a serialisable result to store in the job store regardless of outcome.

The context carries the job timeout (set by the caller from Command.Timeout). Cancelling ctx kills the subprocess.

Jump to

Keyboard shortcuts

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