terminal

package
v0.2.5 Latest Latest
Warning

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

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

Documentation

Overview

Package terminal — adapter.go provides ManagerAdapter which bridges terminal.Manager to the api.TerminalManager interface.

Package terminal manages interactive terminal sessions inside Docker containers. It provides a Manager that creates exec-based PTY sessions with ring-buffered output, and supports attach/detach, input, resize, and stop operations.

Index

Constants

This section is empty.

Variables

View Source
var ErrClientNotFound = errors.New("client not found")

ErrClientNotFound is returned when a detach is attempted with an unrecognized client channel.

View Source
var ErrSessionNotFound = errors.New("session not found")

ErrSessionNotFound is returned when a session ID is not recognized.

Functions

This section is empty.

Types

type DockerExecClient

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

DockerExecClient implements ExecClient using the Docker SDK. It wraps the Docker exec API (docker exec) to create interactive processes inside running containers. This is separate from container.Client which handles container lifecycle (docker create/start/stop/rm).

func NewDockerExecClient

func NewDockerExecClient() (*DockerExecClient, error)

NewDockerExecClient creates a new DockerExecClient backed by the Docker SDK.

func (*DockerExecClient) ExecAttach added in v0.2.0

func (c *DockerExecClient) ExecAttach(ctx context.Context, execID string) (io.ReadWriteCloser, error)

ExecAttach attaches to an exec process and returns an io.ReadWriteCloser over the hijacked connection.

func (*DockerExecClient) ExecCreate added in v0.2.0

func (c *DockerExecClient) ExecCreate(ctx context.Context, containerID string, cmd []string, tty bool) (string, error)

