Help us shape the future of Go! Take the 2026 Go Developer Survey

agent

package
v1.25.0-beta.6 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2026 License: MPL-2.0 Imports: 31 Imported by: 0

Documentation

Index

Constants

View Source
const ContainerDaemonConfigPath = "/var/run/secrets/" + config.BinaryName + "/daemon_config"
View Source
const (
	DefaultActivityInterval = 10 * time.Second
)
View Source
const (

	// LifecycleOwnerManagedDaemon marks a container whose main process is the
	// Devsy daemon and owns inactivity shutdown.
	LifecycleOwnerManagedDaemon = "managedDaemon"
)
View Source
const (
	LifecycleProtocolVersion = 3
)

Variables

View Source
var (
	ErrLifecycleOwnerMissing = errors.New(
		"container lifecycle owner unavailable; stop and start the workspace to replace its pod",
	)
	ErrLifecycleNotAcknowledged = errors.New(
		"container lifecycle owner did not acknowledge the update",
	)
	ErrLifecycleOwnerIncompatible = errors.New(
		"container lifecycle owner is incompatible; stop and start the workspace to replace its pod",
	)
)
View Source
var ErrInactivityExpired = errors.New("inactivity timeout reached")

ErrInactivityExpired is returned by the lifecycle loop when the idle timeout elapsed. It is the normal way a managed container asks to stop.

Functions

func AgentHomeStateRoot added in v1.20.0

func AgentHomeStateRoot(origin, contextName, workspaceID string) (string, error)

AgentHomeStateRoot derives the agent home from a workspace origin created by a container-side agent invocation.

func CanonicalStateRoot added in v1.20.0

func CanonicalStateRoot(origin, contextName, workspaceID string) (string, error)

CanonicalStateRoot derives the canonical data root from a persisted workspace origin while validating every structural component.

func DiagnosticsReaderIdentity added in v1.20.0

func DiagnosticsReaderIdentity() machinediagnostics.ReaderIdentity

DiagnosticsReaderIdentity captures the invoking user before systemd starts the daemon as root. SUDO_UID/GID identify the original user on sudo paths.

func EncodeDaemonConfig

func EncodeDaemonConfig(cfg *DaemonConfig) (string, error)

EncodeDaemonConfig is the inverse of DecodeDaemonConfig.

func FormatTimeout

func FormatTimeout(d time.Duration) string

FormatTimeout renders a timeout for DaemonConfig/ContainerWorkspaceInfo; zero is "".

func GetEncodedWorkspaceDaemonConfig

func GetEncodedWorkspaceDaemonConfig(
	platformOptions devsy.PlatformOptions,
	workspaceConfig *provider2.Workspace,
	substitutionContext *config.SubstitutionContext,
	mergedConfig *config.MergedDevContainerConfig,
	lifecycle LifecycleOptions,
) (string, error)

func InstallDaemon

func InstallDaemon(
	opts InstallOptions,
) error

func RefreshLifecycle

func RefreshLifecycle(
	encoded string,
	lifecycle LifecycleOptions,
	shutdownAction string,
) (string, error)

RefreshLifecycle rewrites the generated lifecycle policy of a stored encoded daemon config, leaving platform and SSH settings untouched. An empty stored config yields a minimal timeout-only config.

func RemoveDaemon

func RemoveDaemon() error

func ResolveInactivityTimeout

func ResolveInactivityTimeout(in TimeoutInputs) (time.Duration, error)

ResolveInactivityTimeout returns the single effective inactivity timeout for a managed container. Zero means disabled.

func RunProcessReaper

func RunProcessReaper(ctx context.Context)

RunProcessReaper reaps zombie child processes until ctx is cancelled. This is needed when running as PID 1 (e.g. in a container).

func StartActivityWriter

func StartActivityWriter(
	ctx context.Context,
	interval time.Duration,
) (context.Context, func(), error)

func TouchActivity

func TouchActivity(path string, now time.Time) error

Types

type AckRecord

type AckRecord struct {
	Version    int    `json:"version"`
	Generation string `json:"generation"`
	ClientID   string `json:"clientID"`
	Sequence   uint64 `json:"sequence"`
	Error      string `json:"error,omitempty"`
}

type ActivityWriter

type ActivityWriter struct {
	Path         string
	LifecycleDir string
	RequireOwner bool
	Interval     time.Duration
	Touch        func(string, time.Time) error
	Now          func() time.Time
	Tick         func(time.Duration) (<-chan time.Time, func())
}

ActivityWriter retains file heartbeats for non-managed daemons. Managed work is protected by its acknowledged connection, including when all writes fail.

