Documentation
¶
Overview ¶
Package agent implements hope's remote-host model. A hope-agent runs on a remote Docker host and dials OUT to a hope hub (so the remote needs only outbound access — no inbound ports, no VPN). Over that single connection it multiplexes (yamux) the host's Docker socket back to hope: hope opens a stream per Docker request and the agent proxies each to the local daemon. So hope's entire existing Docker layer works against the remote host unchanged.
Index ¶
- Constants
- func Run(ctx context.Context, opts Options) error
- type AgentInfo
- type FrontServer
- type Host
- type HostInfo
- type Hub
- func (h *Hub) DialContainer(hostID, addr string) (net.Conn, error)
- func (h *Hub) Listen(ctx context.Context, addr string) error
- func (h *Hub) OnConnect(fn func(ctx context.Context, host *Host))
- func (h *Hub) Registry() *Registry
- func (h *Hub) ServeWS(ctx context.Context) http.HandlerFunc
- func (h *Hub) SetBus(bus *events.Bus)
- func (h *Hub) SetReverseTarget(addr string)
- type Logger
- type Options
- type Registry
Constants ¶
const ReversePort = 8790
ReversePort is the port the agent listens on (inside its container) for a co-located plugin's reverse-channel HTTP, reachable by the agent's container id once hope attaches the agent to the ink-plugins network. Shared by the agent listener and the callback URL hope hands an agent-hosted plugin.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type AgentInfo ¶
type AgentInfo struct {
Version string `json:"version"`
Revision string `json:"revision"`
GoVersion string `json:"go_version"`
Platform string `json:"platform"`
BuildTime string `json:"build_time"`
ContainerID string `json:"container_id"` // the agent's own container id (for self-recreate)
}
AgentInfo is the remote agent's build metadata, reported in the handshake.
type FrontServer ¶
type FrontServer struct {
// contains filtered or unexported fields
}
FrontServer is a sov gateway.Server that fronts hope's HTTP listener so the agent tunnel can ride the SAME port as the UI/API (so it traverses Cloudflare on 443 with no extra port). It claims one path for the WebSocket tunnel and hands every other request to sov's dispatch untouched.
The non-tunnel bridge mirrors sov's default NetHTTPServer: a 4 MiB body cap, stripping inbound X-Sov-* identity headers (hope faces the public internet, so it must not trust smuggled identity claims), and streaming responses with a per-chunk flush and no write deadline.
func NewFrontServer ¶
func NewFrontServer(hub *Hub, wsPath string) *FrontServer
NewFrontServer returns a Server that serves the agent WebSocket at wsPath and forwards everything else to the gateway.
func (*FrontServer) Handle ¶
func (s *FrontServer) Handle(h gateway.RequestHandler)
Handle records the gateway's request handler (sov calls this once at boot).
func (*FrontServer) ListenAndServe ¶
func (s *FrontServer) ListenAndServe(ctx context.Context, addr string) error
ListenAndServe binds addr and serves until ctx is cancelled.
type Host ¶
type Host struct {
ID string
Docker *docker.Client
Remote string
ConnectedAt time.Time
Info AgentInfo
// contains filtered or unexported fields
}
Host is a connected remote Docker host, exposed to hope as a normal docker.Client that happens to run over the agent tunnel.
type HostInfo ¶
type HostInfo struct {
ID string `json:"id"`
Remote string `json:"remote"`
ConnectedAt time.Time `json:"connected_at"`
Info AgentInfo `json:"info"`
}
HostInfo is the frontend-facing summary of a connected agent.
type Hub ¶
type Hub struct {
// contains filtered or unexported fields
}
Hub accepts agent connections and registers each as a Host.
func NewHub ¶
NewHub builds a hub. token is the shared enrollment secret; configPath is the docker config.json for registry creds applied to remote pulls.
func (*Hub) DialContainer ¶
DialContainer opens a stream to a connected host's agent that connects to addr (ip:port) on that host, for reaching a plugin container over the tunnel.
func (*Hub) OnConnect ¶
OnConnect registers a callback run for each agent once it's online, with a context cancelled when that agent disconnects. hope uses it to start the host's background jobs (registry creds, update + disk crawlers) so a remote host gets the same periodic work as the local daemon.
func (*Hub) ServeWS ¶
func (h *Hub) ServeWS(ctx context.Context) http.HandlerFunc
ServeWS upgrades an HTTP request to a WebSocket and runs the agent tunnel over it, so the agent can reach the hub on hope's main HTTPS port (through Cloudflare) with no extra port. Cloudflare Access auth (service token or a bypass policy) is enforced at the edge before the request arrives; the shared token in the handshake is the second factor. ctx bounds the tunnel lifetime.
func (*Hub) SetBus ¶
SetBus wires the event bus after construction (the hub is built before the bus in serve.go). Safe to leave unset — publishing on a nil bus is a no-op.
func (*Hub) SetReverseTarget ¶
SetReverseTarget wires hope's own gateway address (loopback, e.g. 127.0.0.1:8080) that relayed plugin reverse-channel calls from agent-hosted plugins are piped to. Empty (unset) leaves the reverse-over-agent path off — the hub won't advertise the `reverse` capability, so agents stay co-located-only for the reverse channel.
type Logger ¶
type Logger interface {
Info(msg string, kv ...any)
Warn(msg string, kv ...any)
Error(msg string, kv ...any)
}
Logger is the small logging surface the agent/hub need (hope's logger fits).
type Options ¶
type Options struct {
// Connect is the hub endpoint. A ws://host/path or wss://host/path URL rides
// hope's main HTTPS port through Cloudflare (no extra port); a bare host:port
// or tcp://host:port uses a raw TCP hub listener (LAN/overlay).
Connect string
Token string // shared enrollment secret the hub checks
HostID string // stable id this host registers under
Docker string // local docker endpoint to expose (unix:// or tcp://)
// CFAccessClientID/Secret, when set, are sent as the Cloudflare Access
// service-token headers so the agent passes Access as a machine identity
// (leave empty if you instead bypass Access for the agent path).
CFAccessClientID string
CFAccessClientSecret string
Log Logger
}
Options configures a hope-agent.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry tracks the live agents. Safe for concurrent use.