ExecCreate creates a new exec process in the container with the given command and TTY setting. The exec runs as the host user (matching the container's non-root agent user created by the entrypoint). If cmd is empty, defaults to /bin/sh.

func (*DockerExecClient) ExecResize added in v0.2.0

func (c *DockerExecClient) ExecResize(ctx context.Context, execID string, height, width uint) error

ExecResize changes the PTY dimensions of the exec process.

type ExecClient

type ExecClient interface {
	ExecCreate(ctx context.Context, targetID string, cmd []string, tty bool) (string, error)
	ExecAttach(ctx context.Context, execID string) (io.ReadWriteCloser, error)
	ExecResize(ctx context.Context, execID string, height, width uint) error
}

ExecClient abstracts the Docker exec operations needed by the terminal manager (docker exec), making it testable without a real Docker daemon.

This is distinct from container.DockerClient, which handles container lifecycle (docker create/start/stop/rm). ExecClient runs commands inside already-running containers for interactive PTY sessions.

type HostExecClient added in v0.2.0

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

HostExecClient implements ExecClient for running shell commands directly on the host machine. On Unix it uses creack/pty; on Windows it uses ConPTY. The containerID parameter in ExecCreate is repurposed as the working directory.

func NewHostExecClient added in v0.2.0

func NewHostExecClient() *HostExecClient

NewHostExecClient creates a new HostExecClient.

func (*HostExecClient) ExecAttach added in v0.2.0

func (c *HostExecClient) ExecAttach(_ context.Context, execID string) (io.ReadWriteCloser, error)

ExecAttach starts the exec process with a PTY and returns a ReadWriteCloser wrapping the PTY file descriptor. Close sends SIGHUP to the process group, waits briefly, then SIGKILL.

func (*HostExecClient) ExecCreate added in v0.2.0

func (c *HostExecClient) ExecCreate(_ context.Context, dirPath string, cmd []string, _ bool) (string, error)

ExecCreate creates a new exec process. The dirPath parameter is used as the working directory. The process is not started until ExecAttach is called.

func (*HostExecClient) ExecResize added in v0.2.0

func (c *HostExecClient) ExecResize(_ context.Context, execID string, height, width uint) error

ExecResize changes the PTY dimensions of the exec process.

type Manager

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

Manager manages terminal sessions.

func NewManager

func NewManager(client ExecClient, logger *slog.Logger) *Manager

NewManager creates a new terminal session manager.

func (*Manager) CreateSession

func (m *Manager) CreateSession(ctx context.Context, containerID string, cmd []string) (*Session, error)

CreateSession starts a new interactive terminal session by creating a Docker exec with a PTY, attaching to it, and starting the read loop. If cmd is empty, the ExecClient decides the default shell.

func (*Manager) GetSession

func (m *Manager) GetSession(id string) (*Session, error)

GetSession returns the session with the given ID.

func (*Manager) ListSessions

func (m *Manager) ListSessions() []string

ListSessions returns all active session IDs.

func (*Manager) Resize

func (m *Manager) Resize(ctx context.Context, id string, rows, cols uint) error

Resize changes the PTY dimensions of a session.

func (*Manager) SendInput

func (m *Manager) SendInput(id string, data []byte) error

SendInput writes raw bytes to the session's PTY stdin.

func (*Manager) SetIdleTimeout

func (m *Manager) SetIdleTimeout(d time.Duration)

SetIdleTimeout sets the idle timeout for new sessions. Sessions that receive no output within this duration are automatically closed. A zero value disables the timeout.

func (*Manager) SetRingBufSize

func (m *Manager) SetRingBufSize(size int)

SetRingBufSize sets the ring buffer size for new sessions.

func (*Manager) StopSession

func (m *Manager) StopSession(id string) (string, error)

StopSession closes the exec connection and removes the session. It returns the container ID the session was running in.

type ManagerAdapter

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

ManagerAdapter wraps a terminal.Manager to satisfy the api.TerminalManager interface expected by the WebSocket handler.

func NewManagerAdapter

func NewManagerAdapter(mgr *Manager) *ManagerAdapter

NewManagerAdapter creates a new adapter around the given Manager.

func (*ManagerAdapter) AttachSession

func (a *ManagerAdapter) AttachSession(sessionID string) (<-chan []byte, []byte, <-chan struct{}, error)

AttachSession re-attaches to an existing session.

func (*ManagerAdapter) CreateSession

func (a *ManagerAdapter) CreateSession(ctx context.Context, containerID string, cmd []string) (string, <-chan []byte, []byte, <-chan struct{}, error)

CreateSession creates a PTY session and immediately attaches a client channel, returning the decomposed session fields.

func (*ManagerAdapter) DetachSession

func (a *ManagerAdapter) DetachSession(sessionID string, output <-chan []byte) error

DetachSession detaches a client channel from a session.

func (*ManagerAdapter) Resize

func (a *ManagerAdapter) Resize(ctx context.Context, sessionID string, rows, cols uint) error

Resize changes the PTY dimensions of a session.

func (*ManagerAdapter) SendInput

func (a *ManagerAdapter) SendInput(sessionID string, data []byte) error

SendInput writes raw bytes to the session's PTY stdin.

func (*ManagerAdapter) StopSession

func (a *ManagerAdapter) StopSession(sessionID string) (string, error)

StopSession closes the exec connection and removes the session. Returns the container ID the session was running in.

type RingBuffer

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

RingBuffer is a fixed-size circular byte buffer that is safe for concurrent use. When full, new writes overwrite the oldest data.

func NewRingBuffer

func NewRingBuffer(size int) *RingBuffer

NewRingBuffer creates a ring buffer with the given capacity in bytes.

func (*RingBuffer) Bytes

func (r *RingBuffer) Bytes() []byte

Bytes returns a copy of the buffered data in chronological order.

func (*RingBuffer) Len

func (r *RingBuffer) Len() int

Len returns the number of bytes currently stored.

func (*RingBuffer) Reset

func (r *RingBuffer) Reset()

Reset clears the buffer.

func (*RingBuffer) Write

func (r *RingBuffer) Write(p []byte) (int, error)

Write appends data to the ring buffer, overwriting oldest data if full.

type Session

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

Session represents a single interactive terminal session backed by a Docker exec instance with a PTY.

func (*Session) Attach

func (s *Session) Attach() (<-chan []byte, []byte)

Attach registers a new client channel that receives a copy of all subsequent output. The caller receives the current ring buffer contents followed by a live stream. Close the returned channel by calling Detach.

func (*Session) ContainerID

func (s *Session) ContainerID() string

ContainerID returns the container this session runs in.

func (*Session) Detach

func (s *Session) Detach(ch <-chan []byte) error

Detach removes a previously attached client channel.

func (*Session) Done

func (s *Session) Done() <-chan struct{}

Done returns a channel that is closed when the session ends.

func (*Session) ID

func (s *Session) ID() string

ID returns the session identifier.

Jump to

Keyboard shortcuts

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