func (ActivityWriter) Run

func (w ActivityWriter) Run(ctx context.Context)

Run records legacy file activity without claiming managed protection. Managed callers use Start so registration completes before their work begins.

func (ActivityWriter) Start

func (w ActivityWriter) Start(ctx context.Context) (context.Context, func(), error)

Start returns only after registering with any live managed owner. The caller must use workCtx and stop its work if that context is cancelled.

type ControlRecord

type ControlRecord struct {
	Version        int            `json:"version"`
	Generation     string         `json:"generation"`
	ClientID       string         `json:"clientID"`
	Sequence       uint64         `json:"sequence"`
	PID            int            `json:"pid"`
	StartTicks     string         `json:"startTicks,omitempty"`
	Timeout        string         `json:"timeout"`
	ShutdownAction string         `json:"shutdownAction"`
	State          LifecycleState `json:"state"`
}

ControlRecord belongs to one connection and operation. PID/start identity prevents inherited descriptors or PID reuse from orphaning setup protection.

type DaemonConfig

type DaemonConfig struct {
	Platform       devsy.PlatformOptions `json:"platform"`
	Ssh            SshConfig             `json:"ssh"`
	Timeout        string                `json:"timeout"`
	ShutdownAction string                `json:"shutdownAction,omitempty"`
	Lifecycle      LifecycleConfig       `json:"lifecycle,omitzero"`
}

func BuildWorkspaceDaemonConfig

func BuildWorkspaceDaemonConfig(
	platformOptions devsy.PlatformOptions,
	workspaceConfig *provider2.Workspace,
	substitutionContext *config.SubstitutionContext,
	mergedConfig *config.MergedDevContainerConfig,
	lifecycle LifecycleOptions,
) (*DaemonConfig, error)

func DecodeDaemonConfig

func DecodeDaemonConfig(encoded string) (*DaemonConfig, error)

DecodeDaemonConfig parses the base64 JSON produced by GetEncodedWorkspaceDaemonConfig.

func LoadContainerDaemonConfig

func LoadContainerDaemonConfig() (*DaemonConfig, error)

type Decision

type Decision struct {
	Expired            bool
	ActivityUnreadable bool
	Failures           int
}

Decision is the outcome of one inactivity check.

type InstallOptions added in v1.20.0

type InstallOptions struct {
	StateLocation     StateLocation
	Interval          string
	ShutdownAction    string
	DiagnosticsReader machinediagnostics.ReaderIdentity
}

type LifecycleClient

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

LifecycleClient never reconnects silently: losing protection cancels the work. A fresh operation must explicitly connect to the current owner instance.

func ConnectLifecycle

func ConnectLifecycle(ctx context.Context, dir string) (*LifecycleClient, error)

func (*LifecycleClient) Close

func (c *LifecycleClient) Close() error

func (*LifecycleClient) Done

func (c *LifecycleClient) Done() <-chan struct{}

func (*LifecycleClient) ProtectedContext

func (c *LifecycleClient) ProtectedContext(
	parent context.Context,
) (context.Context, context.CancelCauseFunc)

ProtectedContext aborts work on socket loss instead of leaving it untracked.

func (*LifecycleClient) Send

func (c *LifecycleClient) Send(
	state LifecycleState,
	timeout, shutdownAction string,
) (sendErr error)

Send retries the same operation while the connection survives. The owner's cached result makes acknowledgement recovery independent of applying state.

type LifecycleConfig

type LifecycleConfig struct {
	// Owner is LifecycleOwnerManagedDaemon when the daemon is the container's main
	// process and owns the timer.
	Owner string `json:"owner,omitempty"`
	// SetupArmsTimer means the daemon starts unarmed and container setup arms it.
	SetupArmsTimer bool `json:"setupArmsTimer,omitempty"`
}

LifecycleConfig tells the daemon who owns inactivity shutdown.

func (LifecycleConfig) Managed

func (l LifecycleConfig) Managed() bool

Managed reports whether the daemon owns the inactivity timer.

type LifecycleLoop

type LifecycleLoop struct {
	Owner        *LifecycleOwner
	Monitor      *LifecycleMonitor
	ActivityPath string
}

LifecycleLoop uses live registrations for managed containers and the legacy activity file only for daemons without a managed owner.

func (*LifecycleLoop) Run

func (l *LifecycleLoop) Run(ctx context.Context) error

type LifecycleMonitor

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

LifecycleMonitor serializes protection changes with the decision to stop.

func (*LifecycleMonitor) Apply

