ClientUtils.Harness.Onboarding.Port (client_utils v0.1.35)
View SourceCalls an io: adapter — a module, or a module paired with the thing it acts on.
Why the names are what they are
These four operations are read_file/2, write_file/3, file_exists?/2 and
cmd/4 because that is CodeMySpec.Environments' contract, verbatim. A host
that already has a filesystem abstraction passes {ThatModule, its_handle}
and writes no adapter at all — CodeMySpec passes
{CodeMySpec.Environments, env}.
The port used to name them read/2, write/3, exists?/2, cmd/3 and take
a bare root, which had two consequences. A host with state could not use it:
CodeMySpec's specs drive a :memory environment holding an Agent pid in
ref, and no adapter given only a path can find that agent — so the single
case this port was justified by ("CodeMySpec passes an adapter over its own
Environments", written into c570d32 as though it were already true) was
the one it could not serve, and CodeMySpec kept a second implementation of
onboard/2 and check/2 instead. And a host without state still had to write
a translation module whose whole content was renaming read to read_file.
Naming the port after an interface a caller already implements costs this
library nothing — its own FileIO is the only other implementation and it is
ours to shape — and costs the caller nothing at all, which is the point.
The shapes
{module, state}—module.read_file(state, path). The state is opaque here; it is whatever the host needs and is passed straight back.module—module.read_file(root, path). The root is the state, which is allFileIOhas ever needed.
A generated application passes neither and gets FileIO.
Summary
Functions
Restrict a file this run just wrote, where the adapter can.
The module an adapter dispatches to.
Types
Functions
@spec chmod(t(), String.t(), String.t(), non_neg_integer()) :: :ok
Restrict a file this run just wrote, where the adapter can.
Optional, and silently skipped by an adapter that does not implement it. Two
of the three cannot honour it meaningfully: a host writing through a channel
to another machine, and an in-memory adapter, have no local inode to restrict.
FileIO does, and .cms_harness.json holds a deploy key once one is
recorded — git ignores that file, which keeps it out of the repository, and
this keeps it out of the other accounts on the machine.
Never load-bearing. A copy whose mode could not be set is still onboarded, and saying so would be noise on every adapter that legitimately has nothing to do.
The module an adapter dispatches to.
Exposed so a host can assert the adapter it passed is the one being called — the check whose absence let this port go unused for a week while its own documentation said otherwise.