Documentation
¶
Overview ¶
Package wsl lets a Windows-native `dejima` client drive a `dejimad` running inside a WSL2 distro.
Windows can't host Dejima: dejimad needs a Unix host with Docker (see scripts/setup.sh, which exits on anything but Darwin/Linux, and internal/service, which only knows launchd + systemd). WSL2 *is* such a host — a real Linux kernel with a real Docker — so a Windows user can run the whole stack locally after all, with the daemon one virtualization boundary away.
The transport is deliberately the cheapest thing that preserves the security model: we shell out to `wsl.exe -d <distro> -- socat STDIO UNIX-CONNECT:…` and wrap that process's stdio as a net.Conn. dejimad needs no new listener, no TCP bind, and no relaxation of the tailnet pin; its 0600 Unix socket remains the only operator surface, reachable exactly by whoever can already run commands as that user inside the distro.
A connection target for this path is spelled `wsl://<distro>` and is stored in a client profile like any other host.
Index ¶
- Constants
- Variables
- func Available() bool
- func Dial(ctx context.Context, distro string) (net.Conn, error)
- func DialTimeout() time.Duration
- func Distro(host string) string
- func Host(distro string) string
- func IsHost(host string) bool
- func Run(ctx context.Context, distro, script string) (string, error)
- func RunExe(ctx context.Context, args ...string) (string, error)
- func Supported() bool
- type Distribution
- type Report
Constants ¶
const DefaultDistro = "dejima"
DefaultDistro is the distro name `dejima wsl setup` creates and that the first-run flow offers. Named for the project so it's obvious in `wsl -l -v` and can't be confused with a distro the user keeps for other work.
const InstallHint = "wsl --install --no-distribution\n" +
" (older wsl.exe: wsl --install, reboot, then wsl --update)"
InstallHint is the exact command to install WSL, in ONE place because three user-facing sites print it and a fourth (the website) copies it. They had already drifted: the binary said `wsl --install` while the site said `--no-distribution`, so the same operator got two different instructions depending on where they read.
--no-distribution is the right one HERE, specifically. Plain `wsl --install` also downloads a default Ubuntu and puts a username/password prompt in front of the operator — a distro Dejima never uses, because `dejima wsl setup` creates its own (see createDistro). Telling someone to install a distro we then ignore costs a download, a reboot-time prompt, and the belief that the thing they set up is the thing we run.
The flag needs a reasonably recent wsl.exe. Where it is rejected, the fallback is the plain form, a reboot, and then `wsl --update` to get a wsl.exe new enough for everything after — d4 walked that path on a real box, which is why the update step is here rather than inferred.
The update step lives in THIS constant rather than only on the website because d5 asserts the page's command block is a substring of this string, read out of this file at check time. A step that exists only on the page is invisible to that check and can drift silently — which is the whole failure this constant was created to end.
const Scheme = "wsl://"
Scheme prefixes a WSL connection target: "wsl://dejima".
Variables ¶
var ErrUnsupported = errors.New("wsl:// targets work only on Windows (WSL interop); use a host:port address here")
ErrUnsupported is returned when a `wsl://` target is used off Windows.
Functions ¶
func Available ¶
func Available() bool
Available reports whether WSL interop is usable at all: Windows, with wsl.exe on PATH.
func Dial ¶
Dial opens a connection to dejimad's Unix socket inside distro by piping through `wsl.exe … socat`. The returned conn owns the subprocess and kills it on Close.
ctx bounds the *handshake* (spawning wsl.exe), not the connection's lifetime: http.Transport pools connections past the request whose context triggered the dial, so binding the process to that context would kill live pooled conns.
func DialTimeout ¶
DialTimeout is the handshake budget callers should use when building a transport for this path.
func Distro ¶
Distro extracts the distro name from a `wsl://<distro>` host, or "" if host isn't a WSL target. A bare "wsl://" yields DefaultDistro so the shorthand works.
func IsHost ¶
IsHost reports whether a connection host names a WSL distro rather than a TCP address.
func Run ¶
Run is run() exported for the setup flow, which needs to execute provisioning steps inside the distro and show their output.
func RunExe ¶
RunExe invokes wsl.exe with *management* arguments (--install, --set-version, …) rather than a command inside a distro. It returns the combined output even on failure so callers can classify the error (e.g. an old wsl.exe that lacks a flag), and streams nothing — these operations are slow but quiet.
Types ¶
type Distribution ¶
type Distribution struct {
Name string
State string // "Running" / "Stopped"
Version int // 1 or 2; only 2 has a real kernel + Docker
Default bool
}
Distribution is one entry from `wsl.exe -l -v`.
type Report ¶
type Report struct {
Distro string
Exists bool
Version int
Running bool
HasSocat bool
HasDocker bool // docker CLI present AND the engine answers
HasDejima bool // dejimad binary installed
SocketUp bool // ~/.dejima/dejimad.sock exists
}
Report is a health read of one distro as a Dejima host.