func (m *LifecycleMonitor) Apply(rec ControlRecord, now time.Time) (bool, error)

Apply changes one client's protection. Acknowledgements are sent only after this method returns; no filesystem write is needed to retain protection.

func (*LifecycleMonitor) ArmNow

func (m *LifecycleMonitor) ArmNow(timeout time.Duration, now time.Time)

ArmNow arms daemons that have no managed setup handshake.

func (*LifecycleMonitor) CheckInterval

func (m *LifecycleMonitor) CheckInterval() time.Duration

CheckInterval bounds the delay before observing idle time or process death.

func (*LifecycleMonitor) Evaluate

func (m *LifecycleMonitor) Evaluate(now, modTime time.Time, statErr error) Decision

Evaluate observes the timer without committing the daemon to shutdown.

func (*LifecycleMonitor) Release

func (m *LifecycleMonitor) Release(id string, now time.Time)

Release ends only this client's protection and starts a fresh idle interval.

type LifecycleOptions

type LifecycleOptions struct {
	// Managed marks the daemon as the container's main process and timer owner.
	Managed bool
	// Timeout is the effective inactivity timeout; zero disables it.
	Timeout time.Duration
}

LifecycleOptions are the explicit lifecycle inputs for building a daemon config.

func ResolveManagedLifecycle

func ResolveManagedLifecycle(
	timeout time.Duration,
	dockerless, imageEntrypoint bool,
) (LifecycleOptions, error)

ResolveManagedLifecycle selects ownership for a managed-capable driver's topology. Dockerless owns the pod process; its nested workspace cannot stop that pod.

type LifecycleOwner

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

LifecycleOwner keeps live work and applied operations in memory. Discovery and policy files are never evidence that a registered writer is healthy.

func NewLifecycleOwner

func NewLifecycleOwner(dir string) (*LifecycleOwner, error)

NewLifecycleOwner binds before publishing discovery. All subsequent safety decisions and acknowledgements use the connection, never writable files.

func (*LifecycleOwner) Close

func (o *LifecycleOwner) Close() error

func (*LifecycleOwner) Generation

func (o *LifecycleOwner) Generation() string

func (*LifecycleOwner) Serve

func (o *LifecycleOwner) Serve(ctx context.Context, monitor *LifecycleMonitor) error

type LifecycleState

type LifecycleState string
const (
	LifecycleStateSetup    LifecycleState = "setup"
	LifecycleStateReady    LifecycleState = "ready"
	LifecycleStateFailed   LifecycleState = "failed"
	LifecycleStateActivity LifecycleState = "activity"
	LifecycleStateRelease  LifecycleState = "release"
)

type OwnerRecord

type OwnerRecord struct {
	Version    int    `json:"version"`
	Generation string `json:"generation"`
	PID        int    `json:"pid"`
	StartTicks string `json:"startTicks,omitempty"`
}

OwnerRecord identifies the daemon instance, not a lease on work.

type ResolveStateLocationOptions added in v1.20.0

type ResolveStateLocationOptions struct {
	AgentDataPath string
	Origin        string
	Context       string
	WorkspaceID   string
}

type SshConfig

type SshConfig struct {
	Workdir string `json:"workdir,omitempty"`
	User    string `json:"user,omitempty"`
}

type StateLayout added in v1.20.0

type StateLayout string

StateLayout describes how machine workspace state is stored beneath Root.

const (
	StateLayoutCanonical StateLayout = "canonical"
	StateLayoutAgentHome StateLayout = "agent-home"
)

type StateLocation added in v1.20.0

type StateLocation struct {
	Root   string
	Layout StateLayout
}

StateLocation identifies the workspace state that an inactivity daemon owns.

func ResolveStateLocation added in v1.20.0

func ResolveStateLocation(opts ResolveStateLocationOptions) (StateLocation, error)

ResolveStateLocation captures the persisted state root at installation time, before the daemon is started by systemd under a potentially different user.

func (StateLocation) Validate added in v1.20.0

func (l StateLocation) Validate() error

func (StateLocation) WorkspaceConfigPattern added in v1.20.0

func (l StateLocation) WorkspaceConfigPattern() (string, error)

type TimeoutInputs

type TimeoutInputs struct {
	// Canonical is agent.containerInactivityTimeout.
	Canonical string
	// Legacy is agent.kubernetes.inactivityTimeout, used only when Canonical is empty.
	Legacy         string
	ShutdownAction string
	DisableDaemon  bool
}

TimeoutInputs are the configured values that decide the effective timeout.

Jump to

Keyboard shortcuts

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